From 6e4a39ad532dd13bc6cc6413f49ad6f37002c94e Mon Sep 17 00:00:00 2001 From: Isa Nanic <isa.nanic@savoirfairelinux.com> Date: Tue, 4 Dec 2018 14:26:02 -0500 Subject: [PATCH] new lrc: refactor settings page, ui overhaul Change-Id: I7eac9e025a3c1281b0ba98515dc77f65c36fc178 Reviewed-by: Andreas Traczyk <andreas.traczyk@savoirfairelinux.com> --- RingWinClient.pro | 8 +- accountdetails.cpp | 2 +- advancedsettingswidget.cpp | 419 +++ advancedsettingswidget.h | 89 + advancedsettingswidget.ui | 1082 +++++++ avatargraphicsview.cpp | 59 + avatargraphicsview.h | 41 + bannedlistmodel.cpp | 40 + bannedlistmodel.h | 33 + callwidget.cpp | 14 +- callwidget.h | 4 + callwidget.ui | 26 + configurationwidget.cpp | 18 +- configurationwidget.ui | 2 +- conversationitemdelegate.cpp | 2 +- copy-runtime-files.ps1 | 2 + currentaccountcombobox.cpp | 19 +- currentaccountcombobox.h | 4 +- deleteaccountdialog.cpp | 43 +- deleteaccountdialog.h | 13 +- deleteaccountdialog.ui | 164 +- deviceeditwidget.ui | 42 + images/ajax-loader.gif | Bin 0 -> 673 bytes images/icons/round-add-24px.svg | 1 + images/icons/round-arrow_drop_down-24px.svg | 1 + images/icons/round-arrow_drop_up-24px.svg | 1 + images/icons/round-arrow_right-24px.svg | 1 + images/icons/round-check_circle-24px.svg | 1 + images/icons/round-close-24px.svg | 1 + images/icons/round-edit-24px.svg | 1 + images/icons/round-error-24px.svg | 1 + images/icons/round-folder-24px.svg | 1 + images/icons/round-remove_circle-24px.svg | 1 + images/icons/round-save_alt-24px.svg | 1 + images/icons/round-undo-24px.svg | 1 + invitebuttonswidget.ui | 2 +- linkdevwidget.cpp | 80 + linkdevwidget.h | 49 + linkdevwidget.ui | 611 ++++ lrcinstance.h | 59 +- mainwindow.cpp | 9 +- mainwindow.ui | 1 + navwidget.h | 1 + passworddialog.cpp | 108 + passworddialog.h | 44 + passworddialog.ui | 205 ++ photoboothdialog.ui | 4 +- regnamedialog.cpp | 46 + regnamedialog.h | 37 + regnamedialog.ui | 119 + ressources.qrc | 134 +- ring-client-windows.sln | 116 +- ring-client-windows.vcxproj | 66 +- ring-client-windows.vcxproj.filters | 78 + ringthemeutils.h | 2 + ringtones/Makefile.am | 5 + ringtones/default.opus | Bin 0 -> 22089 bytes ringtones/default.opus.LICENSE | 4 + ringtones/default.wav | Bin 0 -> 56472 bytes ringtones/default.wav.LICENSE | 4 + ringtones/konga.ul | 11 + setavatardialog.cpp | 224 ++ setavatardialog.h | 82 + setavatardialog.ui | 226 ++ settingsitemwidget.cpp | 134 + settingsitemwidget.h | 50 + settingswidget.cpp | 926 ++++++ settingswidget.h | 158 ++ settingswidget.ui | 2820 +++++++++++++++++++ smartlistmodel.h | 1 - smartlistview.h | 1 - stylesheet.css | 27 +- utils.cpp | 1 - 73 files changed, 8355 insertions(+), 228 deletions(-) create mode 100644 advancedsettingswidget.cpp create mode 100644 advancedsettingswidget.h create mode 100644 advancedsettingswidget.ui create mode 100644 avatargraphicsview.cpp create mode 100644 avatargraphicsview.h create mode 100644 bannedlistmodel.cpp create mode 100644 bannedlistmodel.h create mode 100644 deviceeditwidget.ui create mode 100644 images/ajax-loader.gif create mode 100644 images/icons/round-add-24px.svg create mode 100644 images/icons/round-arrow_drop_down-24px.svg create mode 100644 images/icons/round-arrow_drop_up-24px.svg create mode 100644 images/icons/round-arrow_right-24px.svg create mode 100644 images/icons/round-check_circle-24px.svg create mode 100644 images/icons/round-close-24px.svg create mode 100644 images/icons/round-edit-24px.svg create mode 100644 images/icons/round-error-24px.svg create mode 100644 images/icons/round-folder-24px.svg create mode 100644 images/icons/round-remove_circle-24px.svg create mode 100644 images/icons/round-save_alt-24px.svg create mode 100644 images/icons/round-undo-24px.svg create mode 100644 linkdevwidget.cpp create mode 100644 linkdevwidget.h create mode 100644 linkdevwidget.ui create mode 100644 passworddialog.cpp create mode 100644 passworddialog.h create mode 100644 passworddialog.ui create mode 100644 regnamedialog.cpp create mode 100644 regnamedialog.h create mode 100644 regnamedialog.ui create mode 100644 ringtones/Makefile.am create mode 100644 ringtones/default.opus create mode 100644 ringtones/default.opus.LICENSE create mode 100644 ringtones/default.wav create mode 100644 ringtones/default.wav.LICENSE create mode 100644 ringtones/konga.ul create mode 100644 setavatardialog.cpp create mode 100644 setavatardialog.h create mode 100644 setavatardialog.ui create mode 100644 settingsitemwidget.cpp create mode 100644 settingsitemwidget.h create mode 100644 settingswidget.cpp create mode 100644 settingswidget.h create mode 100644 settingswidget.ui diff --git a/RingWinClient.pro b/RingWinClient.pro index 735b90d..c4a06d8 100644 --- a/RingWinClient.pro +++ b/RingWinClient.pro @@ -80,11 +80,11 @@ SOURCES += main.cpp\ invitebuttonswidget.cpp \ wizardwidget.cpp \ currentaccountcombobox.cpp \ - conversationfilterbutton.cpp \ messagewebpage.cpp \ messagewebview.cpp \ webchathelpers.cpp \ - animationhelpers.cpp + animationhelpers.cpp \ + settingsitemwidget.cpp HEADERS += mainwindow.h \ callwidget.h \ @@ -128,11 +128,11 @@ HEADERS += mainwindow.h \ invitebuttonswidget.h \ wizardwidget.h \ currentaccountcombobox.h \ - conversationfilterbutton.h \ messagewebpage.h \ messagewebview.h \ webchathelpers.h \ - animationhelpers.h + animationhelpers.h \ + settingsitemwidget.h contains(DEFINES, URI_PROTOCOL) { diff --git a/accountdetails.cpp b/accountdetails.cpp index fed1d3a..ee95a82 100644 --- a/accountdetails.cpp +++ b/accountdetails.cpp @@ -157,7 +157,7 @@ AccountDetails::setAccount(Account* currentAccount) { if (not currentAccount_->tlsPrivateKey().isEmpty()) ui->lrcfg_tlsPrivateKeyCertificate->setText(currentAccount_->tlsPrivateKey()); -#if defined(Q_OS_WIN) && !defined(_MSC_VER) +#if defined(Q_OS_WIN) && !defined(_MSC_VER) certMap_[ui->lrcfg_tlsCaListCertificate->objectName()] = ¤tAccount_->setTlsCaListCertificate; certMap_[ui->lrcfg_tlsCertificate->objectName()] = ¤tAccount_->setTlsCertificate; certMap_[ui->lrcfg_tlsPrivateKeyCertificate->objectName()] = ¤tAccount_->setTlsPrivateKey; diff --git a/advancedsettingswidget.cpp b/advancedsettingswidget.cpp new file mode 100644 index 0000000..8ef915f --- /dev/null +++ b/advancedsettingswidget.cpp @@ -0,0 +1,419 @@ +/*************************************************************************** + * Copyright (C) 2018 by Savoir-faire Linux * + * Author: Isa Nanic <isa.nanic@savoirfairelinux.com> * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 3 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program. If not, see <http://www.gnu.org/licenses/>. * + **************************************************************************/ +#include "direct.h" +#include <QFileDialog> + +#include "lrcinstance.h" +#include "api/newcodecmodel.h" + +#include "advancedsettingswidget.h" +#include "ui_advancedsettingswidget.h" + +AdvancedSettingsWidget::AdvancedSettingsWidget(QWidget* parent) + :QWidget(parent), + ui(new Ui::AdvancedSettingsWidget) +{ + ui->setupUi(this); + + updateAdvancedSettings(); +/////////////////////////////////////////////////////////////////////////////// + // call settings + connect(ui->checkBoxUntrusted, &QCheckBox::stateChanged, this, &AdvancedSettingsWidget::setCallsUntrusted); + connect(ui->checkBoxCustomRingtone, &QCheckBox::stateChanged, this, &AdvancedSettingsWidget::setEnableRingtone); + connect(ui->checkBoxAutoAnswer, &QCheckBox::stateChanged, this, &AdvancedSettingsWidget::setAutoAnswerCalls); + connect(ui->btnRingtone, &QPushButton::clicked, this, &AdvancedSettingsWidget::openFileCustomRingtone); + connect(ui->checkBoxCustomRingtone, &QCheckBox::stateChanged, [this](int state) { ui->btnRingtone->setEnabled((bool)state); }); + + // name server + connect(ui->lineEditNameServer, &QLineEdit::textChanged, this, &AdvancedSettingsWidget::setNameServer); + + // openDHT config + connect(ui->checkBoxEnableProxy, &QCheckBox::stateChanged, this, &AdvancedSettingsWidget::setEnableProxy); + + connect(ui->lineEditProxy, &QLineEdit::textChanged, this, &AdvancedSettingsWidget::setProxyAddress); + connect(ui->lineEditBootstrap, &QLineEdit::textChanged, this, &AdvancedSettingsWidget::setBootstrapAddress); + + // security + connect(ui->btnCACert, &QPushButton::clicked, this, &AdvancedSettingsWidget::openFileCACert); + connect(ui->btnUserCert, &QPushButton::clicked, this, &AdvancedSettingsWidget::openFileUserCert); + connect(ui->btnPrivateKey, &QPushButton::clicked, this, &AdvancedSettingsWidget::openFilePrivateKey); + + // connectivity + connect(ui->checkBoxUPnP, &QCheckBox::stateChanged, this, &AdvancedSettingsWidget::setUseUPnP); + connect(ui->checkBoxTurnEnable, &QCheckBox::stateChanged, this, &AdvancedSettingsWidget::setUseTURN); + connect(ui->checkBoxSTUNEnable, &QCheckBox::stateChanged, this, &AdvancedSettingsWidget::setUseSTUN); + + connect(ui->lineEditTurnAddress, &QLineEdit::textChanged, this, &AdvancedSettingsWidget::setTURNAddress); + connect(ui->lineEditTurnUsername, &QLineEdit::textChanged, this, &AdvancedSettingsWidget::setTURNUsername); + connect(ui->lineEditTurnPsswd, &QLineEdit::textChanged, this, &AdvancedSettingsWidget::setTURNPsswd); + connect(ui->lineEditSTUNAddress, &QLineEdit::textChanged, this, &AdvancedSettingsWidget::setSTUNAddress); + + // codecs + connect(ui->audioListWidget, &QListWidget::itemChanged, this, &AdvancedSettingsWidget::audioCodecsStateChange); + connect(ui->videoListWidget, &QListWidget::itemChanged, this, &AdvancedSettingsWidget::videoCodecsStateChange); + + connect(ui->videoCheckBox, &QCheckBox::stateChanged, this, &AdvancedSettingsWidget::setVideoState); + + // codec priority setting + connect(ui->audioDownPushButton, &QPushButton::clicked, this, &AdvancedSettingsWidget::decreaseAudioCodecPriority); + connect(ui->audioUpPushButton, &QPushButton::clicked, this, &AdvancedSettingsWidget::increaseAudioCodecPriority); + + connect(ui->videoDownPushButton, &QPushButton::clicked, this, &AdvancedSettingsWidget::decreaseVideoCodecPriority); + connect(ui->videoUpPushButton, &QPushButton::clicked, this, &AdvancedSettingsWidget::increaseVideoCodecPriority); + + +/////////////////////////////////////////////////////////////////////////////// + ui->btnRingtone->setEnabled(LRCInstance::getCurrAccConfig().Ringtone.ringtoneEnabled); + ui->lineEditProxy->setEnabled(LRCInstance::getCurrAccConfig().proxyEnabled); + ui->lineEditSTUNAddress->setEnabled(LRCInstance::getCurrAccConfig().STUN.enable); + + +} + +AdvancedSettingsWidget::~AdvancedSettingsWidget() +{ + delete ui; +} + +void +AdvancedSettingsWidget::updateAdvancedSettings() +{ + auto config = LRCInstance::getCurrAccConfig(); + //Call Settings + ui->checkBoxUntrusted->setChecked(config.allowIncoming); + ui->checkBoxAutoAnswer->setChecked(config.autoAnswer); + ui->checkBoxCustomRingtone->setChecked(config.Ringtone.ringtoneEnabled); + + // Name Server + ui->lineEditNameServer->setText(QString::fromStdString(config.RingNS.uri)); + + //OpenDHT Config + ui->checkBoxEnableProxy->setChecked(config.proxyEnabled); + ui->lineEditProxy->setText(QString::fromStdString(config.proxyServer)); + ui->lineEditBootstrap->setText(QString::fromStdString(config.hostname)); + + // Security + ui->btnCACert->setText(QString::fromStdString(config.TLS.certificateListFile)); + ui->btnUserCert->setText(QString::fromStdString(config.TLS.certificateFile)); + ui->btnPrivateKey->setText(QString::fromStdString(config.TLS.privateKeyFile)); + + // Connectivity + ui->checkBoxUPnP->setChecked(config.upnpEnabled); + ui->checkBoxTurnEnable->setChecked(config.TURN.enable); + ui->lineEditTurnAddress->setText(QString::fromStdString(config.TURN.server)); + ui->lineEditTurnUsername->setText(QString::fromStdString(config.TURN.username)); + ui->lineEditTurnPsswd->setText(QString::fromStdString(config.TURN.password)); + ui->checkBoxSTUNEnable->setChecked(config.STUN.enable); + ui->lineEditSTUNAddress->setText(QString::fromStdString(config.STUN.server)); + + // codecs + ui->videoCheckBox->setChecked(config.Video.videoEnabled); + updateAudioCodecs(); + updateVideoCodecs(); +} + +// call settings +void +AdvancedSettingsWidget::setCallsUntrusted(bool state) +{ + auto confProps = LRCInstance::accountModel().getAccountConfig(LRCInstance::getCurrAccId()); + confProps.allowIncoming = state; + LRCInstance::editableAccountModel()->setAccountConfig(LRCInstance::getCurrAccId(), confProps); +} +void +AdvancedSettingsWidget::setAutoAnswerCalls(bool state) +{ + auto confProps = LRCInstance::accountModel().getAccountConfig(LRCInstance::getCurrAccId()); + confProps.autoAnswer = state; + LRCInstance::editableAccountModel()->setAccountConfig(LRCInstance::getCurrAccId(), confProps); +} +void +AdvancedSettingsWidget::setEnableRingtone(bool state) +{ + auto confProps = LRCInstance::accountModel().getAccountConfig(LRCInstance::getCurrAccId()); + confProps.Ringtone.ringtoneEnabled = state; + LRCInstance::editableAccountModel()->setAccountConfig(LRCInstance::getCurrAccId(), confProps); +} + +void +AdvancedSettingsWidget::openFileCustomRingtone() +{ + QString fileUrl; + fileUrl = QFileDialog::getOpenFileName(this, QString("Select a new ringtone"), QDir::currentPath() + QString("/ringtones/")); + if (!fileUrl.isEmpty()) { + auto confProps = LRCInstance::accountModel().getAccountConfig(LRCInstance::getCurrAccId()); + confProps.Ringtone.ringtonePath = fileUrl.toStdString(); + LRCInstance::editableAccountModel()->setAccountConfig(LRCInstance::getCurrAccId(), confProps); + ui->btnRingtone->setText(QString::fromStdString(LRCInstance::getCurrAccConfig().Ringtone.ringtonePath)); + + } else { + ui->btnRingtone->setText(tr("Add a custom ringtone")); + } +} + +// name server +void +AdvancedSettingsWidget::setNameServer(const QString& name) +{ + auto confProps = LRCInstance::accountModel().getAccountConfig(LRCInstance::getCurrAccId()); + confProps.RingNS.uri = name.toStdString(); + LRCInstance::editableAccountModel()->setAccountConfig(LRCInstance::getCurrAccId(), confProps); +} + +// openDHT config +void +AdvancedSettingsWidget::setEnableProxy(bool state) +{ + auto confProps = LRCInstance::accountModel().getAccountConfig(LRCInstance::getCurrAccId()); + confProps.proxyEnabled = state; + LRCInstance::editableAccountModel()->setAccountConfig(LRCInstance::getCurrAccId(), confProps); + + state ? ui->lineEditProxy->setEnabled(true) : ui->lineEditProxy->setEnabled(false); +} +void +AdvancedSettingsWidget::setProxyAddress(const QString& name) +{ + auto confProps = LRCInstance::accountModel().getAccountConfig(LRCInstance::getCurrAccId()); + confProps.proxyServer = name.toStdString(); + LRCInstance::editableAccountModel()->setAccountConfig(LRCInstance::getCurrAccId(), confProps); +} +void +AdvancedSettingsWidget::setBootstrapAddress(const QString& name) +{ + auto confProps = LRCInstance::accountModel().getAccountConfig(LRCInstance::getCurrAccId()); + confProps.hostname = name.toStdString(); + LRCInstance::editableAccountModel()->setAccountConfig(LRCInstance::getCurrAccId(), confProps); +} + +// security + +// connectivity +void +AdvancedSettingsWidget::setUseUPnP(bool state) +{ + auto confProps = LRCInstance::accountModel().getAccountConfig(LRCInstance::getCurrAccId()); + confProps.upnpEnabled = state; + LRCInstance::editableAccountModel()->setAccountConfig(LRCInstance::getCurrAccId(), confProps); +} +void +AdvancedSettingsWidget::setUseTURN(bool state) +{ + auto confProps = LRCInstance::accountModel().getAccountConfig(LRCInstance::getCurrAccId()); + confProps.TURN.enable = state; + LRCInstance::editableAccountModel()->setAccountConfig(LRCInstance::getCurrAccId(), confProps); +} +void +AdvancedSettingsWidget::setUseSTUN(bool state) +{ + auto confProps = LRCInstance::accountModel().getAccountConfig(LRCInstance::getCurrAccId()); + confProps.STUN.enable = state; + LRCInstance::editableAccountModel()->setAccountConfig(LRCInstance::getCurrAccId(), confProps); + + state ? ui->lineEditSTUNAddress->setEnabled(true) : ui->lineEditSTUNAddress->setEnabled(false); +} + +void +AdvancedSettingsWidget::setTURNAddress(const QString& name) +{ + auto confProps = LRCInstance::accountModel().getAccountConfig(LRCInstance::getCurrAccId()); + confProps.TURN.server = name.toStdString(); + LRCInstance::editableAccountModel()->setAccountConfig(LRCInstance::getCurrAccId(), confProps); +} +void +AdvancedSettingsWidget::setTURNUsername(const QString& name) +{ + auto confProps = LRCInstance::accountModel().getAccountConfig(LRCInstance::getCurrAccId()); + confProps.TURN.username = name.toStdString(); + LRCInstance::editableAccountModel()->setAccountConfig(LRCInstance::getCurrAccId(), confProps); +} +void +AdvancedSettingsWidget::setTURNPsswd(const QString& name) +{ + auto confProps = LRCInstance::accountModel().getAccountConfig(LRCInstance::getCurrAccId()); + confProps.TURN.password = name.toStdString(); + LRCInstance::editableAccountModel()->setAccountConfig(LRCInstance::getCurrAccId(), confProps); +} +void +AdvancedSettingsWidget::setSTUNAddress(const QString& name) +{ + auto confProps = LRCInstance::accountModel().getAccountConfig(LRCInstance::getCurrAccId()); + confProps.STUN.server = name.toStdString(); + LRCInstance::editableAccountModel()->setAccountConfig(LRCInstance::getCurrAccId(), confProps); +} + +void +AdvancedSettingsWidget::openFileCACert() +{ + QString fileUrl; + fileUrl = QFileDialog::getOpenFileName(this, QString("Select a CA certificate"), QDir::homePath() + + QString("/.local/share/ring/") + QString::fromStdString(LRCInstance::getCurrentAccountInfo().id)); + if (!fileUrl.isEmpty()) { + auto confProps = LRCInstance::accountModel().getAccountConfig(LRCInstance::getCurrAccId()); + confProps.TLS.certificateListFile = fileUrl.toStdString(); + LRCInstance::editableAccountModel()->setAccountConfig(LRCInstance::getCurrAccId(), confProps); + } + ui->btnCACert->setText(QString::fromStdString(LRCInstance::getCurrAccConfig().TLS.certificateListFile)); +} + +void +AdvancedSettingsWidget::openFileUserCert() +{ + QString fileUrl; + fileUrl = QFileDialog::getOpenFileName(this, QString("Select a user certificate"), QDir::homePath() + + QString("/.local/share/ring/") + QString::fromStdString(LRCInstance::getCurrentAccountInfo().id)); + if (!fileUrl.isEmpty()) { + auto confProps = LRCInstance::accountModel().getAccountConfig(LRCInstance::getCurrAccId()); + confProps.TLS.certificateFile = fileUrl.toStdString(); + LRCInstance::editableAccountModel()->setAccountConfig(LRCInstance::getCurrAccId(), confProps); + } + ui->btnUserCert->setText(QString::fromStdString(LRCInstance::getCurrAccConfig().TLS.certificateFile)); +} + +void +AdvancedSettingsWidget::openFilePrivateKey() +{ + QString fileUrl; + fileUrl = QFileDialog::getOpenFileName(this, QString("Select a private key"), QDir::homePath() + + QString("/.local/share/ring/") + QString::fromStdString(LRCInstance::getCurrentAccountInfo().id)); + if (!fileUrl.isEmpty()) { + auto confProps = LRCInstance::accountModel().getAccountConfig(LRCInstance::getCurrAccId()); + confProps.TLS.privateKeyFile = fileUrl.toStdString(); + LRCInstance::editableAccountModel()->setAccountConfig(LRCInstance::getCurrAccId(), confProps); + } + ui->btnPrivateKey->setText(QString::fromStdString(LRCInstance::getCurrAccConfig().TLS.privateKeyFile)); +} + +void +AdvancedSettingsWidget::updateAudioCodecs() +{ + ui->audioListWidget->clear(); + + auto audioCodecList = LRCInstance::getCurrentAccountInfo().codecModel->getAudioCodecs(); + int i = 0; + for (auto it = audioCodecList.begin(); it != audioCodecList.end(); ++it, ++i) { + QListWidgetItem* audioItem = new QListWidgetItem(ui->audioListWidget); + audioItem->setFlags(Qt::ItemIsUserCheckable | Qt::ItemIsEnabled | Qt::ItemIsSelectable); + Qt::CheckState state; + it->enabled ? state = Qt::Checked : state = Qt::Unchecked; + audioItem->setCheckState(state); + audioItem->setData(Qt::DisplayRole, QString::fromStdString(it->name) + "\n" + QString::fromStdString(it->samplerate) + + " Hz"); + + ui->audioListWidget->addItem(audioItem); + } +} + +void +AdvancedSettingsWidget::updateVideoCodecs() +{ + ui->videoListWidget->clear(); + + auto videoCodecList = LRCInstance::getCurrentAccountInfo().codecModel->getVideoCodecs(); + int i = 0; + + for (auto it = videoCodecList.begin(); it != videoCodecList.end(); ++it, ++i) { + if (it->name.length()) { // [temporary fix] + QListWidgetItem* videoItem = new QListWidgetItem(ui->videoListWidget); + videoItem->setFlags(Qt::ItemIsUserCheckable | Qt::ItemIsEnabled | Qt::ItemIsSelectable); + Qt::CheckState state; + it->enabled ? state = Qt::Checked : state = Qt::Unchecked; + videoItem->setCheckState(state); + videoItem->setData(Qt::DisplayRole, QString::fromStdString(it->name) + "\n"); + + ui->audioListWidget->addItem(videoItem); + } + } +} + +void +AdvancedSettingsWidget::audioCodecsStateChange(QListWidgetItem* item) +{ + auto audioCodecList = LRCInstance::getCurrentAccountInfo().codecModel->getAudioCodecs(); + auto it = audioCodecList.begin(); + + std::advance(it, ui->audioListWidget->row(item)); + + LRCInstance::getCurrentAccountInfo().codecModel->enable(it->id, !(it->enabled)); +} + +void +AdvancedSettingsWidget::videoCodecsStateChange(QListWidgetItem* item) +{ + auto videoCodecList = LRCInstance::getCurrentAccountInfo().codecModel->getVideoCodecs(); + auto it = videoCodecList.begin(); + + std::advance(it, ui->videoListWidget->row(item)); + + LRCInstance::getCurrentAccountInfo().codecModel->enable(it->id, !(it->enabled)); +} + +void +AdvancedSettingsWidget::decreaseAudioCodecPriority() +{ + int selectedRow = ui->audioListWidget->row(ui->audioListWidget->selectedItems().at(0)); + auto audioCodecList = LRCInstance::getCurrentAccountInfo().codecModel->getAudioCodecs(); + auto it = audioCodecList.begin(); + + advance(it, selectedRow); + LRCInstance::getCurrentAccountInfo().codecModel->decreasePriority(it->id, false); + updateAudioCodecs(); +} + +void +AdvancedSettingsWidget::increaseAudioCodecPriority() +{ + int selectedRow = ui->audioListWidget->row(ui->audioListWidget->selectedItems().at(0)); + auto audioCodecList = LRCInstance::getCurrentAccountInfo().codecModel->getAudioCodecs(); + auto it = audioCodecList.begin(); + + advance(it, selectedRow); + LRCInstance::getCurrentAccountInfo().codecModel->increasePriority(it->id, false); + updateAudioCodecs(); +} + +void +AdvancedSettingsWidget::decreaseVideoCodecPriority() +{ + int selectedRow = ui->videoListWidget->row(ui->videoListWidget->selectedItems().at(0)); + auto videoCodecList = LRCInstance::getCurrentAccountInfo().codecModel->getVideoCodecs(); + auto it = videoCodecList.begin(); + + advance(it, selectedRow); + LRCInstance::getCurrentAccountInfo().codecModel->decreasePriority(it->id, true); + updateVideoCodecs(); +} + +void +AdvancedSettingsWidget::increaseVideoCodecPriority() +{ + int selectedRow = ui->videoListWidget->row(ui->videoListWidget->selectedItems().at(0)); + auto videoCodecList = LRCInstance::getCurrentAccountInfo().codecModel->getVideoCodecs(); + auto it = videoCodecList.begin(); + + advance(it, selectedRow); + LRCInstance::getCurrentAccountInfo().codecModel->increasePriority(it->id, true); + updateVideoCodecs(); +} + +void +AdvancedSettingsWidget::setVideoState(int state) +{ + auto confProps = LRCInstance::accountModel().getAccountConfig(LRCInstance::getCurrAccId()); + confProps.Video.videoEnabled = (bool)state; + LRCInstance::editableAccountModel()->setAccountConfig(LRCInstance::getCurrAccId(), confProps); +} \ No newline at end of file diff --git a/advancedsettingswidget.h b/advancedsettingswidget.h new file mode 100644 index 0000000..a805294 --- /dev/null +++ b/advancedsettingswidget.h @@ -0,0 +1,89 @@ +/*************************************************************************** + * Copyright (C) 2018 by Savoir-faire Linux * + * Author: Isa Nanic <isa.nanic@savoirfairelinux.com> * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 3 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program. If not, see <http://www.gnu.org/licenses/>. * + **************************************************************************/ + +#pragma once + +#include <QWidget> +#include <QListWidgetItem> + +namespace Ui { + class AdvancedSettingsWidget; +} + +class AdvancedSettingsWidget : public QWidget { + + Q_OBJECT + AdvancedSettingsWidget(const AdvancedSettingsWidget& cpy); + +public: + AdvancedSettingsWidget(QWidget* parent = nullptr); + ~AdvancedSettingsWidget(); + +private: + Ui::AdvancedSettingsWidget* ui; + void updateAdvancedSettings(); + +private slots: +// call settings + void setCallsUntrusted(bool state); + void setAutoAnswerCalls(bool state); + void setEnableRingtone(bool state); + + void openFileCustomRingtone(); + +// name server + void setNameServer(const QString& name); + +// openDHT config + void setEnableProxy(bool state); + + void setProxyAddress(const QString& name); + void setBootstrapAddress(const QString& name); + +// security + void openFileCACert(); + void openFileUserCert(); + void openFilePrivateKey(); + +// connectivity + void setUseUPnP(bool state); + void setUseTURN(bool state); + void setUseSTUN(bool state); + + void setTURNAddress(const QString& name); + void setTURNUsername(const QString& name); + void setTURNPsswd(const QString& name); + void setSTUNAddress(const QString& name); + +// codecs + void updateAudioCodecs(); + void updateVideoCodecs(); + + void audioCodecsStateChange(QListWidgetItem* item = nullptr); + void videoCodecsStateChange(QListWidgetItem* item = nullptr); + + void decreaseAudioCodecPriority(); + void increaseAudioCodecPriority(); + + void decreaseVideoCodecPriority(); + void increaseVideoCodecPriority(); + + void setVideoState(int state); + + +}; \ No newline at end of file diff --git a/advancedsettingswidget.ui b/advancedsettingswidget.ui new file mode 100644 index 0000000..61c4ba4 --- /dev/null +++ b/advancedsettingswidget.ui @@ -0,0 +1,1082 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>AdvancedSettingsWidget</class> + <widget class="QWidget" name="AdvancedSettingsWidget"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>688</width> + <height>1197</height> + </rect> + </property> + <property name="windowTitle"> + <string>Form</string> + </property> + <property name="styleSheet"> + <string notr="true">background: white;</string> + </property> + <layout class="QVBoxLayout" name="verticalLayout"> + <item> + <widget class="Line" name="line"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + </widget> + </item> + <item> + <widget class="QFrame" name="CallSettings"> + <property name="styleSheet"> + <string notr="true"/> + </property> + <layout class="QVBoxLayout" name="verticalLayout_2"> + <property name="topMargin"> + <number>20</number> + </property> + <property name="bottomMargin"> + <number>20</number> + </property> + <item> + <widget class="QLabel" name="label"> + <property name="font"> + <font> + <pointsize>11</pointsize> + </font> + </property> + <property name="text"> + <string>Call Settings</string> + </property> + </widget> + </item> + <item> + <layout class="QVBoxLayout" name="verticalLayout_3"> + <property name="leftMargin"> + <number>40</number> + </property> + <property name="topMargin"> + <number>5</number> + </property> + <item> + <layout class="QHBoxLayout" name="horizontalLayout_9"> + <property name="bottomMargin"> + <number>3</number> + </property> + <item> + <widget class="QCheckBox" name="checkBoxUntrusted"> + <property name="text"> + <string>Allow Calls From Untrusted Peers</string> + </property> + </widget> + </item> + </layout> + </item> + <item> + <widget class="QCheckBox" name="checkBoxAutoAnswer"> + <property name="text"> + <string>Auto Answer Calls</string> + </property> + </widget> + </item> + <item> + <layout class="QHBoxLayout" name="horizontalLayout" stretch="0,0,0"> + <item> + <widget class="QCheckBox" name="checkBoxCustomRingtone"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Expanding" vsizetype="Fixed"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="text"> + <string>Enable Custom Ringtone</string> + </property> + </widget> + </item> + <item> + <widget class="QPushButton" name="btnRingtone"> + <property name="minimumSize"> + <size> + <width>250</width> + <height>25</height> + </size> + </property> + <property name="styleSheet"> + <string notr="true">background: rgb(248, 248, 248); border-radius: 3px;</string> + </property> + <property name="text"> + <string>Add a custom ringtone</string> + </property> + <property name="icon"> + <iconset> + <normaloff>images/icons/round-folder-24px.svg</normaloff>images/icons/round-folder-24px.svg</iconset> + </property> + </widget> + </item> + <item> + <spacer name="horizontalSpacer_7"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeType"> + <enum>QSizePolicy::Fixed</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>40</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + </layout> + </item> + </layout> + </item> + </layout> + </widget> + </item> + <item> + <widget class="Line" name="line_2"> + <property name="frameShadow"> + <enum>QFrame::Plain</enum> + </property> + <property name="lineWidth"> + <number>1</number> + </property> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + </widget> + </item> + <item> + <widget class="QFrame" name="NameServer"> + <property name="frameShape"> + <enum>QFrame::StyledPanel</enum> + </property> + <property name="frameShadow"> + <enum>QFrame::Raised</enum> + </property> + <layout class="QVBoxLayout" name="verticalLayout_4"> + <property name="topMargin"> + <number>30</number> + </property> + <property name="bottomMargin"> + <number>20</number> + </property> + <item> + <widget class="QLabel" name="label_2"> + <property name="font"> + <font> + <pointsize>11</pointsize> + </font> + </property> + <property name="text"> + <string>Name Server</string> + </property> + </widget> + </item> + <item> + <layout class="QHBoxLayout" name="horizontalLayout_2"> + <property name="leftMargin"> + <number>40</number> + </property> + <item> + <widget class="QLabel" name="label_3"> + <property name="minimumSize"> + <size> + <width>60</width> + <height>0</height> + </size> + </property> + <property name="frameShape"> + <enum>QFrame::NoFrame</enum> + </property> + <property name="text"> + <string>Address</string> + </property> + </widget> + </item> + <item> + <spacer name="horizontalSpacer_8"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>40</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + <item> + <widget class="QLineEdit" name="lineEditNameServer"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Fixed" vsizetype="Fixed"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="minimumSize"> + <size> + <width>300</width> + <height>0</height> + </size> + </property> + <property name="styleSheet"> + <string notr="true">border-bottom: 1px solid black;</string> + </property> + </widget> + </item> + </layout> + </item> + </layout> + </widget> + </item> + <item> + <widget class="Line" name="line_3"> + <property name="frameShadow"> + <enum>QFrame::Plain</enum> + </property> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + </widget> + </item> + <item> + <widget class="QFrame" name="OpenDHTConfiguration"> + <property name="frameShape"> + <enum>QFrame::StyledPanel</enum> + </property> + <property name="frameShadow"> + <enum>QFrame::Raised</enum> + </property> + <layout class="QVBoxLayout" name="verticalLayout_5"> + <property name="topMargin"> + <number>30</number> + </property> + <property name="bottomMargin"> + <number>20</number> + </property> + <item> + <widget class="QLabel" name="label_4"> + <property name="font"> + <font> + <pointsize>11</pointsize> + </font> + </property> + <property name="text"> + <string>OpenDHT Configuration</string> + </property> + </widget> + </item> + <item> + <layout class="QVBoxLayout" name="verticalLayout_6"> + <property name="topMargin"> + <number>0</number> + </property> + <item> + <layout class="QHBoxLayout" name="horizontalLayout_3"> + <property name="leftMargin"> + <number>40</number> + </property> + <item> + <widget class="QCheckBox" name="checkBoxEnableProxy"> + <property name="minimumSize"> + <size> + <width>100</width> + <height>0</height> + </size> + </property> + <property name="text"> + <string>Enable Proxy</string> + </property> + </widget> + </item> + <item> + <spacer name="horizontalSpacer_2"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>40</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + <item> + <widget class="QLineEdit" name="lineEditProxy"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Fixed" vsizetype="Fixed"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="minimumSize"> + <size> + <width>300</width> + <height>0</height> + </size> + </property> + <property name="styleSheet"> + <string notr="true">border-bottom: 1px solid black;</string> + </property> + <property name="frame"> + <bool>true</bool> + </property> + </widget> + </item> + </layout> + </item> + </layout> + </item> + <item> + <layout class="QHBoxLayout" name="horizontalLayout_4"> + <property name="leftMargin"> + <number>40</number> + </property> + <item> + <widget class="QLabel" name="labelBootstrap"> + <property name="text"> + <string>Bootstrap</string> + </property> + </widget> + </item> + <item> + <spacer name="horizontalSpacer_3"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>40</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + <item> + <widget class="QLineEdit" name="lineEditBootstrap"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Fixed" vsizetype="Fixed"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="minimumSize"> + <size> + <width>300</width> + <height>0</height> + </size> + </property> + <property name="styleSheet"> + <string notr="true">border-bottom: 1px solid black;</string> + </property> + </widget> + </item> + </layout> + </item> + </layout> + </widget> + </item> + <item> + <widget class="Line" name="line_4"> + <property name="frameShadow"> + <enum>QFrame::Plain</enum> + </property> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + </widget> + </item> + <item> + <widget class="QFrame" name="Security"> + <property name="frameShape"> + <enum>QFrame::StyledPanel</enum> + </property> + <property name="frameShadow"> + <enum>QFrame::Raised</enum> + </property> + <layout class="QVBoxLayout" name="verticalLayout_16"> + <property name="topMargin"> + <number>30</number> + </property> + <property name="bottomMargin"> + <number>20</number> + </property> + <item> + <widget class="QLabel" name="label_17"> + <property name="font"> + <font> + <pointsize>11</pointsize> + </font> + </property> + <property name="text"> + <string>Security</string> + </property> + </widget> + </item> + <item> + <layout class="QGridLayout" name="gridLayout_2"> + <property name="leftMargin"> + <number>40</number> + </property> + <item row="3" column="0"> + <widget class="QLabel" name="label_21"> + <property name="text"> + <string>Private Key Password</string> + </property> + </widget> + </item> + <item row="1" column="0"> + <widget class="QLabel" name="label_19"> + <property name="text"> + <string>User Certificate</string> + </property> + </widget> + </item> + <item row="3" column="1"> + <widget class="QLineEdit" name="lineEditCertPassword"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Fixed" vsizetype="Fixed"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="minimumSize"> + <size> + <width>300</width> + <height>0</height> + </size> + </property> + <property name="styleSheet"> + <string notr="true">border-bottom: 1px solid black;</string> + </property> + <property name="placeholderText"> + <string>no password</string> + </property> + </widget> + </item> + <item row="2" column="0"> + <widget class="QLabel" name="label_20"> + <property name="text"> + <string>Private Key</string> + </property> + </widget> + </item> + <item row="0" column="0"> + <widget class="QLabel" name="label_18"> + <property name="text"> + <string>CA Certificate</string> + </property> + </widget> + </item> + <item row="0" column="1"> + <layout class="QHBoxLayout" name="horizontalLayout_5"> + <item> + <widget class="QPushButton" name="btnCACert"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Minimum" vsizetype="Fixed"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="minimumSize"> + <size> + <width>250</width> + <height>25</height> + </size> + </property> + <property name="layoutDirection"> + <enum>Qt::LeftToRight</enum> + </property> + <property name="styleSheet"> + <string notr="true">background: rgb(248, 248, 248); border-radius: 3px;</string> + </property> + <property name="text"> + <string/> + </property> + <property name="icon"> + <iconset> + <normaloff>images/icons/round-folder-24px.svg</normaloff>images/icons/round-folder-24px.svg</iconset> + </property> + </widget> + </item> + <item> + <spacer name="horizontalSpacer"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeType"> + <enum>QSizePolicy::Minimum</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>40</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + </layout> + </item> + <item row="1" column="1"> + <layout class="QHBoxLayout" name="horizontalLayout_6"> + <item> + <widget class="QPushButton" name="btnUserCert"> + <property name="minimumSize"> + <size> + <width>250</width> + <height>25</height> + </size> + </property> + <property name="layoutDirection"> + <enum>Qt::LeftToRight</enum> + </property> + <property name="styleSheet"> + <string notr="true">background: rgb(248, 248, 248); border-radius: 3px;</string> + </property> + <property name="text"> + <string/> + </property> + <property name="icon"> + <iconset> + <normaloff>images/icons/round-folder-24px.svg</normaloff>images/icons/round-folder-24px.svg</iconset> + </property> + </widget> + </item> + <item> + <spacer name="horizontalSpacer_4"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeType"> + <enum>QSizePolicy::Minimum</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>40</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + </layout> + </item> + <item row="2" column="1"> + <layout class="QHBoxLayout" name="horizontalLayout_7"> + <item> + <widget class="QPushButton" name="btnPrivateKey"> + <property name="minimumSize"> + <size> + <width>250</width> + <height>25</height> + </size> + </property> + <property name="layoutDirection"> + <enum>Qt::LeftToRight</enum> + </property> + <property name="styleSheet"> + <string notr="true">background: rgb(248, 248, 248); border-radius: 3px;</string> + </property> + <property name="text"> + <string/> + </property> + <property name="icon"> + <iconset> + <normaloff>images/icons/round-folder-24px.svg</normaloff>images/icons/round-folder-24px.svg</iconset> + </property> + </widget> + </item> + <item> + <spacer name="horizontalSpacer_6"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeType"> + <enum>QSizePolicy::Minimum</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>40</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + </layout> + </item> + </layout> + </item> + </layout> + </widget> + </item> + <item> + <widget class="Line" name="line_5"> + <property name="frameShadow"> + <enum>QFrame::Plain</enum> + </property> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + </widget> + </item> + <item> + <widget class="QFrame" name="Connectivity"> + <property name="frameShape"> + <enum>QFrame::StyledPanel</enum> + </property> + <property name="frameShadow"> + <enum>QFrame::Raised</enum> + </property> + <layout class="QVBoxLayout" name="verticalLayout_8"> + <property name="topMargin"> + <number>30</number> + </property> + <property name="bottomMargin"> + <number>20</number> + </property> + <item> + <widget class="QLabel" name="label_11"> + <property name="font"> + <font> + <pointsize>11</pointsize> + </font> + </property> + <property name="text"> + <string>Connectivity</string> + </property> + </widget> + </item> + <item> + <layout class="QGridLayout" name="gridLayout"> + <property name="leftMargin"> + <number>40</number> + </property> + <item row="3" column="2"> + <widget class="QLineEdit" name="lineEditTurnUsername"> + <property name="styleSheet"> + <string notr="true">border-bottom: 1px solid black;</string> + </property> + </widget> + </item> + <item row="0" column="1"> + <spacer name="horizontalSpacer_5"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeType"> + <enum>QSizePolicy::MinimumExpanding</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>40</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + <item row="2" column="0"> + <widget class="QLabel" name="label_13"> + <property name="text"> + <string> TURN Address</string> + </property> + </widget> + </item> + <item row="2" column="2"> + <widget class="QLineEdit" name="lineEditTurnAddress"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Fixed" vsizetype="Fixed"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="minimumSize"> + <size> + <width>300</width> + <height>0</height> + </size> + </property> + <property name="autoFillBackground"> + <bool>false</bool> + </property> + <property name="styleSheet"> + <string notr="true">border-bottom: 1px solid black;</string> + </property> + </widget> + </item> + <item row="5" column="0"> + <widget class="QCheckBox" name="checkBoxSTUNEnable"> + <property name="text"> + <string>Use STUN</string> + </property> + </widget> + </item> + <item row="4" column="2"> + <widget class="QLineEdit" name="lineEditTurnPsswd"> + <property name="styleSheet"> + <string notr="true">border-bottom: 1px solid black;</string> + </property> + </widget> + </item> + <item row="5" column="2"> + <widget class="QLineEdit" name="lineEditSTUNAddress"> + <property name="styleSheet"> + <string notr="true">border-bottom: 1px solid black;</string> + </property> + <property name="placeholderText"> + <string>STUN Address</string> + </property> + </widget> + </item> + <item row="3" column="0"> + <widget class="QLabel" name="label_14"> + <property name="text"> + <string> TURN Username</string> + </property> + </widget> + </item> + <item row="4" column="0"> + <widget class="QLabel" name="label_12"> + <property name="text"> + <string> TURN Password</string> + </property> + </widget> + </item> + <item row="0" column="0"> + <widget class="QCheckBox" name="checkBoxUPnP"> + <property name="text"> + <string>Use UPnP</string> + </property> + </widget> + </item> + <item row="1" column="0"> + <widget class="QCheckBox" name="checkBoxTurnEnable"> + <property name="text"> + <string>Use TURN</string> + </property> + </widget> + </item> + </layout> + </item> + </layout> + </widget> + </item> + <item> + <widget class="Line" name="line_6"> + <property name="frameShadow"> + <enum>QFrame::Plain</enum> + </property> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + </widget> + </item> + <item> + <widget class="QFrame" name="frame_5"> + <property name="frameShape"> + <enum>QFrame::StyledPanel</enum> + </property> + <property name="frameShadow"> + <enum>QFrame::Raised</enum> + </property> + <layout class="QHBoxLayout" name="horizontalLayout_14"> + <property name="topMargin"> + <number>30</number> + </property> + <property name="bottomMargin"> + <number>20</number> + </property> + <item> + <layout class="QVBoxLayout" name="verticalLayout_12"> + <item> + <layout class="QHBoxLayout" name="horizontalLayout_10"> + <item> + <widget class="QLabel" name="audioLabel"> + <property name="minimumSize"> + <size> + <width>0</width> + <height>30</height> + </size> + </property> + <property name="maximumSize"> + <size> + <width>16777215</width> + <height>30</height> + </size> + </property> + <property name="font"> + <font> + <pointsize>10</pointsize> + </font> + </property> + <property name="styleSheet"> + <string notr="true">border-bottom: 1px solid black;</string> + </property> + <property name="text"> + <string>Audio Codecs</string> + </property> + </widget> + </item> + <item> + <spacer name="horizontalSpacer_10"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeType"> + <enum>QSizePolicy::Fixed</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>20</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + <item> + <widget class="QPushButton" name="audioDownPushButton"> + <property name="minimumSize"> + <size> + <width>30</width> + <height>30</height> + </size> + </property> + <property name="maximumSize"> + <size> + <width>30</width> + <height>30</height> + </size> + </property> + <property name="text"> + <string/> + </property> + <property name="icon"> + <iconset> + <normaloff>images/icons/round-arrow_drop_down-24px.svg</normaloff>images/icons/round-arrow_drop_down-24px.svg</iconset> + </property> + <property name="iconSize"> + <size> + <width>20</width> + <height>20</height> + </size> + </property> + </widget> + </item> + <item> + <widget class="QPushButton" name="audioUpPushButton"> + <property name="minimumSize"> + <size> + <width>30</width> + <height>30</height> + </size> + </property> + <property name="maximumSize"> + <size> + <width>30</width> + <height>30</height> + </size> + </property> + <property name="text"> + <string/> + </property> + <property name="icon"> + <iconset> + <normaloff>images/icons/round-arrow_drop_up-24px.svg</normaloff>images/icons/round-arrow_drop_up-24px.svg</iconset> + </property> + <property name="iconSize"> + <size> + <width>20</width> + <height>20</height> + </size> + </property> + </widget> + </item> + <item> + <spacer name="horizontalSpacer_11"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeType"> + <enum>QSizePolicy::Fixed</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>10</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + </layout> + </item> + <item> + <widget class="QListWidget" name="audioListWidget"> + <property name="minimumSize"> + <size> + <width>0</width> + <height>200</height> + </size> + </property> + </widget> + </item> + </layout> + </item> + <item> + <layout class="QVBoxLayout" name="verticalLayout_13"> + <item> + <layout class="QHBoxLayout" name="horizontalLayout_8"> + <item> + <widget class="QCheckBox" name="videoCheckBox"> + <property name="minimumSize"> + <size> + <width>0</width> + <height>30</height> + </size> + </property> + <property name="maximumSize"> + <size> + <width>16777215</width> + <height>30</height> + </size> + </property> + <property name="font"> + <font> + <pointsize>10</pointsize> + </font> + </property> + <property name="styleSheet"> + <string notr="true">border-bottom: 1px solid black;</string> + </property> + <property name="text"> + <string>Video Codecs</string> + </property> + </widget> + </item> + <item> + <spacer name="horizontalSpacer_9"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeType"> + <enum>QSizePolicy::Fixed</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>20</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + <item> + <widget class="QPushButton" name="videoDownPushButton"> + <property name="minimumSize"> + <size> + <width>30</width> + <height>30</height> + </size> + </property> + <property name="maximumSize"> + <size> + <width>30</width> + <height>30</height> + </size> + </property> + <property name="text"> + <string/> + </property> + <property name="icon"> + <iconset> + <normaloff>images/icons/round-arrow_drop_down-24px.svg</normaloff>images/icons/round-arrow_drop_down-24px.svg</iconset> + </property> + <property name="iconSize"> + <size> + <width>20</width> + <height>20</height> + </size> + </property> + </widget> + </item> + <item> + <widget class="QPushButton" name="videoUpPushButton"> + <property name="minimumSize"> + <size> + <width>30</width> + <height>30</height> + </size> + </property> + <property name="maximumSize"> + <size> + <width>30</width> + <height>30</height> + </size> + </property> + <property name="text"> + <string/> + </property> + <property name="icon"> + <iconset> + <normaloff>images/icons/round-arrow_drop_up-24px.svg</normaloff>images/icons/round-arrow_drop_up-24px.svg</iconset> + </property> + <property name="iconSize"> + <size> + <width>20</width> + <height>20</height> + </size> + </property> + </widget> + </item> + <item> + <spacer name="horizontalSpacer_12"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeType"> + <enum>QSizePolicy::Fixed</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>10</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + </layout> + </item> + <item> + <widget class="QListWidget" name="videoListWidget"> + <property name="minimumSize"> + <size> + <width>0</width> + <height>200</height> + </size> + </property> + </widget> + </item> + </layout> + </item> + </layout> + </widget> + </item> + <item> + <spacer name="verticalSpacer"> + <property name="orientation"> + <enum>Qt::Vertical</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>20</width> + <height>40</height> + </size> + </property> + </spacer> + </item> + </layout> + </widget> + <resources/> + <connections/> +</ui> diff --git a/avatargraphicsview.cpp b/avatargraphicsview.cpp new file mode 100644 index 0000000..eb97f3a --- /dev/null +++ b/avatargraphicsview.cpp @@ -0,0 +1,59 @@ +/************************************************************************** +* Copyright (C) 2018 by Savoir-faire Linux * +* Author: Isa Nanic <isa.nanic@savoirfairelinux.com> * +* * +* This program is free software; you can redistribute it and/or modify * +* it under the terms of the GNU General Public License as published by * +* the Free Software Foundation; either version 3 of the License, or * +* (at your option) any later version. * +* * +* This program is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU General Public License for more details. * +* * +* You should have received a copy of the GNU General Public License * +* along with this program. If not, see <https://www.gnu.org/licenses/>. * +**************************************************************************/ + +#include "avatargraphicsview.h" + +AvatarGraphicsView::AvatarGraphicsView(QWidget* parent) + : QGraphicsView(parent) +{ + setDragMode(QGraphicsView::ScrollHandDrag); +} + +void +AvatarGraphicsView::wheelEvent(QWheelEvent* event) +{ + QPoint numSteps = event->angleDelta() / (8*15); + + if (!numSteps.isNull()) { + zoomImage(numSteps); + } + event->accept(); +} + +void +AvatarGraphicsView::zoomImage(const QPoint& steps) +{ + steps.y() == 1 ? scale(zoomIncrement_, zoomIncrement_) : scale(1 / zoomIncrement_, 1 / zoomIncrement_); +} + +void +AvatarGraphicsView::paintEvent(QPaintEvent* e) +{ + QGraphicsView::paintEvent(e); + QPainter painter(viewport()); + + QPainterPath square; + QPainterPath circle; + + square.addRect(0, 0, width(), height()); + circle.addEllipse(QPoint(width() / 2 - 0.5, height() / 2 - 0.5), circleSize_ + 1, circleSize_ + 1); + + painter.setOpacity(0.3); + + painter.fillPath(square.subtracted(circle), QBrush(QColor(Qt::black))); +} \ No newline at end of file diff --git a/avatargraphicsview.h b/avatargraphicsview.h new file mode 100644 index 0000000..b8f79c8 --- /dev/null +++ b/avatargraphicsview.h @@ -0,0 +1,41 @@ +/************************************************************************** +* Copyright (C) 2018 by Savoir-faire Linux * +* Author: Isa Nanic <isa.nanic@savoirfairelinux.com> * +* * +* This program is free software; you can redistribute it and/or modify * +* it under the terms of the GNU General Public License as published by * +* the Free Software Foundation; either version 3 of the License, or * +* (at your option) any later version. * +* * +* This program is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU General Public License for more details. * +* * +* You should have received a copy of the GNU General Public License * +* along with this program. If not, see <https://www.gnu.org/licenses/>. * +**************************************************************************/ +#pragma once + +#include <QGraphicsView> +#include <QWheelEvent> +#include <QDragMoveEvent> + +class AvatarGraphicsView : public QGraphicsView +{ + Q_OBJECT + AvatarGraphicsView(const AvatarGraphicsView& cpy); + +public: + AvatarGraphicsView(QWidget* parent = nullptr); + inline void setAvatarSize(int size) { circleSize_ = size; }; + +private: + void wheelEvent(QWheelEvent* event); + void zoomImage(const QPoint& steps); + + void paintEvent(QPaintEvent* e); + + const qreal zoomIncrement_ = 1.03; + int circleSize_ = 130; +}; \ No newline at end of file diff --git a/bannedlistmodel.cpp b/bannedlistmodel.cpp new file mode 100644 index 0000000..1bd85e6 --- /dev/null +++ b/bannedlistmodel.cpp @@ -0,0 +1,40 @@ +/*************************************************************************** +* Copyright (C) 2018 by Savoir-faire Linux * +* Author: Isa Nanic <isa.nanic@savoirfairelinux.com> * +* * +* This program is free software; you can redistribute it and/or modify * +* it under the terms of the GNU General Public License as published by * +* the Free Software Foundation; either version 3 of the License, or * +* (at your option) any later version. * +* * +* This program is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU General Public License for more details. * +* * +* You should have received a copy of the GNU General Public License * +* along with this program. If not, see <http://www.gnu.org/licenses/>. * +***************************************************************************/ + +#include "bannedlistmodel.h" +#include "lrcinstance.h" + +BannedListModel::BannedListModel(QObject *parent) + : QAbstractListModel(parent) +{ +} + +int +BannedListModel::rowCount(const QModelIndex &index) const +{ + if (!index.isValid()) { + return LRCInstance::accountModel().getAccountList().size(); // count + } + return 0; // A valid QModelIndex returns 0 as no entry has sub-elements +} + +bool +BannedListModel::setData(const QModelIndex& index, const QVariant& value, int role) +{ + return 1; +} \ No newline at end of file diff --git a/bannedlistmodel.h b/bannedlistmodel.h new file mode 100644 index 0000000..2aa96b4 --- /dev/null +++ b/bannedlistmodel.h @@ -0,0 +1,33 @@ +/*************************************************************************** +* Copyright (C) 2018 by Savoir-faire Linux * +* Author: Isa Nanic <isa.nanic@savoirfairelinux.com> * +* * +* This program is free software; you can redistribute it and/or modify * +* it under the terms of the GNU General Public License as published by * +* the Free Software Foundation; either version 3 of the License, or * +* (at your option) any later version. * +* * +* This program is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU General Public License for more details. * +* * +* You should have received a copy of the GNU General Public License * +* along with this program. If not, see <http://www.gnu.org/licenses/>. * +***************************************************************************/ +#pragma once + +#include <QAbstractListModel> + +class BannedListModel : public QAbstractListModel +{ + Q_OBJECT + BannedListModel(const BannedListModel& cpy); + +public: + explicit BannedListModel(QObject *parent = nullptr); + + int rowCount(const QModelIndex &index = QModelIndex()) const override; + bool setData(const QModelIndex& index, const QVariant& value, int role = Qt::EditRole) override; + +}; diff --git a/callwidget.cpp b/callwidget.cpp index d5679f2..98b64f0 100644 --- a/callwidget.cpp +++ b/callwidget.cpp @@ -193,6 +193,8 @@ CallWidget::CallWidget(QWidget* parent) : // chat view ui->messageView->buildView(); + + emit setLeftSizeWidget(ui->currentAccountComboBox->width()); } CallWidget::~CallWidget() @@ -439,7 +441,7 @@ CallWidget::imageForConv(const std::string& convUid) const std::string& CallWidget::selectedAccountId() { - return LRCInstance::getSelectedAccountId(); + return LRCInstance::getCurrAccId(); } const std::string& @@ -502,6 +504,7 @@ CallWidget::invitationsButtonClicked() void CallWidget::settingsButtonClicked() { + emit setLeftSizeWidget(ui->currentAccountComboBox->width()); emit NavigationRequested(ScreenEnum::ConfScreen); } @@ -727,7 +730,7 @@ CallWidget::showIMOutOfCall(const QModelIndex& nodeIdx) QString contactURI = nodeIdx.data(static_cast<int>(SmartListModel::Role::URI)).toString(); bool isContact = false; - auto selectedAccountId = LRCInstance::getSelectedAccountId(); + auto selectedAccountId = LRCInstance::getCurrAccId(); auto& accountInfo = LRCInstance::accountModel().getAccountInfo(selectedAccountId); bool isRINGAccount = accountInfo.profileInfo.type == lrc::api::profile::Type::RING; try { @@ -1062,10 +1065,17 @@ CallWidget::updateSmartList() SLOT(smartListSelectionChanged(QItemSelection, QItemSelection))); } +void +CallWidget::updateComboBox() +{ + ui->currentAccountComboBox->updateComboBoxDisplay(); +} + void CallWidget::update() { updateSmartList(); updateConversationsFilterWidget(); + updateComboBox(); connectConversationModel(); } diff --git a/callwidget.h b/callwidget.h index e6b1f13..1501074 100644 --- a/callwidget.h +++ b/callwidget.h @@ -64,6 +64,9 @@ public: explicit CallWidget(QWidget* parent = 0); ~CallWidget(); +signals: + void setLeftSizeWidget(int size); + public slots: void on_ringContactLineEdit_returnPressed(); @@ -125,6 +128,7 @@ private: void setConversationFilter(const QString& filter); void setConversationFilter(lrc::api::profile::Type filter); void updateConversationsFilterWidget(); + void updateComboBox(); const std::string& selectedAccountId(); const std::string& selectedConvUid(); diff --git a/callwidget.ui b/callwidget.ui index dcc32b1..4541ae1 100644 --- a/callwidget.ui +++ b/callwidget.ui @@ -440,6 +440,32 @@ <property name="bottomMargin"> <number>0</number> </property> + <item> + <layout class="QHBoxLayout" name="horizontalLayout_9"> + <property name="spacing"> + <number>0</number> + </property> + <property name="topMargin"> + <number>7</number> + </property> + <property name="rightMargin"> + <number>7</number> + </property> + <item> + <spacer name="horizontalSpacer_11"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>40</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + </layout> + </item> <item> <spacer name="verticalSpacer"> <property name="orientation"> diff --git a/configurationwidget.cpp b/configurationwidget.cpp index 803a99b..ee3fb95 100644 --- a/configurationwidget.cpp +++ b/configurationwidget.cpp @@ -84,15 +84,15 @@ ConfigurationWidget::ConfigurationWidget(QWidget *parent) : accountStateDelegate_ = new AccountStateDelegate(); ui->accountView->setItemDelegate(accountStateDelegate_); - // connect delete button to popup trigger - connect(ui->deleteAccountBtn, &QPushButton::clicked, [=](){ - auto idx = ui->accountView->currentIndex(); - DeleteAccountDialog dialog(idx); - dialog.exec(); - if (!LRCInstance::accountModel().getAccountList().size()) { - emit NavigationRequested(ScreenEnum::WizardScreen); - } - }); + //// connect delete button to popup trigger + //connect(ui->deleteAccountBtn, &QPushButton::clicked, [=](){ + // auto idx = ui->accountView->currentIndex(); + // DeleteAccountDialog dialog(idx); + // dialog.exec(); + // if (!LRCInstance::accountModel().getAccountList().size()) { + // emit NavigationRequested(ScreenEnum::WizardScreen); + // } + //}); isLoading_ = true; ui->deviceBox->setModel(deviceModel_); diff --git a/configurationwidget.ui b/configurationwidget.ui index 5848345..86e6cfd 100644 --- a/configurationwidget.ui +++ b/configurationwidget.ui @@ -209,7 +209,7 @@ <bool>true</bool> </property> <property name="currentIndex"> - <number>0</number> + <number>1</number> </property> <widget class="QWidget" name="generalPage"> <layout class="QHBoxLayout" name="verticalLayout_2"> diff --git a/conversationitemdelegate.cpp b/conversationitemdelegate.cpp index 9c3f1f4..015ee88 100644 --- a/conversationitemdelegate.cpp +++ b/conversationitemdelegate.cpp @@ -187,7 +187,7 @@ ConversationItemDelegate::paintRingConversationItem(QPainter* painter, QFontMetrics fontMetrics(font); // The name is displayed at the avatar's right - QString nameStr = index.data(static_cast<int>(SmartListModel::Role::DisplayName)).value<QString>();; + QString nameStr = index.data(static_cast<int>(SmartListModel::Role::DisplayName)).value<QString>(); if (!nameStr.isNull()) { font.setItalic(false); font.setBold(true); diff --git a/copy-runtime-files.ps1 b/copy-runtime-files.ps1 index 7ad7349..bba75a0 100644 --- a/copy-runtime-files.ps1 +++ b/copy-runtime-files.ps1 @@ -64,6 +64,8 @@ $FilesToCopy = @( "$QtDir\bin\Qt5Widgets.dll", "$QtDir\bin\Qt5WinExtras.dll", "$QtDir\bin\Qt5Xml.dll", + "$QtDir\bin\Qt5Multimedia.dll", + "$QtDir\bin\Qt5MultimediaWidgets.dll", "$QtDir\bin\QtWebEngineProcess.exe", "$QtDir\resources\qtwebengine_resources.pak", "$QtDir\resources\icudtl.dat" diff --git a/currentaccountcombobox.cpp b/currentaccountcombobox.cpp index 59f0b67..a9888b4 100644 --- a/currentaccountcombobox.cpp +++ b/currentaccountcombobox.cpp @@ -59,8 +59,7 @@ CurrentAccountComboBox::CurrentAccountComboBox(QWidget* parent) } }); - gearPixmap_.load(":/images/icons/round-settings-24px.svg"); - gearLabel_.setPixmap(gearPixmap_); + gearLabel_.setPixmap(QPixmap(":/images/icons/round-settings-24px.svg")); gearLabel_.setParent(this); gearLabel_.setStyleSheet("background: transparent;"); setupSettingsButton(); @@ -134,16 +133,17 @@ CurrentAccountComboBox::paintEvent(QPaintEvent* e) } } -void CurrentAccountComboBox::resizeEvent(QResizeEvent * event) +void CurrentAccountComboBox::resizeEvent(QResizeEvent* event) { + Q_UNUSED(event); setupSettingsButton(); } void CurrentAccountComboBox::setupSettingsButton() { - gearPoint_.setX(this->width() - gearSize_ - 4 * gearBorder_); - gearPoint_.setY(this->height() / 2 - gearLabel_.height() / 2 - 2 * gearBorder_); + gearPoint_.setX(this->width() - gearSize_ - 4 * gearBorder_ + 2); + gearPoint_.setY(this->height() / 2 - gearLabel_.height() / 2 - 2 * gearBorder_ + 4.5); gearLabel_.setGeometry(gearPoint_.x() - 3, gearPoint_.y(), gearSize_ + 2 * gearBorder_, gearSize_ + 2 * gearBorder_); gearLabel_.setMargin(gearBorder_); @@ -209,7 +209,6 @@ CurrentAccountComboBox::hidePopup() gearLabel_.show(); popupPresent = false; QComboBox::hidePopup(); - } void @@ -217,4 +216,10 @@ CurrentAccountComboBox::leaveEvent(QEvent* event) { gearLabel_.setStyleSheet("background: transparent;"); QComboBox::leaveEvent(event); -} \ No newline at end of file +} + +void +CurrentAccountComboBox::updateComboBoxDisplay() +{ + importLabelPhoto(LRCInstance::getCurrentAccountIndex()); +} diff --git a/currentaccountcombobox.h b/currentaccountcombobox.h index 586d911..93f8596 100644 --- a/currentaccountcombobox.h +++ b/currentaccountcombobox.h @@ -36,6 +36,7 @@ public: ~CurrentAccountComboBox(); void accountListUpdate(); void setCurrentIndex(int index); + void updateComboBoxDisplay(); signals: void settingsButtonClicked(); @@ -64,6 +65,5 @@ private: bool popupPresent = false; QPoint gearPoint_; - QPixmap gearPixmap_; QLabel gearLabel_; -}; \ No newline at end of file +}; diff --git a/deleteaccountdialog.cpp b/deleteaccountdialog.cpp index 8528605..ef8c575 100644 --- a/deleteaccountdialog.cpp +++ b/deleteaccountdialog.cpp @@ -1,6 +1,7 @@ /*************************************************************************** - * Copyright (C) 2015-2017 by Savoir-faire Linux * + * Copyright (C) 2015-2018 by Savoir-faire Linux * * Author: Olivier Soldano <olivier.soldano@savoirfairelinux.com> * + * Author: Isa Nanic <isa.nanic@savoirfairelinux.com> * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * @@ -19,26 +20,22 @@ #include "deleteaccountdialog.h" #include "ui_deleteaccountdialog.h" -// LRC -#include "accountmodel.h" -#include "itemdataroles.h" -#include "account.h" +#include "lrcinstance.h" +#include "utils.h" -DeleteAccountDialog::DeleteAccountDialog(const QModelIndex & idx, QWidget *parent) : +DeleteAccountDialog::DeleteAccountDialog(QWidget *parent) : QDialog(parent), - ui(new Ui::DeleteAccountDialog), - index_(idx) + ui(new Ui::DeleteAccountDialog) { - setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint); ui->setupUi(this); - ui->accountAliasLabel->setText(AccountModel::instance().data(index_, Qt::DisplayRole).toString()); - auto ac = AccountModel::instance().getAccountByModelIndex(index_); - if (ac->protocol() == Account::Protocol::RING){ - ui->accountIdLabel->setAlignment(Qt::AlignCenter); - ui->accountIdLabel->setText((ac->registeredName().isEmpty())? ac->username(): ac->registeredName() + "\n" + ac->username()); + if (LRCInstance::getCurrentAccountInfo().profileInfo.type == lrc::api::profile::Type::RING){ + ui->labelBestId->setText(QString::fromStdString(Utils::bestNameForAccount(LRCInstance::getCurrentAccountInfo()))); + ui->labelAccountHash->setText(QString::fromStdString(LRCInstance::getCurrentAccountInfo().profileInfo.uri)); } else { - ui->warningLabel->hide(); + ui->labelWarning->hide(); } + connect(ui->btnDeleteAccept, &QPushButton::clicked, this, &DeleteAccountDialog::on_deleteAcceptBtn_clicked); + connect(ui->btnDeleteCancel, &QPushButton::clicked, this, &DeleteAccountDialog::on_deleteCancelBtn_clicked); } DeleteAccountDialog::~DeleteAccountDialog() @@ -46,15 +43,15 @@ DeleteAccountDialog::~DeleteAccountDialog() delete ui; } -void DeleteAccountDialog::on_deleteCancelBtn_clicked() +void +DeleteAccountDialog::on_deleteCancelBtn_clicked() { - close(); + done(0); } -void DeleteAccountDialog::on_deleteAcceptBtn_clicked() +void +DeleteAccountDialog::on_deleteAcceptBtn_clicked() { - auto account = AccountModel::instance().getAccountByModelIndex(index_); - AccountModel::instance().remove(account); - AccountModel::instance().save(); - close(); -} + LRCInstance::editableAccountModel()->removeAccount(LRCInstance::getCurrAccId()); + done(0); +} \ No newline at end of file diff --git a/deleteaccountdialog.h b/deleteaccountdialog.h index d06163c..9e97c0d 100644 --- a/deleteaccountdialog.h +++ b/deleteaccountdialog.h @@ -1,6 +1,7 @@ /*************************************************************************** - * Copyright (C) 2015-2017 by Savoir-faire Linux * + * Copyright (C) 2015-2018 by Savoir-faire Linux * * Author: Olivier Soldano <olivier.soldano@savoirfairelinux.com> * + * Author: Isa Nanic <isa.nanic@savoirfairelinux.com> * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * @@ -20,7 +21,6 @@ #define DELETEACCOUNTDIALOG_H #include <QDialog> -#include <QModelIndex> namespace Ui { class DeleteAccountDialog; @@ -31,20 +31,17 @@ class DeleteAccountDialog : public QDialog Q_OBJECT public: - DeleteAccountDialog(const QModelIndex & idx, QWidget *parent = 0); + DeleteAccountDialog(QWidget *parent = nullptr); ~DeleteAccountDialog(); -signals: - void deleteAcceptClicked(); - private slots: void on_deleteCancelBtn_clicked(); - void on_deleteAcceptBtn_clicked(); +signals: + void deleteAcceptClicked(); private: Ui::DeleteAccountDialog *ui; - QModelIndex index_; }; #endif // DELETEACCOUNTDIALOG_H diff --git a/deleteaccountdialog.ui b/deleteaccountdialog.ui index c30cdaa..13ef201 100644 --- a/deleteaccountdialog.ui +++ b/deleteaccountdialog.ui @@ -2,6 +2,9 @@ <ui version="4.0"> <class>DeleteAccountDialog</class> <widget class="QDialog" name="DeleteAccountDialog"> + <property name="windowModality"> + <enum>Qt::ApplicationModal</enum> + </property> <property name="geometry"> <rect> <x>0</x> @@ -10,67 +13,126 @@ <height>240</height> </rect> </property> + <property name="sizePolicy"> + <sizepolicy hsizetype="Fixed" vsizetype="Fixed"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="minimumSize"> + <size> + <width>400</width> + <height>240</height> + </size> + </property> + <property name="maximumSize"> + <size> + <width>400</width> + <height>240</height> + </size> + </property> <property name="windowTitle"> - <string>Ring - account deletion</string> + <string>Account deletion</string> </property> - <layout class="QVBoxLayout" name="verticalLayout" stretch="3,3,1,1,1,0,3,0"> - <item> - <spacer name="verticalSpacer"> - <property name="orientation"> - <enum>Qt::Vertical</enum> - </property> - <property name="sizeHint" stdset="0"> + <property name="styleSheet"> + <string notr="true">background: white;</string> + </property> + <layout class="QVBoxLayout" name="verticalLayout" stretch="3,1,1,0,0,0,0,0"> + <item alignment="Qt::AlignHCenter"> + <widget class="QLabel" name="labelDeletion"> + <property name="maximumSize"> <size> - <width>20</width> + <width>16777215</width> <height>40</height> </size> </property> - </spacer> - </item> - <item alignment="Qt::AlignHCenter"> - <widget class="QLabel" name="deletionLabel1"> + <property name="font"> + <font> + <pointsize>8</pointsize> + </font> + </property> <property name="text"> - <string>Do you really want to delete account ?</string> + <string>Do you really want to delete the following account?</string> </property> </widget> </item> <item alignment="Qt::AlignHCenter"> - <widget class="QLabel" name="accountAliasLabel"> + <widget class="QLabel" name="labelBestId"> <property name="minimumSize"> <size> <width>30</width> <height>0</height> </size> </property> + <property name="font"> + <font> + <pointsize>10</pointsize> + </font> + </property> <property name="text"> <string/> </property> + <property name="alignment"> + <set>Qt::AlignCenter</set> + </property> </widget> </item> <item alignment="Qt::AlignHCenter"> - <widget class="QLabel" name="accountIdLabel"> + <widget class="QLabel" name="labelAccountHash"> <property name="minimumSize"> <size> <width>20</width> <height>0</height> </size> </property> + <property name="font"> + <font> + <pointsize>10</pointsize> + </font> + </property> <property name="text"> <string/> </property> + <property name="alignment"> + <set>Qt::AlignCenter</set> + </property> </widget> </item> - <item alignment="Qt::AlignHCenter"> - <widget class="QLabel" name="deletionLabel2"> - <property name="text"> - <string>This action is irrevocable</string> + <item> + <spacer name="verticalSpacer_3"> + <property name="orientation"> + <enum>Qt::Vertical</enum> </property> - </widget> + <property name="sizeType"> + <enum>QSizePolicy::Fixed</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>20</width> + <height>10</height> + </size> + </property> + </spacer> </item> <item alignment="Qt::AlignHCenter"> - <widget class="QLabel" name="warningLabel"> + <widget class="QLabel" name="labelWarning"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Fixed" vsizetype="Fixed"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="minimumSize"> + <size> + <width>250</width> + <height>0</height> + </size> + </property> + <property name="styleSheet"> + <string notr="true">color: red;</string> + </property> <property name="text"> - <string>If this account hasn't been exported, or added to another device, it will be lost</string> + <string>If this account hasn't been exported, or added to another device, it will be irrevocably lost.</string> </property> <property name="alignment"> <set>Qt::AlignCenter</set> @@ -78,6 +140,9 @@ <property name="wordWrap"> <bool>true</bool> </property> + <property name="margin"> + <number>3</number> + </property> </widget> </item> <item> @@ -85,10 +150,13 @@ <property name="orientation"> <enum>Qt::Vertical</enum> </property> + <property name="sizeType"> + <enum>QSizePolicy::Fixed</enum> + </property> <property name="sizeHint" stdset="0"> <size> <width>20</width> - <height>40</height> + <height>20</height> </size> </property> </spacer> @@ -121,9 +189,9 @@ </spacer> </item> <item> - <widget class="QPushButton" name="deleteCancelBtn"> + <widget class="QPushButton" name="btnDeleteAccept"> <property name="sizePolicy"> - <sizepolicy hsizetype="Minimum" vsizetype="Fixed"> + <sizepolicy hsizetype="Fixed" vsizetype="Fixed"> <horstretch>0</horstretch> <verstretch>0</verstretch> </sizepolicy> @@ -134,11 +202,20 @@ <height>30</height> </size> </property> + <property name="maximumSize"> + <size> + <width>130</width> + <height>30</height> + </size> + </property> <property name="toolTip"> - <string>Cancel contact deletion button</string> + <string>Permanently delete account</string> + </property> + <property name="styleSheet"> + <string notr="true">border: 0px;; border-radius:3px; background: rgb(245, 245, 245);</string> </property> <property name="text"> - <string>Cancel</string> + <string>Delete</string> </property> </widget> </item> @@ -156,7 +233,13 @@ </spacer> </item> <item> - <widget class="QPushButton" name="deleteAcceptBtn"> + <widget class="QPushButton" name="btnDeleteCancel"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Minimum" vsizetype="Fixed"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> <property name="minimumSize"> <size> <width>130</width> @@ -164,10 +247,13 @@ </size> </property> <property name="toolTip"> - <string>Validate contact deletion button</string> + <string>Cancel account deletion</string> + </property> + <property name="styleSheet"> + <string notr="true">border: 0px; border-radius:3px; background: rgb(245, 245, 245);</string> </property> <property name="text"> - <string>Ok</string> + <string>Cancel</string> </property> </widget> </item> @@ -186,6 +272,22 @@ </item> </layout> </item> + <item> + <spacer name="verticalSpacer"> + <property name="orientation"> + <enum>Qt::Vertical</enum> + </property> + <property name="sizeType"> + <enum>QSizePolicy::Fixed</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>20</width> + <height>5</height> + </size> + </property> + </spacer> + </item> </layout> </widget> <resources/> diff --git a/deviceeditwidget.ui b/deviceeditwidget.ui new file mode 100644 index 0000000..5ebc245 --- /dev/null +++ b/deviceeditwidget.ui @@ -0,0 +1,42 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>Form</class> + <widget class="QWidget" name="Form"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>324</width> + <height>120</height> + </rect> + </property> + <property name="windowTitle"> + <string>Form</string> + </property> + <widget class="QLineEdit" name="lineEdit"> + <property name="geometry"> + <rect> + <x>30</x> + <y>20</y> + <width>113</width> + <height>20</height> + </rect> + </property> + </widget> + <widget class="QPushButton" name="pushButton"> + <property name="geometry"> + <rect> + <x>240</x> + <y>50</y> + <width>75</width> + <height>23</height> + </rect> + </property> + <property name="text"> + <string>PushButton</string> + </property> + </widget> + </widget> + <resources/> + <connections/> +</ui> diff --git a/images/ajax-loader.gif b/images/ajax-loader.gif new file mode 100644 index 0000000000000000000000000000000000000000..f2a1bc0c6f545e20e631a96e8e92f9822e75d046 GIT binary patch literal 673 zcmZ?wbhEHb6krfw_{6~Q|Nnmm28Kh24mmkFF)%PBB_%aAHBFi{N%5bQb5UwyNotBh zd1gt5LSj~8MNWQVie6@3T0Vo~PZkC)1_lPj|J;7AA;Hd$0j@@R2F#2M3=BF93=9k) z!x@;3Id<LoXK>0hTR54+ibHY^yWfm7PS=fwhjxj~Jh)9S;mD!F3%bz~mUox2TT1Y- zdu2cOV1OFUh-{7t$Q-{OMFr^=p4}Usb-5He1%@OTN-8AyxJFB@sFB%PdjD;r1bc(R zb%{r9&XSu{RkVbl1~DNUWX7?}NLl-o<B17priAIUwI<8(eUbG0=;@R=V|9Vd2d*=l z_sSewq0JQeR{RfR^I?9Yl_^s5_p?BaVn#N~m}6Ixs`e?Pwux`%gvGaZFXL=g<Y6&% zX-||9T;<lZ;i5cqQc&z?TX_Qu9jX2kONuOgV18pkHphr#SCP85*YgyS4-%h!8hO;p z4kyGUg-mH}*(sM1>7;r7l!E}X+)Eqz!)jo2f+oR?VMR8^m}8g1p$V4ak4v8Kxi!x~ z^0>?cMLnl&b5Dh@S!Bq=#w}8uxO;=?_o<AH1{*j#chAq&^n#hghHQ=zD5yVh3f`O( z8as>e-L1lcsR<o-6X)DDnbzv)cGN&*Lc;8AjJzy|90X<?HXOQkZX(PWb_`<-PI<0Q zb-FS~^ST@d$6<xO<Ar=Ih6XE7ZCDo|aVSxOJ?z#}CWX=@iKcncf)f}RtU(C}i~;o{ B(boU~ literal 0 HcmV?d00001 diff --git a/images/icons/round-add-24px.svg b/images/icons/round-add-24px.svg new file mode 100644 index 0000000..a2fcb8e --- /dev/null +++ b/images/icons/round-add-24px.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><path fill="none" d="M0 0h24v24H0V0z"/><path d="M18 13h-5v5c0 .55-.45 1-1 1s-1-.45-1-1v-5H6c-.55 0-1-.45-1-1s.45-1 1-1h5V6c0-.55.45-1 1-1s1 .45 1 1v5h5c.55 0 1 .45 1 1s-.45 1-1 1z"/></svg> \ No newline at end of file diff --git a/images/icons/round-arrow_drop_down-24px.svg b/images/icons/round-arrow_drop_down-24px.svg new file mode 100644 index 0000000..49addb2 --- /dev/null +++ b/images/icons/round-arrow_drop_down-24px.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><path fill="none" d="M0 0h24v24H0V0z"/><path d="M8.71 11.71l2.59 2.59c.39.39 1.02.39 1.41 0l2.59-2.59c.63-.63.18-1.71-.71-1.71H9.41c-.89 0-1.33 1.08-.7 1.71z"/></svg> \ No newline at end of file diff --git a/images/icons/round-arrow_drop_up-24px.svg b/images/icons/round-arrow_drop_up-24px.svg new file mode 100644 index 0000000..f5477ae --- /dev/null +++ b/images/icons/round-arrow_drop_up-24px.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><path fill="none" d="M0 0h24v24H0V0z"/><path d="M8.71 12.29L11.3 9.7c.39-.39 1.02-.39 1.41 0l2.59 2.59c.63.63.18 1.71-.71 1.71H9.41c-.89 0-1.33-1.08-.7-1.71z"/></svg> \ No newline at end of file diff --git a/images/icons/round-arrow_right-24px.svg b/images/icons/round-arrow_right-24px.svg new file mode 100644 index 0000000..81124fa --- /dev/null +++ b/images/icons/round-arrow_right-24px.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><path fill="none" d="M0 0h24v24H0V0z"/><path d="M11.71 15.29l2.59-2.59c.39-.39.39-1.02 0-1.41L11.71 8.7c-.63-.62-1.71-.18-1.71.71v5.17c0 .9 1.08 1.34 1.71.71z"/></svg> \ No newline at end of file diff --git a/images/icons/round-check_circle-24px.svg b/images/icons/round-check_circle-24px.svg new file mode 100644 index 0000000..7466a89 --- /dev/null +++ b/images/icons/round-check_circle-24px.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><path fill="none" d="M0 0h24v24H0V0z"/><path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zM9.29 16.29L5.7 12.7c-.39-.39-.39-1.02 0-1.41.39-.39 1.02-.39 1.41 0L10 14.17l6.88-6.88c.39-.39 1.02-.39 1.41 0 .39.39.39 1.02 0 1.41l-7.59 7.59c-.38.39-1.02.39-1.41 0z"/></svg> \ No newline at end of file diff --git a/images/icons/round-close-24px.svg b/images/icons/round-close-24px.svg new file mode 100644 index 0000000..e7261bc --- /dev/null +++ b/images/icons/round-close-24px.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><path fill="none" d="M0 0h24v24H0V0z"/><path d="M18.3 5.71c-.39-.39-1.02-.39-1.41 0L12 10.59 7.11 5.7c-.39-.39-1.02-.39-1.41 0-.39.39-.39 1.02 0 1.41L10.59 12 5.7 16.89c-.39.39-.39 1.02 0 1.41.39.39 1.02.39 1.41 0L12 13.41l4.89 4.89c.39.39 1.02.39 1.41 0 .39-.39.39-1.02 0-1.41L13.41 12l4.89-4.89c.38-.38.38-1.02 0-1.4z"/></svg> \ No newline at end of file diff --git a/images/icons/round-edit-24px.svg b/images/icons/round-edit-24px.svg new file mode 100644 index 0000000..8d6bc17 --- /dev/null +++ b/images/icons/round-edit-24px.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><path fill="none" d="M0 0h24v24H0V0z"/><path d="M3 17.46v3.04c0 .28.22.5.5.5h3.04c.13 0 .26-.05.35-.15L17.81 9.94l-3.75-3.75L3.15 17.1c-.1.1-.15.22-.15.36zM20.71 7.04c.39-.39.39-1.02 0-1.41l-2.34-2.34c-.39-.39-1.02-.39-1.41 0l-1.83 1.83 3.75 3.75 1.83-1.83z"/></svg> \ No newline at end of file diff --git a/images/icons/round-error-24px.svg b/images/icons/round-error-24px.svg new file mode 100644 index 0000000..3daa478 --- /dev/null +++ b/images/icons/round-error-24px.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm0 11c-.55 0-1-.45-1-1V8c0-.55.45-1 1-1s1 .45 1 1v4c0 .55-.45 1-1 1zm1 4h-2v-2h2v2z"/></svg> \ No newline at end of file diff --git a/images/icons/round-folder-24px.svg b/images/icons/round-folder-24px.svg new file mode 100644 index 0000000..4f02e22 --- /dev/null +++ b/images/icons/round-folder-24px.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><path fill="none" d="M0 0h24v24H0V0z"/><path d="M10.59 4.59C10.21 4.21 9.7 4 9.17 4H4c-1.1 0-1.99.9-1.99 2L2 18c0 1.1.9 2 2 2h16c1.1 0 2-.9 2-2V8c0-1.1-.9-2-2-2h-8l-1.41-1.41z"/></svg> \ No newline at end of file diff --git a/images/icons/round-remove_circle-24px.svg b/images/icons/round-remove_circle-24px.svg new file mode 100644 index 0000000..9413863 --- /dev/null +++ b/images/icons/round-remove_circle-24px.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><path fill="none" d="M0 0h24v24H0V0z"/><path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm4 11H8c-.55 0-1-.45-1-1s.45-1 1-1h8c.55 0 1 .45 1 1s-.45 1-1 1z"/></svg> \ No newline at end of file diff --git a/images/icons/round-save_alt-24px.svg b/images/icons/round-save_alt-24px.svg new file mode 100644 index 0000000..07b2cb5 --- /dev/null +++ b/images/icons/round-save_alt-24px.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><path fill="none" d="M0 0h24v24H0V0z"/><path d="M19 13v5c0 .55-.45 1-1 1H6c-.55 0-1-.45-1-1v-5c0-.55-.45-1-1-1s-1 .45-1 1v6c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2v-6c0-.55-.45-1-1-1s-1 .45-1 1zm-6-.33l1.88-1.88c.39-.39 1.02-.39 1.41 0 .39.39.39 1.02 0 1.41l-3.59 3.59c-.39.39-1.02.39-1.41 0L7.7 12.2c-.39-.39-.39-1.02 0-1.41.39-.39 1.02-.39 1.41 0L11 12.67V4c0-.55.45-1 1-1s1 .45 1 1v8.67z"/></svg> \ No newline at end of file diff --git a/images/icons/round-undo-24px.svg b/images/icons/round-undo-24px.svg new file mode 100644 index 0000000..c0e9241 --- /dev/null +++ b/images/icons/round-undo-24px.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><path fill="none" d="M0 0h24v24H0V0z"/><path d="M12.5 8c-2.65 0-5.05.99-6.9 2.6L3.71 8.71C3.08 8.08 2 8.52 2 9.41V15c0 .55.45 1 1 1h5.59c.89 0 1.34-1.08.71-1.71l-1.91-1.91c1.39-1.16 3.16-1.88 5.12-1.88 3.16 0 5.89 1.84 7.19 4.5.27.56.91.84 1.5.64.71-.23 1.07-1.04.75-1.72C20.23 10.42 16.65 8 12.5 8z"/></svg> \ No newline at end of file diff --git a/invitebuttonswidget.ui b/invitebuttonswidget.ui index e3caf2e..bb6169c 100644 --- a/invitebuttonswidget.ui +++ b/invitebuttonswidget.ui @@ -7,7 +7,7 @@ <x>0</x> <y>0</y> <width>323</width> - <height>114</height> + <height>120</height> </rect> </property> <property name="sizePolicy"> diff --git a/linkdevwidget.cpp b/linkdevwidget.cpp new file mode 100644 index 0000000..4315971 --- /dev/null +++ b/linkdevwidget.cpp @@ -0,0 +1,80 @@ +/*************************************************************************** + * Copyright (C) 2018 by Savoir-faire Linux * + * Author: Isa Nanic <isa.nanic@savoirfairelinux.com> * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 3 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program. If not, see <https://www.gnu.org/licenses/>. * + **************************************************************************/ + +#include "linkdevwidget.h" + +#include <QMovie> + +LinkDevWidget::LinkDevWidget(QWidget* parent) + : QWidget(parent), + ui(new Ui::LinkDevWidget) +{ + ui->setupUi(this); + + if (LRCInstance::getCurrAccConfig().archiveHasPassword) { + ui->stackedWidget->setCurrentWidget(ui->start); + } else { + setGeneratingPage(); + } + + connect(ui->enterBtn, &QPushButton::clicked, this, &LinkDevWidget::setGeneratingPage); + connect(&LRCInstance::accountModel(), &lrc::api::NewAccountModel::exportOnRingEnded, + this, &LinkDevWidget::setExportPage); +} + +LinkDevWidget::~LinkDevWidget() +{ + delete ui; +} + +void +LinkDevWidget::setGeneratingPage() +{ + ui->stackedWidget->setCurrentWidget(ui->middle); + + QMovie* movie = new QMovie(":/images/ajax-loader.gif"); + ui->spinningLabel->setMovie(movie); + ui->spinningLabel->show(); + movie->start(); + + LRCInstance::accountModel().exportOnRing(LRCInstance::getCurrAccId(), ui->passwordLineEdit->text().toStdString()); +} + +void +LinkDevWidget::setExportPage(const std::string& accountId, lrc::api::account::ExportOnRingStatus status, const std::string& pin) +{ + Q_UNUSED(accountId); + ui->stackedWidget->setCurrentWidget(ui->end); + + switch (status) { + case lrc::api::account::ExportOnRingStatus::WRONG_PASSWORD: + ui->label_4->setText(tr("Your account password was incorrect")); + ui->label_5->hide(); + ui->label_6->hide(); + break; + + case lrc::api::account::ExportOnRingStatus::SUCCESS: + ui->label_5->setText(QString::fromStdString(pin)); + break; + + default: + ui->label_4->setText(tr("Something went wrong.\nPlease try again later.")); + ui->label_5->hide(); + ui->label_6->hide(); + } +} \ No newline at end of file diff --git a/linkdevwidget.h b/linkdevwidget.h new file mode 100644 index 0000000..740cca2 --- /dev/null +++ b/linkdevwidget.h @@ -0,0 +1,49 @@ +/*************************************************************************** + * Copyright (C) 2018 by Savoir-faire Linux * + * Author: Isa Nanic <isa.nanic@savoirfairelinux.com> * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 3 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program. If not, see <https://www.gnu.org/licenses/>. * + **************************************************************************/ + +#pragma once +#include <QPushButton> + +#include "lrcinstance.h" +#include "ui_linkdevwidget.h" + + +namespace Ui { + class LinkDevWidget; +} + +class LinkDevWidget : public QWidget +{ + Q_OBJECT + LinkDevWidget(const LinkDevWidget& cpy); + +public: + explicit LinkDevWidget(QWidget* parent = nullptr); + ~LinkDevWidget(); + inline const QPushButton* cancelBtn() const { return ui->cancelBtn; }; + inline const QPushButton* enterBtn() const { return ui->enterBtn; }; + inline const QPushButton* endCancelBtn() const { return ui->closePushButton; }; + + +private: + Ui::LinkDevWidget* ui; + +private slots: + void setGeneratingPage(); + void setExportPage(const std::string& accountId, lrc::api::account::ExportOnRingStatus status, const std::string& pin); +}; diff --git a/linkdevwidget.ui b/linkdevwidget.ui new file mode 100644 index 0000000..b9bc7b7 --- /dev/null +++ b/linkdevwidget.ui @@ -0,0 +1,611 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>LinkDevWidget</class> + <widget class="QWidget" name="LinkDevWidget"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>744</width> + <height>848</height> + </rect> + </property> + <property name="windowTitle"> + <string>Form</string> + </property> + <widget class="QWidget" name="verticalLayoutWidget"> + <property name="geometry"> + <rect> + <x>9</x> + <y>9</y> + <width>701</width> + <height>791</height> + </rect> + </property> + <layout class="QVBoxLayout" name="verticalLayout" stretch="0"> + <item> + <widget class="QStackedWidget" name="stackedWidget"> + <property name="currentIndex"> + <number>1</number> + </property> + <widget class="QWidget" name="start"> + <widget class="QWidget" name="verticalLayoutWidget_2"> + <property name="geometry"> + <rect> + <x>9</x> + <y>19</y> + <width>681</width> + <height>761</height> + </rect> + </property> + <layout class="QVBoxLayout" name="verticalLayout_2"> + <item> + <spacer name="verticalSpacer"> + <property name="orientation"> + <enum>Qt::Vertical</enum> + </property> + <property name="sizeType"> + <enum>QSizePolicy::MinimumExpanding</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>20</width> + <height>40</height> + </size> + </property> + </spacer> + </item> + <item> + <layout class="QHBoxLayout" name="horizontalLayout" stretch="1,0,1"> + <item> + <spacer name="horizontalSpacer"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>40</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + <item> + <widget class="QLabel" name="label"> + <property name="font"> + <font> + <pointsize>10</pointsize> + </font> + </property> + <property name="text"> + <string>Add A New Device</string> + </property> + </widget> + </item> + <item> + <spacer name="horizontalSpacer_2"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeType"> + <enum>QSizePolicy::Minimum</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>40</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + </layout> + </item> + <item> + <spacer name="verticalSpacer_3"> + <property name="orientation"> + <enum>Qt::Vertical</enum> + </property> + <property name="sizeType"> + <enum>QSizePolicy::Fixed</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>20</width> + <height>40</height> + </size> + </property> + </spacer> + </item> + <item> + <layout class="QHBoxLayout" name="horizontalLayout_5"> + <item> + <spacer name="horizontalSpacer_3"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>40</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + <item> + <widget class="QLabel" name="label_2"> + <property name="text"> + <string>To add a new device, enter your account password:</string> + </property> + </widget> + </item> + <item> + <spacer name="horizontalSpacer_4"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>40</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + </layout> + </item> + <item> + <layout class="QHBoxLayout" name="horizontalLayout_2"> + <item> + <spacer name="horizontalSpacer_7"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>40</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + <item> + <widget class="QLineEdit" name="passwordLineEdit"> + <property name="minimumSize"> + <size> + <width>250</width> + <height>0</height> + </size> + </property> + <property name="echoMode"> + <enum>QLineEdit::Password</enum> + </property> + <property name="alignment"> + <set>Qt::AlignCenter</set> + </property> + </widget> + </item> + <item> + <spacer name="horizontalSpacer_8"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>40</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + </layout> + </item> + <item> + <layout class="QHBoxLayout" name="horizontalLayout_3"> + <item> + <spacer name="horizontalSpacer_9"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>40</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + <item> + <widget class="QPushButton" name="cancelBtn"> + <property name="text"> + <string>Cancel</string> + </property> + </widget> + </item> + <item> + <spacer name="horizontalSpacer_11"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeType"> + <enum>QSizePolicy::Fixed</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>40</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + <item> + <widget class="QPushButton" name="enterBtn"> + <property name="text"> + <string>Enter</string> + </property> + </widget> + </item> + <item> + <spacer name="horizontalSpacer_10"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>40</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + </layout> + </item> + <item> + <spacer name="verticalSpacer_2"> + <property name="orientation"> + <enum>Qt::Vertical</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>20</width> + <height>40</height> + </size> + </property> + </spacer> + </item> + </layout> + </widget> + </widget> + <widget class="QWidget" name="middle"> + <widget class="QWidget" name="verticalLayoutWidget_3"> + <property name="geometry"> + <rect> + <x>14</x> + <y>9</y> + <width>671</width> + <height>771</height> + </rect> + </property> + <layout class="QVBoxLayout" name="verticalLayout_3"> + <item> + <spacer name="verticalSpacer_4"> + <property name="orientation"> + <enum>Qt::Vertical</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>20</width> + <height>40</height> + </size> + </property> + </spacer> + </item> + <item> + <widget class="QWidget" name="widget" native="true"> + <layout class="QVBoxLayout" name="verticalLayout_5"> + <item> + <layout class="QHBoxLayout" name="horizontalLayout_6" stretch="1,0,1"> + <item> + <spacer name="horizontalSpacer_12"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>40</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + <item> + <widget class="QLabel" name="label_3"> + <property name="text"> + <string>Exporting account on the ring</string> + </property> + </widget> + </item> + <item> + <spacer name="horizontalSpacer_13"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>40</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + </layout> + </item> + <item> + <layout class="QHBoxLayout" name="horizontalLayout_4" stretch="1,0,1"> + <item> + <spacer name="horizontalSpacer_5"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>40</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + <item> + <widget class="QLabel" name="spinningLabel"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Fixed" vsizetype="Fixed"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="minimumSize"> + <size> + <width>50</width> + <height>50</height> + </size> + </property> + <property name="maximumSize"> + <size> + <width>50</width> + <height>50</height> + </size> + </property> + <property name="text"> + <string/> + </property> + </widget> + </item> + <item> + <spacer name="horizontalSpacer_6"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>40</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + </layout> + </item> + </layout> + </widget> + </item> + <item> + <spacer name="verticalSpacer_5"> + <property name="orientation"> + <enum>Qt::Vertical</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>20</width> + <height>40</height> + </size> + </property> + </spacer> + </item> + </layout> + </widget> + </widget> + <widget class="QWidget" name="end"> + <widget class="QWidget" name="verticalLayoutWidget_4"> + <property name="geometry"> + <rect> + <x>10</x> + <y>10</y> + <width>681</width> + <height>771</height> + </rect> + </property> + <layout class="QVBoxLayout" name="verticalLayout_4"> + <item> + <spacer name="verticalSpacer_6"> + <property name="orientation"> + <enum>Qt::Vertical</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>20</width> + <height>40</height> + </size> + </property> + </spacer> + </item> + <item> + <layout class="QHBoxLayout" name="horizontalLayout_7"> + <item> + <spacer name="horizontalSpacer_14"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>40</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + <item> + <widget class="QLabel" name="label_4"> + <property name="text"> + <string>Your generated pin:</string> + </property> + </widget> + </item> + <item> + <spacer name="horizontalSpacer_15"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>40</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + </layout> + </item> + <item> + <layout class="QHBoxLayout" name="horizontalLayout_8"> + <item> + <spacer name="horizontalSpacer_16"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>40</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + <item> + <widget class="QLabel" name="label_5"> + <property name="text"> + <string/> + </property> + </widget> + </item> + <item> + <spacer name="horizontalSpacer_17"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>40</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + </layout> + </item> + <item> + <layout class="QHBoxLayout" name="horizontalLayout_9"> + <item> + <spacer name="horizontalSpacer_18"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>40</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + <item> + <widget class="QLabel" name="label_6"> + <property name="text"> + <string>This pin and the account password should be entered in your device within 5 minutes.</string> + </property> + </widget> + </item> + <item> + <spacer name="horizontalSpacer_19"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>40</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + </layout> + </item> + <item> + <layout class="QHBoxLayout" name="horizontalLayout_10"> + <item> + <spacer name="horizontalSpacer_20"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>40</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + <item> + <widget class="QPushButton" name="closePushButton"> + <property name="text"> + <string>Close</string> + </property> + </widget> + </item> + <item> + <spacer name="horizontalSpacer_21"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>40</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + </layout> + </item> + <item> + <spacer name="verticalSpacer_7"> + <property name="orientation"> + <enum>Qt::Vertical</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>20</width> + <height>40</height> + </size> + </property> + </spacer> + </item> + </layout> + </widget> + </widget> + </widget> + </item> + </layout> + </widget> + </widget> + <resources/> + <connections/> +</ui> diff --git a/lrcinstance.h b/lrcinstance.h index 1377dd6..57fe69b 100644 --- a/lrcinstance.h +++ b/lrcinstance.h @@ -1,6 +1,7 @@ /************************************************************************** | Copyright (C) 2015-2018 by Savoir-faire Linux | | Author: Andreas Traczyk <andreas.traczyk@savoirfairelinux.com> | +| Author: Isa Nanic <isa.nanic@savoirfairelinux.com> | | | | This program is free software; you can redistribute it and/or modify | | it under the terms of the GNU General Public License as published by | @@ -13,7 +14,7 @@ | GNU General Public License for more details. | | | | You should have received a copy of the GNU General Public License | -| along with this program. If not, see <http://www.gnu.org/licenses/>. | +| along with this program. If not, see <https://www.gnu.org/licenses/>. | **************************************************************************/ #pragma once @@ -22,6 +23,9 @@ #endif #include <QSettings> +#include <QRegularExpression> +#include <QPixmap> +#include <QBuffer> #include "api/lrc.h" #include "api/account.h" @@ -33,6 +37,10 @@ #include "api/contact.h" #include "api/datatransfermodel.h" #include "api/conversationmodel.h" +#include "accountlistmodel.h" + +#include "account.h" +//#include "instancemanager.cpp" #include <settingskey.h> @@ -50,19 +58,25 @@ public: static const lrc::api::NewAccountModel& accountModel() { return instance().lrc_->getAccountModel(); }; + static lrc::api::NewAccountModel* editableAccountModel() { + return const_cast<lrc::api::NewAccountModel*>(&instance().lrc_->getAccountModel()); + }; static const lrc::api::BehaviorController& behaviorController() { return instance().lrc_->getBehaviorController(); }; static const lrc::api::DataTransferModel& dataTransferModel() { return instance().lrc_->getDataTransferModel(); }; + static lrc::api::DataTransferModel* editableDataTransferModel() { + return const_cast<lrc::api::DataTransferModel*>(&instance().lrc_->getDataTransferModel()); + }; static bool isConnected() { return instance().lrc_->isConnected(); }; static const lrc::api::account::Info& getCurrentAccountInfo() { - return accountModel().getAccountInfo(instance().selectedAccountId); + return accountModel().getAccountInfo(getCurrAccId()); }; static lrc::api::ConversationModel* @@ -75,8 +89,15 @@ public: return getCurrentAccountInfo().callModel.get(); }; - static const std::string& getSelectedAccountId() { - return instance().selectedAccountId; + static const int getAccountNumList() { + return accountModel().getAccountList().size(); + }; + + static const std::string& getCurrAccId() { + if (!instance().selectedAccountId.empty()) { + return instance().selectedAccountId; + } + return accountModel().getAccountList()[0]; }; static void setSelectedAccountId(const std::string& accountId) { @@ -101,8 +122,36 @@ public: } }; + static const int getCurrentAccountIndex(){ + for (int i = 0; i < accountModel().getAccountList().size(); i++) { + if (accountModel().getAccountList()[i] == getCurrAccId()) { + return i; + } + } + return -1; + }; + + static const QPixmap getCurrAccPixmap() { + return instance().accountListModel_.data(instance().accountListModel_ + .index(getCurrentAccountIndex()), AccountListModel::Role::Picture).value<QPixmap>(); + }; + + static void setCurrAccAvatar(const std::string& avatar) { + instance().editableAccountModel()->setAvatar(getCurrAccId(), avatar); + }; + + static void setCurrAccDisplayName(const std::string& alias) { + instance().editableAccountModel()->setAlias(getCurrAccId(), alias); + }; + + static const lrc::api::account::ConfProperties_t& getCurrAccConfig() { + return instance().getCurrentAccountInfo().confProperties; + } + + private: std::unique_ptr<lrc::api::Lrc> lrc_; + AccountListModel accountListModel_; static LRCInstance& instance() { static LRCInstance instance_; @@ -115,4 +164,4 @@ private: std::string selectedAccountId; std::string selectedConvUid; -}; \ No newline at end of file +}; diff --git a/mainwindow.cpp b/mainwindow.cpp index 176853c..5ba06da 100644 --- a/mainwindow.cpp +++ b/mainwindow.cpp @@ -39,9 +39,11 @@ #include "utils.h" #include "wizarddialog.h" #include "version.h" +#include "settingswidget.h" MainWindow::MainWindow(QWidget* parent) : QMainWindow(parent), + ui(new Ui::MainWindow) { ui->setupUi(this); @@ -56,7 +58,7 @@ MainWindow::MainWindow(QWidget* parent) : Utils::setStackWidget(ui->navStack, ui->navStack->widget(scr)); }); - connect(ui->configurationwidget, &ConfigurationWidget::NavigationRequested, + connect(ui->settingswidget, &SettingsWidget::NavigationRequested, [this](ScreenEnum scr) { Utils::setStackWidget(ui->navStack, ui->navStack->widget(scr)); if (scr == ScreenEnum::CallScreen) { @@ -64,6 +66,11 @@ MainWindow::MainWindow(QWidget* parent) : } }); + connect(ui->callwidget, &CallWidget::setLeftSizeWidget, [=](int size) { + ui->settingswidget->updateSettings(size); + } + ); + QIcon icon(":images/ring.png"); this->setWindowIcon(icon); diff --git a/mainwindow.ui b/mainwindow.ui index f4c675a..32e75f4 100644 --- a/mainwindow.ui +++ b/mainwindow.ui @@ -465,6 +465,7 @@ <widget class="QStackedWidget" name="navStack"> <widget class="WizardWidget" name="wizardwidget"/> <widget class="CallWidget" name="callwidget"/> + <widget class="SettingsWidget" name="settingswidget"/> <widget class="ConfigurationWidget" name="configurationwidget"/> </widget> </item> diff --git a/navwidget.h b/navwidget.h index 189250b..402d5f6 100644 --- a/navwidget.h +++ b/navwidget.h @@ -25,6 +25,7 @@ enum ScreenEnum { WizardScreen, CallScreen, ConfScreen, + SetttingsScreen, END }; diff --git a/passworddialog.cpp b/passworddialog.cpp new file mode 100644 index 0000000..53084a7 --- /dev/null +++ b/passworddialog.cpp @@ -0,0 +1,108 @@ +/************************************************************************** +* Copyright (C) 2018 by Savoir-faire Linux * +* Author: Isa Nanic <isa.nanic@savoirfairelinux.com> * +* * +* This program is free software; you can redistribute it and/or modify * +* it under the terms of the GNU General Public License as published by * +* the Free Software Foundation; either version 3 of the License, or * +* (at your option) any later version. * +* * +* This program is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU General Public License for more details. * +* * +* You should have received a copy of the GNU General Public License * +* along with this program. If not, see <http://www.gnu.org/licenses/>. * +**************************************************************************/ +#include <QTimer> + +#include "passworddialog.h" +#include "ui_passworddialog.h" + +#include "lrcinstance.h" + +PasswordDialog::PasswordDialog(QWidget* parent) + :ui(new Ui::PasswordDialog), + QDialog(parent) +{ + ui->setupUi(this); + + ui->currentPsswdEdit->setEchoMode(QLineEdit::Password); + ui->newPsswdEdit->setEchoMode(QLineEdit::Password); + ui->confirmNewPsswdEdit->setEchoMode(QLineEdit::Password); + + if (!LRCInstance::getCurrAccConfig().archiveHasPassword) { + ui->currentPsswdEdit->hide(); + } else { + ui->currentPsswdEdit->show(); + } + + connect(ui->currentPsswdEdit, &QLineEdit::textChanged, this, &PasswordDialog::validateNewPsswd); + connect(ui->newPsswdEdit, &QLineEdit::textChanged, this, &PasswordDialog::validateNewPsswd); + connect(ui->confirmNewPsswdEdit, &QLineEdit::textChanged, this, &PasswordDialog::validateNewPsswd); + + connect(ui->confirmButton, &QPushButton::clicked, [=]() { + savePassword(); + } + ); + + connect(ui->cancelButton, &QPushButton::clicked, this, &PasswordDialog::closeSlot); + + ui->confirmButton->setEnabled(false); +} + +PasswordDialog::~PasswordDialog() +{ + delete ui; +} + +// only sets new password if both new passwords match +void +PasswordDialog::validateNewPsswd() +{ + ui->newPsswdEdit->setStyleSheet("border: 1px solid red;"); + ui->confirmNewPsswdEdit->setStyleSheet("border: 1px solid red;"); + + if (ui->newPsswdEdit->text() == ui->confirmNewPsswdEdit->text()) { + ui->newPsswdEdit->setStyleSheet("border: 1px solid green;"); + ui->confirmNewPsswdEdit->setStyleSheet("border: 1px solid green;"); + } + freeConfirmButton(); +} + +void +PasswordDialog::freeConfirmButton() +{ + if (ui->newPsswdEdit->text() == ui->confirmNewPsswdEdit->text()) { + ui->confirmButton->setEnabled(true); + } + else { + ui->confirmButton->setEnabled(false); + } +} + +void +PasswordDialog::savePassword() +{ + if (LRCInstance::editableAccountModel()->changeAccountPassword(LRCInstance::getCurrAccId(), + ui->currentPsswdEdit->text().toStdString(), ui->newPsswdEdit->text().toStdString())) { + ui->userMessageLabel->setText(tr("Password Changed Successfully")); + + auto confProps = LRCInstance::accountModel().getAccountConfig(LRCInstance::getCurrAccId()); + ui->newPsswdEdit->text().isEmpty() ? confProps.archiveHasPassword = false : confProps.archiveHasPassword = true; + LRCInstance::editableAccountModel()->setAccountConfig(LRCInstance::getCurrAccId(), confProps); + + ui->cancelButton->hide(); + ui->confirmButton->hide(); + ui->currentPsswdEdit->hide(); + ui->newPsswdEdit->hide(); + ui->confirmNewPsswdEdit->hide(); + + QTimer::singleShot(900, this, SLOT(closeSlot())); + } + else { + ui->userMessageLabel->setText(tr("Current Password Incorrect")); + ui->currentPsswdEdit->setText(""); + } +} \ No newline at end of file diff --git a/passworddialog.h b/passworddialog.h new file mode 100644 index 0000000..6480191 --- /dev/null +++ b/passworddialog.h @@ -0,0 +1,44 @@ +/************************************************************************** +* Copyright (C) 2018 by Savoir-faire Linux * +* Author: Isa Nanic <isa.nanic@savoirfairelinux.com> * +* * +* This program is free software; you can redistribute it and/or modify * +* it under the terms of the GNU General Public License as published by * +* the Free Software Foundation; either version 3 of the License, or * +* (at your option) any later version. * +* * +* This program is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU General Public License for more details. * +* * +* You should have received a copy of the GNU General Public License * +* along with this program. If not, see <http://www.gnu.org/licenses/>. * +**************************************************************************/ + +#pragma once +#include <QDialog> + +namespace Ui { + class PasswordDialog; +} + +class PasswordDialog : public QDialog +{ + Q_OBJECT + PasswordDialog(const PasswordDialog& cpy); + +public: + PasswordDialog(QWidget* parent = nullptr); + ~PasswordDialog(); + +private slots: + void validateNewPsswd(); + inline void closeSlot() { done(0); }; + +private: + Ui::PasswordDialog* ui; + + void freeConfirmButton(); + void savePassword(); +}; \ No newline at end of file diff --git a/passworddialog.ui b/passworddialog.ui new file mode 100644 index 0000000..ee4e26c --- /dev/null +++ b/passworddialog.ui @@ -0,0 +1,205 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>PasswordDialog</class> + <widget class="PasswordDialog" name="PasswordDialog"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>458</width> + <height>250</height> + </rect> + </property> + <property name="sizePolicy"> + <sizepolicy hsizetype="Fixed" vsizetype="Fixed"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="minimumSize"> + <size> + <width>440</width> + <height>250</height> + </size> + </property> + <property name="maximumSize"> + <size> + <width>458</width> + <height>268</height> + </size> + </property> + <property name="windowTitle"> + <string>Change Account Password</string> + </property> + <property name="styleSheet"> + <string notr="true">background: white;</string> + </property> + <layout class="QVBoxLayout" name="verticalLayout"> + <property name="sizeConstraint"> + <enum>QLayout::SetDefaultConstraint</enum> + </property> + <item> + <layout class="QVBoxLayout" name="verticalLayout_5"> + <item> + <widget class="QLineEdit" name="currentPsswdEdit"> + <property name="minimumSize"> + <size> + <width>0</width> + <height>30</height> + </size> + </property> + <property name="layoutDirection"> + <enum>Qt::LeftToRight</enum> + </property> + <property name="text"> + <string/> + </property> + <property name="placeholderText"> + <string>Enter Current Password</string> + </property> + </widget> + </item> + <item> + <spacer name="verticalSpacer"> + <property name="orientation"> + <enum>Qt::Vertical</enum> + </property> + <property name="sizeType"> + <enum>QSizePolicy::Fixed</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>20</width> + <height>15</height> + </size> + </property> + </spacer> + </item> + <item> + <widget class="QLineEdit" name="newPsswdEdit"> + <property name="minimumSize"> + <size> + <width>0</width> + <height>30</height> + </size> + </property> + <property name="text"> + <string/> + </property> + <property name="placeholderText"> + <string>Enter New Password</string> + </property> + </widget> + </item> + <item> + <widget class="QLineEdit" name="confirmNewPsswdEdit"> + <property name="minimumSize"> + <size> + <width>0</width> + <height>30</height> + </size> + </property> + <property name="text"> + <string/> + </property> + <property name="placeholderText"> + <string>Confirm New Password</string> + </property> + </widget> + </item> + <item> + <layout class="QHBoxLayout" name="horizontalLayout"> + <property name="spacing"> + <number>20</number> + </property> + <property name="leftMargin"> + <number>20</number> + </property> + <property name="topMargin"> + <number>0</number> + </property> + <property name="rightMargin"> + <number>20</number> + </property> + <item> + <widget class="QPushButton" name="confirmButton"> + <property name="minimumSize"> + <size> + <width>0</width> + <height>30</height> + </size> + </property> + <property name="styleSheet"> + <string notr="true">background: rgb(237, 237, 237); border: 1px solid black;</string> + </property> + <property name="text"> + <string>Confirm</string> + </property> + <property name="flat"> + <bool>false</bool> + </property> + </widget> + </item> + <item> + <widget class="QPushButton" name="cancelButton"> + <property name="minimumSize"> + <size> + <width>0</width> + <height>30</height> + </size> + </property> + <property name="styleSheet"> + <string notr="true">background: rgb(237, 237, 237); border: 1px solid black;</string> + </property> + <property name="text"> + <string>Cancel</string> + </property> + <property name="flat"> + <bool>false</bool> + </property> + </widget> + </item> + </layout> + </item> + <item> + <widget class="QLabel" name="userMessageLabel"> + <property name="minimumSize"> + <size> + <width>0</width> + <height>25</height> + </size> + </property> + <property name="maximumSize"> + <size> + <width>16777215</width> + <height>25</height> + </size> + </property> + <property name="font"> + <font> + <pointsize>10</pointsize> + </font> + </property> + <property name="text"> + <string/> + </property> + <property name="alignment"> + <set>Qt::AlignCenter</set> + </property> + </widget> + </item> + </layout> + </item> + </layout> + </widget> + <customwidgets> + <customwidget> + <class>PasswordDialog</class> + <extends>QWidget</extends> + <header>passworddialog.h</header> + <container>1</container> + </customwidget> + </customwidgets> + <resources/> + <connections/> +</ui> diff --git a/photoboothdialog.ui b/photoboothdialog.ui index 748b015..ed799eb 100644 --- a/photoboothdialog.ui +++ b/photoboothdialog.ui @@ -6,8 +6,8 @@ <rect> <x>0</x> <y>0</y> - <width>791</width> - <height>456</height> + <width>709</width> + <height>386</height> </rect> </property> <property name="windowTitle"> diff --git a/regnamedialog.cpp b/regnamedialog.cpp new file mode 100644 index 0000000..5f9c732 --- /dev/null +++ b/regnamedialog.cpp @@ -0,0 +1,46 @@ +/************************************************************************** +* Copyright (C) 2018 by Savoir-faire Linux * +* Author: Isa Nanic <isa.nanic@savoirfairelinux.com> * +* * +* This program is free software; you can redistribute it and/or modify * +* it under the terms of the GNU General Public License as published by * +* the Free Software Foundation; either version 3 of the License, or * +* (at your option) any later version. * +* * +* This program is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU General Public License for more details. * +* * +* You should have received a copy of the GNU General Public License * +* along with this program. If not, see <http://www.gnu.org/licenses/>. * +**************************************************************************/ + +#include "regnamedialog.h" +#include "ui_regnamedialog.h" + +RegNameDialog::RegNameDialog(const QString& newRegName, QWidget* parent) + :ui(new Ui::RegNameDialog), + QDialog(parent) +{ + ui->setupUi(this); + ui->registeredName->setText(newRegName); + + connect(ui->confirmBtn, &QPushButton::clicked, [this]() { + accept(); + } + ); + + connect(ui->cancelBtn, &QPushButton::clicked, [this]() { + reject(); + } + ); + ui->registeredName->setTextInteractionFlags(Qt::TextSelectableByMouse); +} + +RegNameDialog::~RegNameDialog() +{ + disconnect(this); + delete ui; +} + diff --git a/regnamedialog.h b/regnamedialog.h new file mode 100644 index 0000000..d213d72 --- /dev/null +++ b/regnamedialog.h @@ -0,0 +1,37 @@ +/************************************************************************** +* Copyright (C) 2018 by Savoir-faire Linux * +* Author: Isa Nanic <isa.nanic@savoirfairelinux.com> * +* * +* This program is free software; you can redistribute it and/or modify * +* it under the terms of the GNU General Public License as published by * +* the Free Software Foundation; either version 3 of the License, or * +* (at your option) any later version. * +* * +* This program is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU General Public License for more details. * +* * +* You should have received a copy of the GNU General Public License * +* along with this program. If not, see <http://www.gnu.org/licenses/>. * +**************************************************************************/ + +#pragma once +#include <QDialog> + +namespace Ui { + class RegNameDialog; +} + +class RegNameDialog : public QDialog +{ + Q_OBJECT + RegNameDialog(const RegNameDialog& cpy); + +public: + RegNameDialog(const QString& newRegName = "", QWidget* parent = nullptr); + ~RegNameDialog(); + +private: + Ui::RegNameDialog* ui; +}; \ No newline at end of file diff --git a/regnamedialog.ui b/regnamedialog.ui new file mode 100644 index 0000000..028f120 --- /dev/null +++ b/regnamedialog.ui @@ -0,0 +1,119 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>RegNameDialog</class> + <widget class="QDialog" name="RegNameDialog"> + <property name="windowModality"> + <enum>Qt::ApplicationModal</enum> + </property> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>420</width> + <height>182</height> + </rect> + </property> + <property name="windowTitle"> + <string>Set Registered Name</string> + </property> + <property name="styleSheet"> + <string notr="true">background: white;</string> + </property> + <property name="modal"> + <bool>true</bool> + </property> + <widget class="QLabel" name="label"> + <property name="geometry"> + <rect> + <x>20</x> + <y>20</y> + <width>381</width> + <height>21</height> + </rect> + </property> + <property name="font"> + <font> + <pointsize>10</pointsize> + </font> + </property> + <property name="text"> + <string>Are you sure you would like to register this name?</string> + </property> + </widget> + <widget class="QLabel" name="label_2"> + <property name="geometry"> + <rect> + <x>30</x> + <y>50</y> + <width>351</width> + <height>16</height> + </rect> + </property> + <property name="text"> + <string>Once associated to this account, it cannot be changed.</string> + </property> + </widget> + <widget class="QPushButton" name="confirmBtn"> + <property name="geometry"> + <rect> + <x>70</x> + <y>140</y> + <width>151</width> + <height>23</height> + </rect> + </property> + <property name="text"> + <string>Confirm Registration</string> + </property> + </widget> + <widget class="QPushButton" name="cancelBtn"> + <property name="geometry"> + <rect> + <x>260</x> + <y>140</y> + <width>75</width> + <height>23</height> + </rect> + </property> + <property name="text"> + <string>Cancel</string> + </property> + </widget> + <widget class="QLabel" name="label_3"> + <property name="geometry"> + <rect> + <x>10</x> + <y>90</y> + <width>231</width> + <height>21</height> + </rect> + </property> + <property name="text"> + <string>Your new registered name would be:</string> + </property> + </widget> + <widget class="QLabel" name="registeredName"> + <property name="enabled"> + <bool>true</bool> + </property> + <property name="geometry"> + <rect> + <x>246</x> + <y>90</y> + <width>161</width> + <height>21</height> + </rect> + </property> + <property name="font"> + <font> + <pointsize>10</pointsize> + </font> + </property> + <property name="text"> + <string/> + </property> + </widget> + </widget> + <resources/> + <connections/> +</ui> diff --git a/ressources.qrc b/ressources.qrc index 51b40be..65db376 100644 --- a/ressources.qrc +++ b/ressources.qrc @@ -1,62 +1,76 @@ <RCC> - <qresource prefix="/"> - <file>stylesheet.css</file> - <file>images/ring.png</file> - <file>images/logo-ring-standard-coul.png</file> - <file>images/icons/ic_arrow_back_white_24dp.png</file> - <file>images/icons/ic_mic_off_white_24dp.png</file> - <file>images/icons/ic_person_add_white_24dp.png</file> - <file>images/icons/ic_search_black_18dp_2x.png</file> - <file>images/icons/ic_content_copy_white_24dp.png</file> - <file>images/icons/ic_send_white_24dp.png</file> - <file>images/icons/ic_group_add_white_24dp.png</file> - <file>images/icons/ic_videocam_off_white_24dp.png</file> - <file>images/icons/ic_high_quality_white_24dp.png</file> - <file>images/icons/ic_pause_white_24dp.png</file> - <file>images/icons/ic_chat_white_24dp.png</file> - <file>images/icons/ic_done_white_24dp.png</file> - <file>images/icons/ic_close_white_24dp.png</file> - <file>images/icons/ic_call_transfer_white_24px.png</file> - <file>images/icons/ic_pause_white_100px.png</file> - <file>images/icons/ic_videocam_white.png</file> - <file>images/icons/ic_add_black_18dp_2x.png</file> - <file>images/icons/ic_delete_black_18dp_2x.png</file> - <file>images/icons/ic_arrow_drop_down_black_18dp_2x.png</file> - <file>images/icons/ic_arrow_drop_up_black_18dp_2x.png</file> - <file>images/icons/ic_check_white_18dp_2x.png</file> - <file>images/icons/ic_folder_black_18dp_2x.png</file> - <file>images/icons/ic_arrow_forward_white_48dp_2x.png</file> - <file>images/icons/ic_settings_white_48dp_2x.png</file> - <file>images/icons/ic_voicemail_white_24dp_2x.png</file> - <file>images/background-light.png</file> - <file>images/background-dark.png</file> - <file>images/icons/ic_arrow_drop_down_black_9dp_2x.png</file> - <file>images/icons/ic_arrow_drop_up_black_9dp_2x.png</file> - <file>images/icons/ic_arrow_tab_next_black_9dp_2x.png</file> - <file>images/icons/ic_arrow_tab_previous_black_9dp_2x.png</file> - <file>images/spikeMask.png</file> - <file>images/icons/ic_photo_camera_white_24dp_2x.png</file> - <file>images/qrcode.png</file> - <file>images/icons/ic_share_black_48dp_2x.png</file> - <file>images/loading.gif</file> - <file>images/FontAwesome.otf</file> - <file>images/icons/ic_chat_black_24dp_2x.png</file> - <file>images/icons/ic_person_add_black_24dp_2x.png</file> - <file>images/waiting.gif</file> - <file>images/default_avatar_overlay.svg</file> - <file>images/icons/ic_clear_24px.svg</file> - <file>images/icons/ic_block_24px.svg</file> - <file>images/icons/ic_phone_24px.svg</file> - <file>images/icons/ic_video_call_24px.svg</file> - <file>images/icons/ic_arrow_back_24px.svg</file> - <file>images/icons/ic_send_24px.svg</file> - <file>images/icons/round-settings-24px.svg</file> - <file>web/chatview.css</file> - <file>web/chatview.html</file> - <file>web/chatview.js</file> - <file>web/linkify-html.js</file> - <file>web/linkify-string.js</file> - <file>web/linkify.js</file> - <file>web/qwebchannel.js</file> - </qresource> + <qresource prefix="/"> + <file>stylesheet.css</file> + <file>images/ajax-loader.gif</file> + <file>images/background-dark.png</file> + <file>images/background-light.png</file> + <file>images/default_avatar_overlay.svg</file> + <file>images/FontAwesome.otf</file> + <file>images/loading.gif</file> + <file>images/logo-ring-standard-coul.png</file> + <file>images/qrcode.png</file> + <file>images/ring.ico</file> + <file>images/ring.png</file> + <file>images/spikeMask.png</file> + <file>images/waiting.gif</file> + <file>images/icons/ic_add_black_18dp_2x.png</file> + <file>images/icons/ic_arrow_back_24px.svg</file> + <file>images/icons/ic_arrow_back_white_24dp.png</file> + <file>images/icons/ic_arrow_drop_down_black_9dp_2x.png</file> + <file>images/icons/ic_arrow_drop_down_black_18dp_2x.png</file> + <file>images/icons/ic_arrow_drop_up_black_9dp_2x.png</file> + <file>images/icons/ic_arrow_drop_up_black_18dp_2x.png</file> + <file>images/icons/ic_arrow_forward_white_48dp_2x.png</file> + <file>images/icons/ic_arrow_tab_next_black_9dp_2x.png</file> + <file>images/icons/ic_arrow_tab_previous_black_9dp_2x.png</file> + <file>images/icons/ic_block_24px.svg</file> + <file>images/icons/ic_call_transfer_white_24px.png</file> + <file>images/icons/ic_chat_black_24dp_2x.png</file> + <file>images/icons/ic_chat_white_24dp.png</file> + <file>images/icons/ic_check_white_18dp_2x.png</file> + <file>images/icons/ic_clear_24px.svg</file> + <file>images/icons/ic_close_white_24dp.png</file> + <file>images/icons/ic_content_copy_white_24dp.png</file> + <file>images/icons/ic_delete_black_18dp_2x.png</file> + <file>images/icons/ic_done_white_24dp.png</file> + <file>images/icons/ic_folder_black_18dp_2x.png</file> + <file>images/icons/ic_group_add_white_24dp.png</file> + <file>images/icons/ic_high_quality_white_24dp.png</file> + <file>images/icons/ic_mic_off_white_24dp.png</file> + <file>images/icons/ic_pause_white_24dp.png</file> + <file>images/icons/ic_pause_white_100px.png</file> + <file>images/icons/ic_person_add_black_24dp_2x.png</file> + <file>images/icons/ic_person_add_white_24dp.png</file> + <file>images/icons/ic_phone_24px.svg</file> + <file>images/icons/ic_photo_camera_white_24dp_2x.png</file> + <file>images/icons/ic_search_black_18dp_2x.png</file> + <file>images/icons/ic_send_24px.svg</file> + <file>images/icons/ic_send_white_24dp.png</file> + <file>images/icons/ic_settings_white_48dp_2x.png</file> + <file>images/icons/ic_share_black_48dp_2x.png</file> + <file>images/icons/ic_video_call_24px.svg</file> + <file>images/icons/ic_videocam_off_white_24dp.png</file> + <file>images/icons/ic_videocam_white.png</file> + <file>images/icons/ic_voicemail_white_24dp_2x.png</file> + <file>images/icons/round-add-24px.svg</file> + <file>images/icons/round-arrow_drop_down-24px.svg</file> + <file>images/icons/round-arrow_drop_up-24px.svg</file> + <file>images/icons/round-arrow_right-24px.svg</file> + <file>images/icons/round-close-24px.svg</file> + <file>images/icons/round-edit-24px.svg</file> + <file>images/icons/round-folder-24px.svg</file> + <file>images/icons/round-remove_circle-24px.svg</file> + <file>images/icons/round-settings-24px.svg</file> + <file>images/icons/round-undo-24px.svg</file> + <file>web/chatview.css</file> + <file>web/chatview.html</file> + <file>web/chatview.js</file> + <file>web/linkify.js</file> + <file>web/linkify-html.js</file> + <file>web/linkify-string.js</file> + <file>web/qwebchannel.js</file> + <file>images/icons/round-check_circle-24px.svg</file> + <file>images/icons/round-error-24px.svg</file> + <file>images/icons/round-save_alt-24px.svg</file> + </qresource> </RCC> diff --git a/ring-client-windows.sln b/ring-client-windows.sln index 9106f8c..ca572fd 100644 --- a/ring-client-windows.sln +++ b/ring-client-windows.sln @@ -5,14 +5,14 @@ VisualStudioVersion = 15.0.27703.2026 MinimumVisualStudioVersion = 10.0.40219.1 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ring-client-windows", "ring-client-windows.vcxproj", "{0F6318E4-4C06-384E-BCA8-F344DA187957}" ProjectSection(ProjectDependencies) = postProject - {A604BA33-C1DB-34F6-8584-C429857717A8} = {A604BA33-C1DB-34F6-8584-C429857717A8} + {103832FC-21E8-3D6C-8C85-21D927092562} = {103832FC-21E8-3D6C-8C85-21D927092562} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ring-daemon", "..\daemon\MSVC\ring-daemon.vcxproj", "{79F8DE42-595D-49D9-A66F-55244FD9DCC3}" EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ringclient_static", "..\lrc\msvc\ringclient_static.vcxproj", "{A604BA33-C1DB-34F6-8584-C429857717A8}" +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ringclient_static", "..\lrc\msvc\ringclient_static.vcxproj", "{103832FC-21E8-3D6C-8C85-21D927092562}" EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "qtwrapper", "..\lrc\msvc\src\qtwrapper\qtwrapper.vcxproj", "{8C3AD0D4-A52C-3EFB-A2C6-04EA3AB5F00E}" +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "qtwrapper", "..\lrc\msvc\src\qtwrapper\qtwrapper.vcxproj", "{75CF859A-E546-32BB-8806-448BDB78A8C4}" ProjectSection(ProjectDependencies) = postProject {79F8DE42-595D-49D9-A66F-55244FD9DCC3} = {79F8DE42-595D-49D9-A66F-55244FD9DCC3} EndProjectSection @@ -99,60 +99,62 @@ Global {79F8DE42-595D-49D9-A66F-55244FD9DCC3}.RelWithDebInfo|x64.Build.0 = ReleaseLib|x64 {79F8DE42-595D-49D9-A66F-55244FD9DCC3}.RelWithDebInfo|x86.ActiveCfg = ReleaseLib|Win32 {79F8DE42-595D-49D9-A66F-55244FD9DCC3}.RelWithDebInfo|x86.Build.0 = ReleaseLib|Win32 - {A604BA33-C1DB-34F6-8584-C429857717A8}.Debug|x64.ActiveCfg = Debug|x64 - {A604BA33-C1DB-34F6-8584-C429857717A8}.Debug|x64.Build.0 = Debug|x64 - {A604BA33-C1DB-34F6-8584-C429857717A8}.Debug|x86.ActiveCfg = Debug|x64 - {A604BA33-C1DB-34F6-8584-C429857717A8}.DebugLib_win32|x64.ActiveCfg = Debug|x64 - {A604BA33-C1DB-34F6-8584-C429857717A8}.DebugLib_win32|x64.Build.0 = Debug|x64 - {A604BA33-C1DB-34F6-8584-C429857717A8}.DebugLib_win32|x86.ActiveCfg = MinSizeRel|x64 - {A604BA33-C1DB-34F6-8584-C429857717A8}.DebugLib_win32|x86.Build.0 = MinSizeRel|x64 - {A604BA33-C1DB-34F6-8584-C429857717A8}.DebugLib|x64.ActiveCfg = Debug|x64 - {A604BA33-C1DB-34F6-8584-C429857717A8}.DebugLib|x64.Build.0 = Debug|x64 - {A604BA33-C1DB-34F6-8584-C429857717A8}.DebugLib|x86.ActiveCfg = MinSizeRel|x64 - {A604BA33-C1DB-34F6-8584-C429857717A8}.DebugLib|x86.Build.0 = MinSizeRel|x64 - {A604BA33-C1DB-34F6-8584-C429857717A8}.MinSizeRel|x64.ActiveCfg = MinSizeRel|x64 - {A604BA33-C1DB-34F6-8584-C429857717A8}.MinSizeRel|x64.Build.0 = MinSizeRel|x64 - {A604BA33-C1DB-34F6-8584-C429857717A8}.MinSizeRel|x86.ActiveCfg = MinSizeRel|x64 - {A604BA33-C1DB-34F6-8584-C429857717A8}.Release|x64.ActiveCfg = Release|x64 - {A604BA33-C1DB-34F6-8584-C429857717A8}.Release|x86.ActiveCfg = Release|x64 - {A604BA33-C1DB-34F6-8584-C429857717A8}.ReleaseLib_win32|x64.ActiveCfg = Release|x64 - {A604BA33-C1DB-34F6-8584-C429857717A8}.ReleaseLib_win32|x64.Build.0 = Release|x64 - {A604BA33-C1DB-34F6-8584-C429857717A8}.ReleaseLib_win32|x86.ActiveCfg = MinSizeRel|x64 - {A604BA33-C1DB-34F6-8584-C429857717A8}.ReleaseLib_win32|x86.Build.0 = MinSizeRel|x64 - {A604BA33-C1DB-34F6-8584-C429857717A8}.ReleaseLib|x64.ActiveCfg = Release|x64 - {A604BA33-C1DB-34F6-8584-C429857717A8}.ReleaseLib|x64.Build.0 = Release|x64 - {A604BA33-C1DB-34F6-8584-C429857717A8}.ReleaseLib|x86.ActiveCfg = MinSizeRel|x64 - {A604BA33-C1DB-34F6-8584-C429857717A8}.ReleaseLib|x86.Build.0 = MinSizeRel|x64 - {A604BA33-C1DB-34F6-8584-C429857717A8}.RelWithDebInfo|x64.ActiveCfg = RelWithDebInfo|x64 - {A604BA33-C1DB-34F6-8584-C429857717A8}.RelWithDebInfo|x64.Build.0 = RelWithDebInfo|x64 - {A604BA33-C1DB-34F6-8584-C429857717A8}.RelWithDebInfo|x86.ActiveCfg = RelWithDebInfo|x64 - {8C3AD0D4-A52C-3EFB-A2C6-04EA3AB5F00E}.Debug|x64.ActiveCfg = Debug|x64 - {8C3AD0D4-A52C-3EFB-A2C6-04EA3AB5F00E}.Debug|x64.Build.0 = Debug|x64 - {8C3AD0D4-A52C-3EFB-A2C6-04EA3AB5F00E}.Debug|x86.ActiveCfg = Debug|x64 - {8C3AD0D4-A52C-3EFB-A2C6-04EA3AB5F00E}.DebugLib_win32|x64.ActiveCfg = Debug|x64 - {8C3AD0D4-A52C-3EFB-A2C6-04EA3AB5F00E}.DebugLib_win32|x64.Build.0 = Debug|x64 - {8C3AD0D4-A52C-3EFB-A2C6-04EA3AB5F00E}.DebugLib_win32|x86.ActiveCfg = MinSizeRel|x64 - {8C3AD0D4-A52C-3EFB-A2C6-04EA3AB5F00E}.DebugLib_win32|x86.Build.0 = MinSizeRel|x64 - {8C3AD0D4-A52C-3EFB-A2C6-04EA3AB5F00E}.DebugLib|x64.ActiveCfg = Debug|x64 - {8C3AD0D4-A52C-3EFB-A2C6-04EA3AB5F00E}.DebugLib|x64.Build.0 = Debug|x64 - {8C3AD0D4-A52C-3EFB-A2C6-04EA3AB5F00E}.DebugLib|x86.ActiveCfg = MinSizeRel|x64 - {8C3AD0D4-A52C-3EFB-A2C6-04EA3AB5F00E}.DebugLib|x86.Build.0 = MinSizeRel|x64 - {8C3AD0D4-A52C-3EFB-A2C6-04EA3AB5F00E}.MinSizeRel|x64.ActiveCfg = MinSizeRel|x64 - {8C3AD0D4-A52C-3EFB-A2C6-04EA3AB5F00E}.MinSizeRel|x64.Build.0 = MinSizeRel|x64 - {8C3AD0D4-A52C-3EFB-A2C6-04EA3AB5F00E}.MinSizeRel|x86.ActiveCfg = MinSizeRel|x64 - {8C3AD0D4-A52C-3EFB-A2C6-04EA3AB5F00E}.Release|x64.ActiveCfg = Release|x64 - {8C3AD0D4-A52C-3EFB-A2C6-04EA3AB5F00E}.Release|x86.ActiveCfg = Release|x64 - {8C3AD0D4-A52C-3EFB-A2C6-04EA3AB5F00E}.ReleaseLib_win32|x64.ActiveCfg = Release|x64 - {8C3AD0D4-A52C-3EFB-A2C6-04EA3AB5F00E}.ReleaseLib_win32|x64.Build.0 = Release|x64 - {8C3AD0D4-A52C-3EFB-A2C6-04EA3AB5F00E}.ReleaseLib_win32|x86.ActiveCfg = MinSizeRel|x64 - {8C3AD0D4-A52C-3EFB-A2C6-04EA3AB5F00E}.ReleaseLib_win32|x86.Build.0 = MinSizeRel|x64 - {8C3AD0D4-A52C-3EFB-A2C6-04EA3AB5F00E}.ReleaseLib|x64.ActiveCfg = Release|x64 - {8C3AD0D4-A52C-3EFB-A2C6-04EA3AB5F00E}.ReleaseLib|x64.Build.0 = Release|x64 - {8C3AD0D4-A52C-3EFB-A2C6-04EA3AB5F00E}.ReleaseLib|x86.ActiveCfg = MinSizeRel|x64 - {8C3AD0D4-A52C-3EFB-A2C6-04EA3AB5F00E}.ReleaseLib|x86.Build.0 = MinSizeRel|x64 - {8C3AD0D4-A52C-3EFB-A2C6-04EA3AB5F00E}.RelWithDebInfo|x64.ActiveCfg = RelWithDebInfo|x64 - {8C3AD0D4-A52C-3EFB-A2C6-04EA3AB5F00E}.RelWithDebInfo|x64.Build.0 = RelWithDebInfo|x64 - {8C3AD0D4-A52C-3EFB-A2C6-04EA3AB5F00E}.RelWithDebInfo|x86.ActiveCfg = RelWithDebInfo|x64 + {103832FC-21E8-3D6C-8C85-21D927092562}.Debug|x64.ActiveCfg = Debug|x64 + {103832FC-21E8-3D6C-8C85-21D927092562}.Debug|x64.Build.0 = Debug|x64 + {103832FC-21E8-3D6C-8C85-21D927092562}.Debug|x86.ActiveCfg = Debug|x64 + {103832FC-21E8-3D6C-8C85-21D927092562}.DebugLib_win32|x64.ActiveCfg = Debug|x64 + {103832FC-21E8-3D6C-8C85-21D927092562}.DebugLib_win32|x64.Build.0 = Debug|x64 + {103832FC-21E8-3D6C-8C85-21D927092562}.DebugLib_win32|x86.ActiveCfg = MinSizeRel|x64 + {103832FC-21E8-3D6C-8C85-21D927092562}.DebugLib_win32|x86.Build.0 = MinSizeRel|x64 + {103832FC-21E8-3D6C-8C85-21D927092562}.DebugLib|x64.ActiveCfg = Debug|x64 + {103832FC-21E8-3D6C-8C85-21D927092562}.DebugLib|x64.Build.0 = Debug|x64 + {103832FC-21E8-3D6C-8C85-21D927092562}.DebugLib|x86.ActiveCfg = MinSizeRel|x64 + {103832FC-21E8-3D6C-8C85-21D927092562}.DebugLib|x86.Build.0 = MinSizeRel|x64 + {103832FC-21E8-3D6C-8C85-21D927092562}.MinSizeRel|x64.ActiveCfg = MinSizeRel|x64 + {103832FC-21E8-3D6C-8C85-21D927092562}.MinSizeRel|x64.Build.0 = MinSizeRel|x64 + {103832FC-21E8-3D6C-8C85-21D927092562}.MinSizeRel|x86.ActiveCfg = MinSizeRel|x64 + {103832FC-21E8-3D6C-8C85-21D927092562}.Release|x64.ActiveCfg = Release|x64 + {103832FC-21E8-3D6C-8C85-21D927092562}.Release|x64.Build.0 = Release|x64 + {103832FC-21E8-3D6C-8C85-21D927092562}.Release|x86.ActiveCfg = Release|x64 + {103832FC-21E8-3D6C-8C85-21D927092562}.ReleaseLib_win32|x64.ActiveCfg = Release|x64 + {103832FC-21E8-3D6C-8C85-21D927092562}.ReleaseLib_win32|x64.Build.0 = Release|x64 + {103832FC-21E8-3D6C-8C85-21D927092562}.ReleaseLib_win32|x86.ActiveCfg = MinSizeRel|x64 + {103832FC-21E8-3D6C-8C85-21D927092562}.ReleaseLib_win32|x86.Build.0 = MinSizeRel|x64 + {103832FC-21E8-3D6C-8C85-21D927092562}.ReleaseLib|x64.ActiveCfg = Release|x64 + {103832FC-21E8-3D6C-8C85-21D927092562}.ReleaseLib|x64.Build.0 = Release|x64 + {103832FC-21E8-3D6C-8C85-21D927092562}.ReleaseLib|x86.ActiveCfg = MinSizeRel|x64 + {103832FC-21E8-3D6C-8C85-21D927092562}.ReleaseLib|x86.Build.0 = MinSizeRel|x64 + {103832FC-21E8-3D6C-8C85-21D927092562}.RelWithDebInfo|x64.ActiveCfg = RelWithDebInfo|x64 + {103832FC-21E8-3D6C-8C85-21D927092562}.RelWithDebInfo|x64.Build.0 = RelWithDebInfo|x64 + {103832FC-21E8-3D6C-8C85-21D927092562}.RelWithDebInfo|x86.ActiveCfg = RelWithDebInfo|x64 + {75CF859A-E546-32BB-8806-448BDB78A8C4}.Debug|x64.ActiveCfg = Debug|x64 + {75CF859A-E546-32BB-8806-448BDB78A8C4}.Debug|x64.Build.0 = Debug|x64 + {75CF859A-E546-32BB-8806-448BDB78A8C4}.Debug|x86.ActiveCfg = Debug|x64 + {75CF859A-E546-32BB-8806-448BDB78A8C4}.DebugLib_win32|x64.ActiveCfg = Debug|x64 + {75CF859A-E546-32BB-8806-448BDB78A8C4}.DebugLib_win32|x64.Build.0 = Debug|x64 + {75CF859A-E546-32BB-8806-448BDB78A8C4}.DebugLib_win32|x86.ActiveCfg = MinSizeRel|x64 + {75CF859A-E546-32BB-8806-448BDB78A8C4}.DebugLib_win32|x86.Build.0 = MinSizeRel|x64 + {75CF859A-E546-32BB-8806-448BDB78A8C4}.DebugLib|x64.ActiveCfg = Debug|x64 + {75CF859A-E546-32BB-8806-448BDB78A8C4}.DebugLib|x64.Build.0 = Debug|x64 + {75CF859A-E546-32BB-8806-448BDB78A8C4}.DebugLib|x86.ActiveCfg = MinSizeRel|x64 + {75CF859A-E546-32BB-8806-448BDB78A8C4}.DebugLib|x86.Build.0 = MinSizeRel|x64 + {75CF859A-E546-32BB-8806-448BDB78A8C4}.MinSizeRel|x64.ActiveCfg = MinSizeRel|x64 + {75CF859A-E546-32BB-8806-448BDB78A8C4}.MinSizeRel|x64.Build.0 = MinSizeRel|x64 + {75CF859A-E546-32BB-8806-448BDB78A8C4}.MinSizeRel|x86.ActiveCfg = MinSizeRel|x64 + {75CF859A-E546-32BB-8806-448BDB78A8C4}.Release|x64.ActiveCfg = Release|x64 + {75CF859A-E546-32BB-8806-448BDB78A8C4}.Release|x64.Build.0 = Release|x64 + {75CF859A-E546-32BB-8806-448BDB78A8C4}.Release|x86.ActiveCfg = Release|x64 + {75CF859A-E546-32BB-8806-448BDB78A8C4}.ReleaseLib_win32|x64.ActiveCfg = Release|x64 + {75CF859A-E546-32BB-8806-448BDB78A8C4}.ReleaseLib_win32|x64.Build.0 = Release|x64 + {75CF859A-E546-32BB-8806-448BDB78A8C4}.ReleaseLib_win32|x86.ActiveCfg = MinSizeRel|x64 + {75CF859A-E546-32BB-8806-448BDB78A8C4}.ReleaseLib_win32|x86.Build.0 = MinSizeRel|x64 + {75CF859A-E546-32BB-8806-448BDB78A8C4}.ReleaseLib|x64.ActiveCfg = Release|x64 + {75CF859A-E546-32BB-8806-448BDB78A8C4}.ReleaseLib|x64.Build.0 = Release|x64 + {75CF859A-E546-32BB-8806-448BDB78A8C4}.ReleaseLib|x86.ActiveCfg = MinSizeRel|x64 + {75CF859A-E546-32BB-8806-448BDB78A8C4}.ReleaseLib|x86.Build.0 = MinSizeRel|x64 + {75CF859A-E546-32BB-8806-448BDB78A8C4}.RelWithDebInfo|x64.ActiveCfg = RelWithDebInfo|x64 + {75CF859A-E546-32BB-8806-448BDB78A8C4}.RelWithDebInfo|x64.Build.0 = RelWithDebInfo|x64 + {75CF859A-E546-32BB-8806-448BDB78A8C4}.RelWithDebInfo|x86.ActiveCfg = RelWithDebInfo|x64 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/ring-client-windows.vcxproj b/ring-client-windows.vcxproj index 8d2867b..0d357db 100644 --- a/ring-client-windows.vcxproj +++ b/ring-client-windows.vcxproj @@ -14,7 +14,7 @@ <ProjectGuid>{0F6318E4-4C06-384E-BCA8-F344DA187957}</ProjectGuid> <RootNamespace>Ring</RootNamespace> <Keyword>Qt4VSv1.0</Keyword> - <WindowsTargetPlatformVersion>10.0.16299.0</WindowsTargetPlatformVersion> + <WindowsTargetPlatformVersion>10.0.17134.0</WindowsTargetPlatformVersion> </PropertyGroup> <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" /> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration"> @@ -92,7 +92,7 @@ <FunctionLevelLinking>true</FunctionLevelLinking> </ClCompile> <Link> - <AdditionalDependencies>dring.lib;qtwrapper.lib;ringclient_static.lib;WinSparkle.lib;qrcodelib.lib;shell32.lib;Ole32.lib;Advapi32.lib;Shlwapi.lib;User32.lib;Gdi32.lib;Crypt32.lib;Strmiids.lib;qtmain.lib;Qt5Svg.lib;Qt5Widgets.lib;Qt5WinExtras.lib;Qt5Gui.lib;Qt5Xml.lib;Qt5Network.lib;Qt5Core.lib;Qt5Sql.lib;Qt5WebEngineWidgets.lib;Qt5WebChannel.lib;%(AdditionalDependencies)</AdditionalDependencies> + <AdditionalDependencies>dring.lib;qtwrapper.lib;ringclient_static.lib;WinSparkle.lib;qrcodelib.lib;shell32.lib;Ole32.lib;Advapi32.lib;Shlwapi.lib;User32.lib;Gdi32.lib;Crypt32.lib;Strmiids.lib;qtmain.lib;Qt5Svg.lib;Qt5Widgets.lib;Qt5WinExtras.lib;Qt5Gui.lib;Qt5Xml.lib;Qt5Network.lib;Qt5Core.lib;Qt5Sql.lib;Qt5WebEngineWidgets.lib;Qt5WebChannel.lib;Qt5Multimedia.lib;Qt5MultimediaWidgets.lib;%(AdditionalDependencies)</AdditionalDependencies> <AdditionalLibraryDirectories>$(QTDIR)\lib;..\ring-daemon\contrib\msvc\lib\x64;..\daemon\contrib\msvc\lib\x64;..\ring-daemon\MSVC\x64\ReleaseLib_win32\bin;..\daemon\MSVC\x64\ReleaseLib_win32\bin;..\ring-lrc\msvc\release;..\lrc\msvc\release;..\ring-lrc\msvc\src\qtwrapper\Release;..\lrc\msvc\src\qtwrapper\Release;.\winsparkle\x64\release;.\qrencode-win32\qrencode-win32\vc8\qrcodelib\x64\Release-Lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories> <AdditionalOptions>"/MANIFESTDEPENDENCY:type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' publicKeyToken='6595b64144ccf1df' language='*' processorArchitecture='*'" /ignore:4006,4049,4078,4098 /LTCG /NODEFAULTLIB:LIBCMT %(AdditionalOptions)</AdditionalOptions> <DataExecutionPrevention>true</DataExecutionPrevention> @@ -219,6 +219,9 @@ </PreBuildEvent> </ItemDefinitionGroup> <ItemGroup> + <ClCompile Include="advancedsettingswidget.cpp" /> + <ClCompile Include="avatargraphicsview.cpp" /> + <ClCompile Include="bannedlistmodel.cpp" /> <ClCompile Include="animationhelpers.cpp" /> <ClCompile Include="currentaccountcombobox.cpp" /> <ClCompile Include="aboutdialog.cpp" /> @@ -246,15 +249,18 @@ <ClCompile Include="globalsystemtray.cpp" /> <ClCompile Include="idlabel.cpp" /> <ClCompile Include="invitebuttonswidget.cpp" /> + <ClCompile Include="linkdevwidget.cpp" /> <ClCompile Include="main.cpp" /> <ClCompile Include="mainwindow.cpp" /> <ClCompile Include="messagewebpage.cpp" /> <ClCompile Include="messagewebview.cpp" /> <ClCompile Include="navwidget.cpp" /> + <ClCompile Include="passworddialog.cpp" /> <ClCompile Include="photoboothdialog.cpp" /> <ClCompile Include="photoboothwidget.cpp" /> <ClCompile Include="pixbufmanipulator.cpp" /> <ClCompile Include="qualitydialog.cpp" /> + <ClCompile Include="regnamedialog.cpp" /> <ClCompile Include="ringbutton.cpp" /> <ClCompile Include="ringcontactlineedit.cpp" /> <ClCompile Include="selectareadialog.cpp" /> @@ -269,6 +275,9 @@ <Define Condition="'$(Configuration)|$(Platform)'=='Release|x64'">_WINDOWS;UNICODE;_UNICODE;WIN32;WIN64;NIGHTLY_VERSION=20180706;ENABLE_AUTOUPDATE;QT_NO_DEBUG;NDEBUG</Define> <Define Condition="'$(Configuration)|$(Platform)'=='ReleaseCompile|x64'">_WINDOWS;UNICODE;_UNICODE;WIN32;WIN64;NIGHTLY_VERSION=20180706;ENABLE_AUTOUPDATE;QT_NO_DEBUG;NDEBUG</Define> </ClCompile> + <ClCompile Include="setavatardialog.cpp" /> + <ClCompile Include="settingsitemwidget.cpp" /> + <ClCompile Include="settingswidget.cpp" /> <ClCompile Include="smartlistselectorbuttonnotifier.cpp" /> <ClCompile Include="smartlistview.cpp" /> <ClCompile Include="conversationitemdelegate.cpp" /> @@ -354,6 +363,22 @@ <Define Condition="'$(Configuration)|$(Platform)'=='Release|x64'">_WINDOWS;UNICODE;_UNICODE;WIN32;WIN64;NIGHTLY_VERSION=20180706;ENABLE_AUTOUPDATE;QT_NO_DEBUG;NDEBUG</Define> <Define Condition="'$(Configuration)|$(Platform)'=='ReleaseCompile|x64'">_WINDOWS;UNICODE;_UNICODE;WIN32;WIN64;NIGHTLY_VERSION=20180706;ENABLE_AUTOUPDATE;QT_NO_DEBUG;NDEBUG</Define> </QtMoc> + <QtMoc Include="advancedsettingswidget.h"> + <IncludePath Condition="'$(Configuration)|$(Platform)'=='Release|x64'">.\GeneratedFiles\$(ConfigurationName)\.;.\GeneratedFiles;.;$(ProjectDir)..\daemon\contrib\msvc\include;$(ProjectDir)..\lrc\src;$(ProjectDir)..\client-windows\winsparkle\include;$(ProjectDir)..\client-windows\qrencode-win32\qrencode-win32;$(QTDIR)\include;$(QTDIR)\include\QtSvg;$(QTDIR)\include\QtWidgets;$(QTDIR)\include\QtWinExtras;$(QTDIR)\include\QtGui;$(QTDIR)\include\QtANGLE;$(QTDIR)\include\QtXml;$(QTDIR)\include\QtNetwork;$(QTDIR)\include\QtCore;$(QTDIR)\mkspecs\win32-msvc;.\release</IncludePath> + <Define Condition="'$(Configuration)|$(Platform)'=='Release|x64'">_WINDOWS;UNICODE;_UNICODE;WIN32;WIN64;NIGHTLY_VERSION=20180706;ENABLE_AUTOUPDATE;QT_NO_DEBUG;NDEBUG</Define> + </QtMoc> + <QtMoc Include="avatargraphicsview.h"> + <IncludePath Condition="'$(Configuration)|$(Platform)'=='Release|x64'">.\GeneratedFiles\$(ConfigurationName)\.;.\GeneratedFiles;.;$(ProjectDir)..\daemon\contrib\msvc\include;$(ProjectDir)..\lrc\src;$(ProjectDir)..\client-windows\winsparkle\include;$(ProjectDir)..\client-windows\qrencode-win32\qrencode-win32;$(QTDIR)\include;$(QTDIR)\include\QtSvg;$(QTDIR)\include\QtWidgets;$(QTDIR)\include\QtWinExtras;$(QTDIR)\include\QtGui;$(QTDIR)\include\QtANGLE;$(QTDIR)\include\QtXml;$(QTDIR)\include\QtNetwork;$(QTDIR)\include\QtCore;$(QTDIR)\mkspecs\win32-msvc;.\release;$(QTDIR)\include\QtMultimedia;$(QTDIR)\include\QtMultimediaWidgets</IncludePath> + <Define Condition="'$(Configuration)|$(Platform)'=='Release|x64'">_WINDOWS;UNICODE;_UNICODE;WIN32;WIN64;NIGHTLY_VERSION=20180706;ENABLE_AUTOUPDATE;QT_NO_DEBUG;NDEBUG;QT_MULTIMEDIA_LIB;QT_MULTIMEDIAWIDGETS_LIB</Define> + </QtMoc> + <QtMoc Include="bannedlistmodel.h"> + <IncludePath Condition="'$(Configuration)|$(Platform)'=='Release|x64'">.\GeneratedFiles\$(ConfigurationName)\.;.\GeneratedFiles;.;$(ProjectDir)..\daemon\contrib\msvc\include;$(ProjectDir)..\lrc\src;$(ProjectDir)..\client-windows\winsparkle\include;$(ProjectDir)..\client-windows\qrencode-win32\qrencode-win32;$(QTDIR)\include;$(QTDIR)\include\QtSvg;$(QTDIR)\include\QtWidgets;$(QTDIR)\include\QtWinExtras;$(QTDIR)\include\QtGui;$(QTDIR)\include\QtANGLE;$(QTDIR)\include\QtXml;$(QTDIR)\include\QtNetwork;$(QTDIR)\include\QtCore;$(QTDIR)\mkspecs\win32-msvc;.\release;$(QTDIR)\include\QtMultimedia;$(QTDIR)\include\QtMultimediaWidgets</IncludePath> + <Define Condition="'$(Configuration)|$(Platform)'=='Release|x64'">_WINDOWS;UNICODE;_UNICODE;WIN32;WIN64;NIGHTLY_VERSION=20180706;ENABLE_AUTOUPDATE;QT_NO_DEBUG;NDEBUG;QT_MULTIMEDIA_LIB;QT_MULTIMEDIAWIDGETS_LIB</Define> + </QtMoc> + <QtMoc Include="linkdevwidget.h"> + <IncludePath Condition="'$(Configuration)|$(Platform)'=='Release|x64'">.\GeneratedFiles\$(ConfigurationName)\.;.\GeneratedFiles;.;$(ProjectDir)..\daemon\contrib\msvc\include;$(ProjectDir)..\lrc\src;$(ProjectDir)..\client-windows\winsparkle\include;$(ProjectDir)..\client-windows\qrencode-win32\qrencode-win32;$(QTDIR)\include;$(QTDIR)\include\QtSvg;$(QTDIR)\include\QtWidgets;$(QTDIR)\include\QtWinExtras;$(QTDIR)\include\QtGui;$(QTDIR)\include\QtANGLE;$(QTDIR)\include\QtXml;$(QTDIR)\include\QtNetwork;$(QTDIR)\include\QtCore;$(QTDIR)\mkspecs\win32-msvc;.\release;$(QTDIR)\include\QtMultimedia;$(QTDIR)\include\QtMultimediaWidgets</IncludePath> + <Define Condition="'$(Configuration)|$(Platform)'=='Release|x64'">_WINDOWS;UNICODE;_UNICODE;WIN32;WIN64;NIGHTLY_VERSION=20180706;ENABLE_AUTOUPDATE;QT_NO_DEBUG;NDEBUG;QT_MULTIMEDIA_LIB;QT_MULTIMEDIAWIDGETS_LIB</Define> + </QtMoc> <ClInclude Include="lrcinstance.h" /> <QtMoc Include="messagewebview.h"> <IncludePath Condition="'$(Configuration)|$(Platform)'=='Release|x64'">.\GeneratedFiles\$(ConfigurationName)\.;.\GeneratedFiles;.;$(ProjectDir)..\daemon\contrib\msvc\include;$(ProjectDir)..\lrc\src;$(ProjectDir)..\client-windows\winsparkle\include;$(ProjectDir)..\client-windows\qrencode-win32\qrencode-win32;$(QTDIR)\include;$(QTDIR)\include\QtSvg;$(QTDIR)\include\QtWidgets;$(QTDIR)\include\QtWinExtras;$(QTDIR)\include\QtGui;$(QTDIR)\include\QtANGLE;$(QTDIR)\include\QtXml;$(QTDIR)\include\QtNetwork;$(QTDIR)\include\QtWebEngineWidgets;$(QTDIR)\include\QtCore;$(QTDIR)\mkspecs\win32-msvc;.\release</IncludePath> @@ -367,6 +392,10 @@ <Define Condition="'$(Configuration)|$(Platform)'=='Release|x64'">_WINDOWS;UNICODE;_UNICODE;WIN32;WIN64;NIGHTLY_VERSION=20180706;ENABLE_AUTOUPDATE;QT_NO_DEBUG;NDEBUG</Define> <Define Condition="'$(Configuration)|$(Platform)'=='ReleaseCompile|x64'">_WINDOWS;UNICODE;_UNICODE;WIN32;WIN64;NIGHTLY_VERSION=20180706;ENABLE_AUTOUPDATE;QT_NO_DEBUG;NDEBUG</Define> </QtMoc> + <QtMoc Include="passworddialog.h"> + <IncludePath Condition="'$(Configuration)|$(Platform)'=='Release|x64'">.\GeneratedFiles\$(ConfigurationName)\.;.\GeneratedFiles;.;$(ProjectDir)..\daemon\contrib\msvc\include;$(ProjectDir)..\lrc\src;$(ProjectDir)..\client-windows\winsparkle\include;$(ProjectDir)..\client-windows\qrencode-win32\qrencode-win32;$(QTDIR)\include;$(QTDIR)\include\QtSvg;$(QTDIR)\include\QtWidgets;$(QTDIR)\include\QtWinExtras;$(QTDIR)\include\QtGui;$(QTDIR)\include\QtANGLE;$(QTDIR)\include\QtXml;$(QTDIR)\include\QtNetwork;$(QTDIR)\include\QtCore;$(QTDIR)\mkspecs\win32-msvc;.\release;$(QTDIR)\include\QtMultimedia;$(QTDIR)\include\QtMultimediaWidgets</IncludePath> + <Define Condition="'$(Configuration)|$(Platform)'=='Release|x64'">_WINDOWS;UNICODE;_UNICODE;WIN32;WIN64;NIGHTLY_VERSION=20180706;ENABLE_AUTOUPDATE;QT_NO_DEBUG;NDEBUG;QT_MULTIMEDIA_LIB;QT_MULTIMEDIAWIDGETS_LIB</Define> + </QtMoc> <ClInclude Include="pixbufmanipulator.h" /> <QtMoc Include="qualitydialog.h"> </QtMoc> @@ -374,11 +403,23 @@ </QtMoc> <QtMoc Include="ringcontactlineedit.h"> </QtMoc> + <QtMoc Include="regnamedialog.h"> + <IncludePath Condition="'$(Configuration)|$(Platform)'=='Release|x64'">.\GeneratedFiles\$(ConfigurationName)\.;.\GeneratedFiles;.;$(ProjectDir)..\daemon\contrib\msvc\include;$(ProjectDir)..\lrc\src;$(ProjectDir)..\client-windows\winsparkle\include;$(ProjectDir)..\client-windows\qrencode-win32\qrencode-win32;$(QTDIR)\include;$(QTDIR)\include\QtSvg;$(QTDIR)\include\QtWidgets;$(QTDIR)\include\QtWinExtras;$(QTDIR)\include\QtGui;$(QTDIR)\include\QtANGLE;$(QTDIR)\include\QtXml;$(QTDIR)\include\QtNetwork;$(QTDIR)\include\QtCore;$(QTDIR)\mkspecs\win32-msvc;.\release;$(QTDIR)\include\QtMultimedia;$(QTDIR)\include\QtMultimediaWidgets</IncludePath> + <Define Condition="'$(Configuration)|$(Platform)'=='Release|x64'">_WINDOWS;UNICODE;_UNICODE;WIN32;WIN64;NIGHTLY_VERSION=20180706;ENABLE_AUTOUPDATE;QT_NO_DEBUG;NDEBUG;QT_MULTIMEDIA_LIB;QT_MULTIMEDIAWIDGETS_LIB</Define> + </QtMoc> <ClInclude Include="ringthemeutils.h" /> <QtMoc Include="selectareadialog.h"> </QtMoc> <QtMoc Include="sendcontactrequestwidget.h"> </QtMoc> + <QtMoc Include="setavatardialog.h"> + <IncludePath Condition="'$(Configuration)|$(Platform)'=='Release|x64'">.\GeneratedFiles\$(ConfigurationName)\.;.\GeneratedFiles;.;$(ProjectDir)..\daemon\contrib\msvc\include;$(ProjectDir)..\lrc\src;$(ProjectDir)..\client-windows\winsparkle\include;$(ProjectDir)..\client-windows\qrencode-win32\qrencode-win32;$(QTDIR)\include;$(QTDIR)\include\QtSvg;$(QTDIR)\include\QtWidgets;$(QTDIR)\include\QtWinExtras;$(QTDIR)\include\QtGui;$(QTDIR)\include\QtANGLE;$(QTDIR)\include\QtXml;$(QTDIR)\include\QtNetwork;$(QTDIR)\include\QtCore;$(QTDIR)\mkspecs\win32-msvc;.\release</IncludePath> + <Define Condition="'$(Configuration)|$(Platform)'=='Release|x64'">_WINDOWS;UNICODE;_UNICODE;WIN32;WIN64;NIGHTLY_VERSION=20180706;ENABLE_AUTOUPDATE;QT_NO_DEBUG;NDEBUG</Define> + </QtMoc> + <ClInclude Include="settingsitemwidget.h"> + <IncludePath Condition="'$(Configuration)|$(Platform)'=='Release|x64'">.\GeneratedFiles\$(ConfigurationName)\.;.\GeneratedFiles;.;$(ProjectDir)..\daemon\contrib\msvc\include;$(ProjectDir)..\lrc\src;$(ProjectDir)..\client-windows\winsparkle\include;$(ProjectDir)..\client-windows\qrencode-win32\qrencode-win32;$(QTDIR)\include;$(QTDIR)\include\QtSvg;$(QTDIR)\include\QtWidgets;$(QTDIR)\include\QtWinExtras;$(QTDIR)\include\QtGui;$(QTDIR)\include\QtANGLE;$(QTDIR)\include\QtXml;$(QTDIR)\include\QtNetwork;$(QTDIR)\include\QtCore;$(QTDIR)\mkspecs\win32-msvc;.\release;$(QTDIR)\include\QtMultimedia;$(QTDIR)\include\QtMultimediaWidgets</IncludePath> + <Define Condition="'$(Configuration)|$(Platform)'=='Release|x64'">_WINDOWS;UNICODE;_UNICODE;WIN32;WIN64;NIGHTLY_VERSION=20180706;ENABLE_AUTOUPDATE;QT_NO_DEBUG;NDEBUG;QT_MULTIMEDIA_LIB;QT_MULTIMEDIAWIDGETS_LIB</Define> + </ClInclude> <ClInclude Include="settingskey.h" /> <QtMoc Include="smartlistview.h"> <IncludePath Condition="'$(Configuration)|$(Platform)'=='Release|x64'">.\GeneratedFiles\$(ConfigurationName)\.;.\GeneratedFiles;.;$(ProjectDir)..\daemon\contrib\msvc\include;$(ProjectDir)..\lrc\src;$(ProjectDir)..\client-windows\winsparkle\include;$(ProjectDir)..\client-windows\qrencode-win32\qrencode-win32;$(QTDIR)\include;$(QTDIR)\include\QtSvg;$(QTDIR)\include\QtWidgets;$(QTDIR)\include\QtWinExtras;$(QTDIR)\include\QtGui;$(QTDIR)\include\QtANGLE;$(QTDIR)\include\QtXml;$(QTDIR)\include\QtNetwork;$(QTDIR)\include\QtCore;$(QTDIR)\mkspecs\win32-msvc;.\release</IncludePath> @@ -410,6 +451,11 @@ <Define Condition="'$(Configuration)|$(Platform)'=='Release|x64'">_WINDOWS;UNICODE;_UNICODE;WIN32;WIN64;NIGHTLY_VERSION=20180706;ENABLE_AUTOUPDATE;QT_NO_DEBUG;NDEBUG</Define> <Define Condition="'$(Configuration)|$(Platform)'=='ReleaseCompile|x64'">_WINDOWS;UNICODE;_UNICODE;WIN32;WIN64;NIGHTLY_VERSION=20180706;ENABLE_AUTOUPDATE;QT_NO_DEBUG;NDEBUG</Define> </QtMoc> + <QtMoc Include="settingswidget.h"> + <IncludePath Condition="'$(Configuration)|$(Platform)'=='Release|x64'">.\GeneratedFiles\$(ConfigurationName)\.;.\GeneratedFiles;.;$(ProjectDir)..\daemon\contrib\msvc\include;$(ProjectDir)..\lrc\src;$(ProjectDir)..\client-windows\winsparkle\include;$(ProjectDir)..\client-windows\qrencode-win32\qrencode-win32;$(QTDIR)\include;$(QTDIR)\include\QtSvg;$(QTDIR)\include\QtWidgets;$(QTDIR)\include\QtWinExtras;$(QTDIR)\include\QtGui;$(QTDIR)\include\QtANGLE;$(QTDIR)\include\QtXml;$(QTDIR)\include\QtNetwork;$(QTDIR)\include\QtCore;$(QTDIR)\mkspecs\win32-msvc;.\release</IncludePath> + <Define Condition="'$(Configuration)|$(Platform)'=='Release|x64'">_WINDOWS;UNICODE;_UNICODE;WIN32;WIN64;NIGHTLY_VERSION=20180706;ENABLE_AUTOUPDATE;QT_NO_DEBUG;NDEBUG</Define> + <SubType>Designer</SubType> + </QtMoc> <ClInclude Include="utils.h" /> <QtMoc Include="videooverlay.h"> </QtMoc> @@ -526,6 +572,9 @@ </QtUic> <QtUic Include="accountdetails.ui"> </QtUic> + <QtUic Include="advancedsettingswidget.ui"> + <SubType>Designer</SubType> + </QtUic> <QtUic Include="animatedoverlay.ui"> <SubType>Designer</SubType> </QtUic> @@ -543,11 +592,17 @@ <QtUic Include="contactrequestwidget.ui"> </QtUic> <QtUic Include="deleteaccountdialog.ui"> + <SubType>Designer</SubType> </QtUic> + <QtUic Include="deviceeditwidget.ui" /> <QtUic Include="invitebuttonswidget.ui" /> + <QtUic Include="linkdevwidget.ui" /> <QtUic Include="mainwindow.ui"> <SubType>Designer</SubType> </QtUic> + <QtUic Include="passworddialog.ui"> + <SubType>Designer</SubType> + </QtUic> <QtUic Include="photoboothdialog.ui"> </QtUic> <QtUic Include="photoboothwidget.ui"> @@ -556,10 +611,17 @@ </QtUic> <QtUic Include="quickactcontactrequestwidget.ui"> </QtUic> + <QtUic Include="regnamedialog.ui" /> <QtUic Include="ringbutton.ui"> </QtUic> <QtUic Include="sendcontactrequestwidget.ui"> </QtUic> + <QtUic Include="setavatardialog.ui"> + <SubType>Designer</SubType> + </QtUic> + <QtUic Include="settingswidget.ui"> + <SubType>Designer</SubType> + </QtUic> <QtUic Include="videooverlay.ui"> </QtUic> <QtUic Include="videoview.ui"> diff --git a/ring-client-windows.vcxproj.filters b/ring-client-windows.vcxproj.filters index d2e77d3..32b83a6 100644 --- a/ring-client-windows.vcxproj.filters +++ b/ring-client-windows.vcxproj.filters @@ -192,6 +192,36 @@ <ClCompile Include="animationhelpers.cpp"> <Filter>Source Files</Filter> </ClCompile> + <ClCompile Include="settingswidget.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="passworddialog.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="advancedsettingswidget.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="setavatardialog.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="avatargraphicsview.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="regnamedialog.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="accountlistmodel.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="bannedlistmodel.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="settingsitemwidget.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="linkdevwidget.cpp"> + <Filter>Source Files</Filter> + </ClCompile> </ItemGroup> <ItemGroup> <QtMoc Include="aboutdialog.h"> @@ -326,6 +356,30 @@ <QtMoc Include="animationhelpers.h"> <Filter>Header Files</Filter> </QtMoc> + <QtMoc Include="settingswidget.h"> + <Filter>Header Files</Filter> + </QtMoc> + <QtMoc Include="passworddialog.h"> + <Filter>Header Files</Filter> + </QtMoc> + <QtMoc Include="advancedsettingswidget.h"> + <Filter>Header Files</Filter> + </QtMoc> + <QtMoc Include="setavatardialog.h"> + <Filter>Header Files</Filter> + </QtMoc> + <QtMoc Include="avatargraphicsview.h"> + <Filter>Header Files</Filter> + </QtMoc> + <QtMoc Include="regnamedialog.h"> + <Filter>Header Files</Filter> + </QtMoc> + <QtMoc Include="bannedlistmodel.h"> + <Filter>Header Files</Filter> + </QtMoc> + <QtMoc Include="linkdevwidget.h"> + <Filter>Header Files</Filter> + </QtMoc> </ItemGroup> <ItemGroup> <CustomBuild Include="debug\moc_predefs.h.cbt"> @@ -635,9 +689,30 @@ <QtUic Include="wizardwidget.ui"> <Filter>Form Files</Filter> </QtUic> + <QtUic Include="settingswidget.ui"> + <Filter>Form Files</Filter> + </QtUic> + <QtUic Include="passworddialog.ui"> + <Filter>Form Files</Filter> + </QtUic> + <QtUic Include="advancedsettingswidget.ui"> + <Filter>Form Files</Filter> + </QtUic> + <QtUic Include="setavatardialog.ui"> + <Filter>Form Files</Filter> + </QtUic> <QtUic Include="animatedoverlay.ui"> <Filter>Form Files</Filter> </QtUic> + <QtUic Include="regnamedialog.ui"> + <Filter>Form Files</Filter> + </QtUic> + <QtUic Include="deviceeditwidget.ui"> + <Filter>Form Files</Filter> + </QtUic> + <QtUic Include="linkdevwidget.ui"> + <Filter>Form Files</Filter> + </QtUic> </ItemGroup> <ItemGroup> <None Include="images\FontAwesome.otf"> @@ -783,6 +858,9 @@ <ClInclude Include="lrcinstance.h"> <Filter>Header Files</Filter> </ClInclude> + <ClInclude Include="settingsitemwidget.h"> + <Filter>Header Files</Filter> + </ClInclude> <ClInclude Include="webchathelpers.h"> <Filter>Header Files</Filter> </ClInclude> diff --git a/ringthemeutils.h b/ringthemeutils.h index 4536685..5434aca 100644 --- a/ringthemeutils.h +++ b/ringthemeutils.h @@ -16,6 +16,8 @@ * along with this program. If not, see <http://www.gnu.org/licenses/>. * **************************************************************************/ +#include <QColor> + #pragma once namespace RingTheme { diff --git a/ringtones/Makefile.am b/ringtones/Makefile.am new file mode 100644 index 0000000..64fab83 --- /dev/null +++ b/ringtones/Makefile.am @@ -0,0 +1,5 @@ +ringringtonesdir = $(datadir)/ring/ringtones +dist_ringringtones_DATA = \ + konga.ul\ + default.wav \ + default.opus diff --git a/ringtones/default.opus b/ringtones/default.opus new file mode 100644 index 0000000000000000000000000000000000000000..c3c0a8076c1bdb474d95514005a0865063373b88 GIT binary patch literal 22089 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 Wkl<Iz+UD9;$LCIQ&E592<01g0_2-TN literal 0 HcmV?d00001 diff --git a/ringtones/default.opus.LICENSE b/ringtones/default.opus.LICENSE new file mode 100644 index 0000000..98b99bf --- /dev/null +++ b/ringtones/default.opus.LICENSE @@ -0,0 +1,4 @@ +Original file name: 171324__swidmark__ringtone.wav +Download location: https://freesound.org/people/swidmark/sounds/171324 +Uploader: https://freesound.org/people/swidmark +License: CC0 1.0 Universal (CC0 1.0) (https://creativecommons.org/publicdomain/zero/1.0/) diff --git a/ringtones/default.wav b/ringtones/default.wav new file mode 100644 index 0000000000000000000000000000000000000000..f68346e5a2df863e1e6741532042db4c173014e0 GIT binary patch literal 56472 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	Z7wQov)ZSGI`BXGyy2j`1* zygHxWaXsXC$hJgOo|9E}^UqBxi~hbB2>K=QpZA^Urz5}mZW{c!eY5{p`>WIZIX{wk zRk&_)Z<4g;N>%gtyG*|M?@XQzpQHcByw-bm<LioRcR%;tKl9i8RfkaDe=EVOLUuwY zB&B%x)O`PO%BlT5&NlJgm7hmm@;=`2+3D*0ck3S9`G4l!F5x9i?EGJZRYY#fKjgir z?#Li6IrG0XhvJ7F-`~Iberx3i->Z#puRpM3sC)a4UyF^8&rkH3kcP4o&k=2Z*3aV4 z7y>w?Kel~&@czoRLvM?(=Df<dzmjp{`*a>Nj@?{`#PUTJYs})Y)9hh!742od&N20K z%iH7ce_d7nu;=FCx10|u7$<&a=T_r9!SO|uO`uF8k!zOn3YH|HZw#sI7GFzWE&Q_U z#>w|N_t-yoKD)#&^Gk$n4(A>=Hu2TG&1z>D?n!Ag8t{GjdxMGX<HskBKW^NK_<G@y z|Bvf0zww1KEacSX{>73fUdeSv+5B&uu-dOZoX$U={xSMw`atZP?Y*#XC!fA$iuw3l zFqQQV#|l1K?)CCJIp!-C|Cq>U|67Dh^2@_d_HVOq{QtV~-kneTA6;es@u^De9@la% zOQB!9(^P(OA5z}?Gnh~4=U(>0PwU@Gzu~&B^uhG5*(bfnsqFi{n+jKQz2<Qf^A*X~ z^5*_8m;ASh|J5Hc4#s!sk5ylJUc2#D`~Jgs{Eu|F694oFZQ+gLDU^I9sia%NdqMX4 z-*|z$|NgP+zVCf#^J>%e!Z*wB#DB1UtjIa%_j~Rx4r4A;*;sKY?QfjUl5R{3MPD+M zFwA<(bML_0<M+(p7~e_w82<bqZyTd8=RJ0Pu4wr$;{56*EPI7#GaeC{!pQoU<K5T0 zsqgh4+P~fXfa`nk8%<vK|2-_xT;jX|3Kha@WPAVr7MjeQA$aDG*4OO!H=cBSk$-;R z?UpCA{_XkZ!C%C9harQrpEq5una@dV@*jJ?1uXtN&A;v5pZXB`)a{$&OOcPvuV*ng z{0`zi%q-04!~cc%s<bbAHGkEgdpzvSOe_jtKfk>BS?lG|ZwFtk`@H$nN1k@3Qm#Ta zM@DIpLjtvuCXCZLg?_B!vST{`EBq7x3(v2yuRebJ_p0dU&aW?cS=byn^VnmVHN*q> z?u#e=3**@O=LYAFzd7Gee6oEm^CRiSg3r6&J^icw?JVCs4sOo>+{w(Yb~eWQA`ZLV zaMZC2_Rq99DK96v>Bg^@`_4Kali9WO#Pt<AhjmWPIDF{sruW7yX>1QnZ_3vObb3VC z?XuQ1{h*T~pQBp(c<I~Y=QXZtUy8r!weiHRedl(ZZ2HdqD&hO#Z<Pv+;(vUV?ff)* zE#-B@4L;~yQhUjmC3WcD=_krJLrw=>ue)(%x8`2I^QZUE_!#;u>c{546S>z2##mpm zR5KEBOwrY|TyNB<9m6=Co$sOVt&00cPAVP}I=1=1`#m%6?Y~_1JmaSoTNC#@(`J*u z_Ira=&GjsPTU^swArU9B;Yt5(ud9!bOg;YkXym$iTc4h=Iq~_$&v$hUCIU;$y(~I> zF8h7AUFGcMbkZnE&Q0?CWA0~%FUB1-+a-G-clr8l!ABGJS-i0Lq{8ka;$p6=8yr*< zc+D%!E7|s?KDUyW+|-wEU%xvPci`Ig^}EtmKiRf-->bv#UkAUg<b1+A&2*Dqc!Y-U zDX*=*{<dBw=1Rw;4WC4Q&OO+@FJwo_w)*wChnSCiJ0S4t@S_DhKLw_m?$mS%DDe>W z7V=+ao@??}f>BoOrO8*3qbE*i>{+@mcZcY~<YSYLZhLKZe-&31#~z(xb#3qSHj%FG z-d%=HW(%aMMelz6%IJOm-}M~_kL=ReH|v<_sh$(rPp)2zVqU{^R%MsmIh%>5I`+n{ z^Ng9y0u-hx%KiVr8GW1SQP+uYhbA7bI;3=>=k)x$zL$J|E&a?dULaFu^i-?d_Oflh zMXZa4<_^`@oEP{$Kac%*>72l^c?WV2$sId<%Ja(QlSMD@zlamy6AUuY)2O$5;qb`$ zxJQcN4!sP)KSCKF-~3QL=X%a*Z^X`{2Y64Uo;-6h>(RFxTex-k-1R%PmpR*6J9~Ec zv0Gm>bCBd0^Zwe+XneWnV&?YaTg|rbIuvs(;P9oJx|e^lWpnl!%4#2V{B7Co+Ym6- zag9@t)E|kJKjt#-zIfu+rVU){4{d(2W7(0zC)eCEzL3r)!Q^acqZjUW)bfs>QP6#- z3J-tTvyvaaI53^Pn0{yf#-=s<H$-k*d}7UMzgv&a+B5$AdBmjGV5ajgtDQdbK4G3Q z0W#8(vIgI8{$6+O$s@n@zUxdjd#>MiLiYU2>sQX@GWY)wGMHqf=)B(2&QI0L+VzTm zmh2?yr{6FBvb}xoWym(mZKdnA*Vdj|bV2zh<5kO_Q{SuTE9?HXKWC-n{=<Hg*F^t9 zC1<tHKXHF9K34qrYlr<o_O%8p<c{^8X}$9I>Yq<7PntEfRIKc3Ed*S(EyR2Z0`_QK zFqrbM;oqzm5kK?~nVjcbUA(;H_`TCj*LU5#^~&ScVfkp$LsrbDrj98_2YuW8cnvOF zv$F)To_i<wC+h^qo#1r>YZe@~IDGHQwVQ|U|2c0g@QyLbRL1CrjiZ5)_gBx2HlE&< zd_6)+KkhKCxsmlQbK{$h()$E<{y)3*^2y6i$JeuFe!8vCr(<QwsVC;o<Id`~Iygc~ zLvbfdIM<JdkG}J4-ngS<8_)WACsfb*pMP-7?dQwKH#N0X%FLJQUh_WVaLd;}%3DcY zr;(MLOY7O4KWElE@2*^Lz5L;czSEmdNgQMRCVl^{)(-^^i@OF|{`Vbgf>*~JQTk;V z!Tyqa*DDT&vzrbb*}U%W(wL)WM;9D>b4=;2^VMZ4x5fNTJq){iX4y)Il|{c%_q2M% zuFEa;*`38{XX$yC)wdSgpGZ1ld_wc|mZx{m`Kc`teru+0#N?i8b}W)7%1JlX;WLLH z&-(BGSvK!|cYWc~n8nqHg!j~($T;uw(EYrO{3?z#i#F2=mmss8h>Jm*W=vjBIgat$ z{HS9xJEHz*?E<$Yi}r8dw(oS;6}CGc&*?~o{FkzrVpQPr$?Qo~v7dsKoX;Gd7O}n` zV*i9sq(2v5ws_-~J%2Y^pAERW<<{&=3;4Hx;4w|sI$_^pygO)v;|%-BepC5;WOe>l zGk(3U@$LDl*?W5S*>0L}R`Sx@OG@Yev&Xzp(A^|oZ+=4GIpD3sS;vEZJH!OECbL;^ zvpm}SYum;J$DMX*uKRsP@09#S*Na>K?!2F&_F5#{ph$<``-MfSo1d?kw6~!!UxNVu zJ0)h{ZOs=a?LM`U<xIr!z!UOkt3Lj}UMRDX-BiO;`M$?J(}jK}e!Qv%Ru6<FC2YU- zvrpVpbm#WgX`3UCsUO^V<nXz&XDXM^igWzmq|K#f;jzqQe&_<96WWdT*#hEXAAh&8 z|JcX>$bQ}1%@s%Y?>lyI*IAxN@|RvqKK}h&yF}@-=Pi>1;lf_ZdJ7!mMCBDc{;uZw zwEx8ObE^*Sl-vJ&+s6F@C!FqzU)Uj0^;uHyvTT-Xm?3}MRL@1`@g8<UPn49HdH63L zIq_!7V*4En4)kx`c<Ae~&o_>ps}{HX^i^Ylgp2(vgEujyp4KKouKq%QHTJNG2pF7{ zervF%<S_e@KijSyH$3*~=7Gx&yzgGURi7x_VEI)yAXwS4%zBplIl(fm434=1Z8sl% zTfS!F$$7`V?|yai%JC&<>(4*oNqCc>{FrBso|`IP*bRq+R{ahOgcY<F^DhujyD#=D zW9#WF(nk{yGM&16^v)&4t5%F$&mPEcVougIRJ!NUYNF)8W9KQc++Y&_7D<Wsyv$#= zJ-WU1(1OEHFWx*Zazg8D%&)5tZRDr@>sDkJQ}p^~Z0sgxmoMdSSSvAIdCkX#Y@s`2 zAGsa<aQfY;$U_&79X<W|^V)k>Vt+p~D|HBExgOAW_e!&KP-->5CbCJ@{%?*z>w(Od z4|i=nHUHd-W6_6fj#)fEc>RXNm(L1v30$sD6LkdwAKP~;XPQb#i|A*vOcmifxc%jl zJu;V%ooYBJvhUvh7mqBjy%IX`+D-m6yNsQdR*Ju_ZGx`1ZInc+ei|E#<i^upUr%p6 za&gHSzoR=3|2R~2YyX8bkqvMCWYd|P%?>MRhIu+%))BTiC@QUgg>SC>+Ot`oI=5fA zdi#9jDf6R?4|3hwb;*kN-m6^cC;y_1SQY$yI4qtRthcBVJEH%d&tH!3PVJxQ9o4rN zUnn>)eYWbv`g5nw+~-JmX(3zqw^&6)DAgy(w86~Te2!3;)&;S9Y8RfKX4c%z|KR+^ zsH-)ndyWa6y?pu$L&;Nj(Uo8SE4>r=;@WKxVkv88E&bYHy~GBM<)8j>-`l_AS@7u< zSNblmILmS3=Lzr6m+z=btoz<5Ez550_*d<<vy)}A><ZmZStTu@Ups|v@1OZ%;~Bo& zt1p~5f8`+e@$>IG?w%HO|9DH%mATihQ01J<LQ^N@;|4RNe6$|_R~5g1BJ`8dk+Pc& zmo8j7cWl<FdynO=d=V=9&?a^G{|D1Q60_W^OlB$7=--qO)K27<QnWZz{$t(|_J@u) zRBm26Y<}YV-8bh=_^n^ri9Y`&YIt0v!(GL|SnHAT4;gR0hdeJ7S6sDY6g%Sm@a>gX zSG`ZUpWShN>Y1q=%};B@fB%+JPvSLk%hoN?n{HYrdPZ}Ju&+Aj{SeNg1A>ny-gLdY z=<Ku$x|dd-h+w(#pjNo>>sOUc93jpY>JkPL#u?IydV*pB8k3&g;A1@c|F!RRle;~a z)UUXoy>a6DuX8sKiHd*wBmItPrIo9!gT*zoYf{&BJ0%R%=YH*we0<FL-Oei}x09}@ z-#B;N`FQA;O;@i9s(<}2w&Q=Z)qN>mt0+@F*|mBrWj|{<{h25$c*^2S$A!|nE3W>% z`QyapQ_?T?ot??Q{e7fV4dYp(Hv&8k+l*hT7@Pi<*r4)|X_msNGhcphK7HoanOolX z-X1MJm+;W`^l$!C?}J2D|IO0R=V5fNF*u^CVKiG(NBJs8m;B!=OpFgt3g5H2E^#m5 zWY{&i+s{vZ;z)fdB=MUuOk16u&vBocxVD$Eo5U@J1-x?<uiSpcQ+=fQ(cYU1kD||g zylZwP`D7sHw5N-tq8Qy&*8Xp@OP8(JW;Wa*`bq9N&llO+`#%L_PT9R~x_$M@&MT*% zc-@|VDUn(Cp@3NH-yk{5e{Dv4g*Irn>rNA{lfTKOEu;E&vefCb%Riaiefq5V;pMkh zw_aRU|JQM=SybkihWPrQmbz=XFRCxnWE3z{(&bwxd+_rL8S`uTfBc@rzASsz_NMBN zzzyCX4Oij?o`2~UTKd~d@dfj8)mHV@!pUlzd1g!2{=KhI^I!^7z~jA7?!A<H^W@Hx zn@JyvFW%t({pk<)g5TycvzfJ2->aAl1*@?L=twuQGRUVrvtyNcy6c(F>!Oz$_b=Yt z@M`(R)y&QB#JMLjE*4W_Zd8g?m?RafT_^lSvXzrxYT8?Cj`GLPo~pmT{(RQGTThlg znt8Q{q2t{)jvm$$VOACijWn5Tc~`9{(dQz&_>Kwjeh}l#e-!h4#?!q|7vE%lrT1XQ zt(!ju-Z*nOvZ+ftv4v}V5LH)BQIV8bBRq%aBVY8VXs*_~6W_Ex(0G35uF?C(dtDF1 ze_wp9!~dFfuJ~t`Me6B1|CN+vvqb8IT6pBRy*^##3A(r9+nvYGZ;I|Kf0cRU@lyTo z;+N-mrZBt^F=nt;u3+Vr_m*5EC?<4-gMoMRmkmNJkE{L(K7IEg`gz0m+s_kT?f$v- z$$PHOZxaOP|GFaM&M-~(j>smyr(%VivxS!b`75^fSqA&hmnvWK-yZ$S_ss6q+ppqx z<Jg|R%j8=6(@?DK&p(OxqEGp&Wd(TTMX&tdEA8>#kmtnv@XwX+<UjVky!e#qi}>w- z3};{MVO#ivN$@A5o!Bl>1p!+HS-$1cO6>O}_`k{XdVX;FT=>5HrRIzL=LYZR-I@4X z{>5~L?!W4Mt<0-LMMWY7gA|m7OU2c=14KB#Z|4aADDyG(gVXEV&%eABeY5yU;m>vN z{1{dK-{*<qXc9jm^iXuIbc=AFm=$jY&yAnIS@b`={`~)4^UJ(vChs1;6nNe6{oVWS z{}RkByw5q_NZjIECRQbWO<0HDhEIn}_wOsVz>ogl=D(f)Ve9jIpEtf_{_yI{^UsY8 zZvXB1bXoU`UFF~wjpx}X#LT14yNn~`-#ZqUPgDPyyubfF{&o8g+t<F|_kZvHY{zuq z*Lu#I{{uu$GyD^d<P_vL=i0=(jdR}r_q=kSZ!>@S#PY}H4dY*pw|l=N{n+~9`k$aL z671&R%7mW&3l-eRHiJKl`v;G_&?QDO!SHV$T-F~~G1|O$`nl|#_vfC^UthWZaerOG z8vV_l|HYs6g16aqdE<o2d4h!|uq+X|`>l#M=bQImnJ)!DHoePwKjFLR^Q^yf-bpY{ z`m&pco8ci(7Oy7f3BFt08$_<MxQi_L&BM<8Gv*)1mlvNoK5cj_^{wa~)2~nO1Q-l| zP2(tFeZ!N_9nJkpXf02R&@!$rz6<}pvn}}H^&{z<>nEL$jqh_mv%g9G;r&_o@8#b{ z?4hh~+`WA5++X?U@P6ap&Jo8Q#$dx3_-oCNn_sy;xqUYN_~Y~X&m}*izq|j<{XdVz zn_Zvh0e39dGj1KOza00tUbF3CXkk$Nz4nLJ&kNuFed7PN_3Nu|{y%^Jn)OTa{~l&9 z7DJ9)jvK5lY#TZ1S*LM$u*ERlXNdnN@z?6N<{!Nuem~=W`22GDHTBQzKSF<3GCXAX z$8wgroHdWRjn$c@iM^9Gf`ysI`Cr5T)IS^k*#1iTGv~*SUnhR=`EB;6|4+cbw!a5h zSeRK@Sy)!Hlrl?loMC5Yoy*F|P|U#iFXn&L?~FeOe#re?_~XHkpFh2RKKUd1M}et< zQI~ZFixb;wHWiLajwS3r*hQHhF>U<!{NLu^TYgLakoxiBN8JzpUpIa}{k`q?R>l>K z9IR@rp)8p!LF}pQ*V*r~Cosh^Dg0Od-|(mAPv(!jAJsp~e%$_f|7YIs?BB_ZDU5Qg z3amP;8mw12ZgNcI?Bo2)#K2tfuk7E}-&=o6eV6*K@Ll1%<}b}(hkqaWZNq5An8%*a zp2eQcevJJHdoo8VhZ~a%Q}dtZKl6Vr_$Bj0_Q#a(6TUzA_3YQIzmxx-WIV?>gMAu% z5_=N+b=DiK{%pQ%EsU*<>wd5Mz4_OsUsXTre%|<T=?CW@fj^r6760=xi7@4}WwM#D zS+nh8-o&iVqQ_#-XvO&NH{&1SKZ1V@ejEK}{l)aF>R;WzNeulARg5)^U926fDy*uk zVoYL8)lAh)ZyDY({QC3bkL4fhKd=70{4?{<j6ZAtZTuI;5WwKg5X5kY=^9f8a}M)P zhHVTl7~e1oGx0My{dN1B_BZ+OvwzS3>HpRHd+guIe=``SFdX}T=Kog44UBJ?-Z6b; z_{vbkSjc#U@fc(D|ET|b|9StH{jdDL`0xC`TmJ6&%kiJ}|Lec+{vP{(^#5t5Q%oj| zCX8K--HczEKQT{ZoW=O#|Cj$#46+Qdf203q{mJ^n`<L(Uhd=NCxc~S3znXCc<59+w zjOEP5%==jmv8-WQ#njHw&fxOj_5bld$Ns4OR{PEQhwBgfU)I0L|I+@QVLZwBocSel z6H5b25^D-;Jaatr1crWw75`TJJMsI}Z|2|sf8F?f@At;vYknX6cle(Ivm)~$<^#;n zSe~=Eu)4BNW}3vb{QvU*aerg~-v9mRckplj-zR^c`@QDxiob^$jxhu=2QY7D*~VhV zV$9OdJb_t)QIgU2pY6Yrzr}x-{9gL|->*Nv*#5HrE&EsT?>55?h7~NUSSGPdWN~J3 zVtL8@nz@XjgrWLh?Z2mgp8Was^ViR(zn=b@@OQ%BdH?49d%*aRQI%DN^*qZ3mP5=3 znbVomnGY}=WH|rl+#lILvVSi8zW5uIKBoMe{LhrZoWYdQi18QmU*-hnIOb5MFeX`M z8Rkj<C;$KS=i?vmf4=_$|N8!A`pf?J`Tqz1YZ#gtQW@eIrZCN7I>mI1NtjWD@ejiv zhSLnE7?l32{I~mW_rL#t-~U5@5B>H0=lQScU(-K@e~SOsF|1+eVeDhnV$fh<XX0d< z$TX2DfWeR9Bf}Sl4u&=cfqz2(Zv4Ie*XW<ozq5bO{C)TT{eOE#d&Un89~hXKS(w9^ zLz#~-9A>a&ux6P1f6o66e>VL2`RCW47k{7qee>ttpT++d{y)lejLDqIoarp{Y39c) z&sokfoMO=Yul@hSzxV&P{NDO|#_t)wW&g_l{ru<ipZ5%J8Md+PV!6wFlX(lvPL}&D zw^&>mycjC~7XS768}RqzulK(ie>H)E<!{r!#(!HGw=xQ`3bE$0<g)m)__KUu{>=RR z|C9d*{vQ4-^q2py$ZxUVbAQkK9sMuzU*P|s|K}OcF{ZMlvG6nVGdD3cF`ZyK$+Y+X zp8rOFjsGtGyXfz{KlA<s{tf>7<p0C}8VouN35+p}|Ctz>S23<+JjZa3VIkvU#+Uz} z|3CHj)Zgj<X8Z%?hyDK!{X6)7@Bbu*G=`P`m;K+zu%F=p!y|@^|IdN6GR|h0%V722 z<o{KMy9|8{9Sm0gZU3M8f8zhFe{=pR{FD8s$e_;f?En4$oB!|lf0*$gBPc(+F}gF> zGS)C|X4uS-`!Da`-oLy5=KU@DtNB;?ujPNc|H~K_Gh{JjGu&pn#}vro!@|PE$rR2Q z#2C+z!l3b2`S0{Uv;V04Rs6f}&%r;>|2_Su#;C@~%f!pX#KO$7g=GuNVx}cb<_x9` ztN*R}*ZZgMPs8up-z9%4|0w>I`K$b2{r@|r*G$WqS1|Lj@UsZA^0V$^+|PLX->rYn z|6Kpw`hDYf{O`oy@Bh5{)AG0NZwo^ULo+i7HZh-NzQDYkc@gtDhRX~!|0@2y`1|JX z;y(-ieEI$L_pQG-{}%o)`rpCO&cMUW$NY`y6Vn97DU6{^K};tZPBD1>^Z9q|-=TlE z|K9&w@Hg-8^Z(EOpZtI3zXpRcgCvt2(@TbD4Au;G4B3nsjAabv3}OGn{`dax`@ie| z&i~E-TmDb^Kk5IU|NsA6{Wt#~@;~gqF@qt)wEr{yPhjX{SjV`LQH?=~;Q_-FhIYm# zM*sgI|I7Xt{{Qmt=fASQ#eW(8Gyb3Vf9`*e|DONF7)2Q`FkWW-!1#u-fT@J3pRtEg zgF%~N>A%JQ^8V)imG~?9x9o4(-@pI<`~#haVZf-*xQ%%`voEtR^J~UejK>&HFz)@g z>)-P~ul@x64gBl=$L-I`zpMW;GcYnNWLUspz--E#&XT|)$Slch!lcXO&fv|!@sIuA z;XjA|*!^+*bNJ7JKWqN3`>VyE%`l5;I+HT9I<p~*9*Z5bJ@Yh%sSM};U;HokPx_zj zANxOse+~Yc|26;X_0RiX0b@Snd&c*S6-*UOS<IQt$&9Itz6?GLU;cmjAMh{m-?6`k z|DODN=CAKR?|-HL%l=0&gfYZ2#xs^M7BeO?CNdsiJjj^EkjWs#AjEL_|CRr4|6Knu z{%8Du;s3?|+x~6+C&(bk;KJa{@a5mPf3p~-Gn`|%#Bl!qng5K8OpH$$o-)`o*fQK= zxXs|o;L1?`zvBPNe<%L6|7-uJ{!ioI%707$NiirgbTc$Fs4?m?rZXoq=P~6m2{Vc^ z+B4cP*8Hpc$MKi#@2tP`{@(p_<B$D6mw!nN2@E`pJdEPZlFUz;A2DxX+Qt;Y7{S=~ zzy1H_znlIp__Od&?VqYYTmSC-yXD`8e>)lWGHhU4%k-V;2U9U~G4pYz<4hYEHZT<Z zFZ}=K@87>G|E&C@@>limq`&=tt^eEo&t=SF1f>gqCO@XzOt+bSFnnW}&#;&wks*d5 z`d`97mwyib*#2?+Tljb3-?aa!|Em~k80s0S8G;!j7*8-BVpL#MW8BHGg`t(9lfnDH z$N%_$N&f==`}|k<ukwHAzpejj85$U>7%CZ_{(t(vim{4Ol2MY;fx({PH^W~BP6l>{ zi2qUl@BF{@|M9=4|62Yv|MUOv|G(;g)qg$)J_ad9NyY}o7Dih}3q~$RK1LBn0miNW zcl=-WZ|T1k|5pC%``i2X`rqq+8~-={*JjXWxXO5qaS_u(rW=em8H<<-m^>N17_a}k z@h{|G@W1H4F@G2SS@`Gi--myB{`3D&V@PHwWGZ3GX3k)CXZB>C&oqxIfH9Eq?Y}qw zxc~C}J^Sa(pZY)be~kW`{B8JO^S_Ism!X-diK(BZpGA;ah&hQVk!cCzVn)k<*8krB zdHaX&FaO`zKXHE!{@wpq=D+;^$qW-1GMF=&=P=J@-pjO`X)@Ccrh^PS8A|@u{EPV; z^7r1Kr+=>gx%g-0-&KFR|9AgC$Z&{3k4cval!uC$3Yq#CCo*<1wlUuLclTfC-`2k; z{+{~#@Xv!k!T&=49r(Zdf8GDq|H4eXOu@|I%zGJkGuksbFv&5=G8OzU_|Ni>_22Bj zGyl5&b^p8T@6NwR{~h@^>Hn1f(u@*}y3B^mvzVqbJ!X8tc$VoDlLdnX!^OXs|33P6 z|DVQR?Z0dPtokGRU*f;pKc|16|9}7gnE3(oM5akhs!VE31<d)(g$%_E0ss8}$^4W4 zH|x*rKXd=g{UiNP=HHxuGyf$qq%urm?q}{~?qOD7l4r_bPG?qRQe=AZ_toF$f1mtK z{+sqU_;<kX+kfx=HUDq+Kj44h|EbJVnBOtKV}8r{j&UdR4(5%F8yNTfJ@EJC-)DbW z{&M~m{Ui9N@L$otu>axz_x#`ae>2k#rd!NcnV&PhViaN$WKw5RXA1on@=yM+;@`A? z$^X9m`SyqTAJac>25tsWeXq%+$)v-g&BDsa&UlmY1|tU(2h+vBm;N63yZ3M1zovhT zfB*eS{Fn6a@c*O#&-_2}|2E@&#x&*><{ykd808ri7_Ts1WSstg_W$XBC;#2{Z}-3b ze|P?k{+sak%m0u6&Hr2c*I>|On94kvIfF5i@hrnxh5+UO=4^&+2IGGw|BU_{{NMU_ z$KN%7SN{F`kKupAzq)@H|6lqq!X(19m2nH>PR8AgznOkA&0w6($oHS?KjVMa|GWQf z|Hu88@2}23-GAr*o&LAz-?D#q7;iCdW7^8Z$jHVh#LUB7%hbdq{a^Bb$^Vl7asLwj z_5SJnbM5b)zc2qj`8)C7lz(DOqD&i@HZVP4yw9k{tiimAX+6{O|EvCI{mb|VYQxO? zGyl(%KM(&b{kQ6$^nbDcos2z<Q<x_+yE3^l{bl;k#LdjXoc2HCzwSTXf9L+5`)mEj z>W}wd@4uD*D*t``_x+zYqbK8arW;IAOp#2nOtDP4OnFQT7#1*0{5RpB^FNn=JOA$Z zYx>vpugpK0f7kw9|5wP6&v2gU5>q)-F_Q+94ih8uU#5)=TN!r!+y3vzzu*5>{ax`l z;&0U7f`57cX8fD=FO4CE!H~(A={VyN#*d6&7|ocBnQk%MWti~4|NpsvXZ~sa)Bbn) z@5R4?|APOW{&)J{lK+eTgZcuS88<MhFlsQiF*P!&F=;bx_`l}=)c@1}+x@rwFZ@sF zU-Q4Ve+~a?|84)b>z^ls8^aNXV+;z6ij1~QHcX&&(azAuaNz&p|1JL;{-^v)|9AE8 zrN0LMjQ_>`i~YCs|FZx3j5>_XjBSkaOma-1JfX*^$N202um7e0i~rmHv;SB9x9abL zzYG5E`M2+%ErTV4J);ZbN5(gdN0?4B1vB|GsWWOazWo34f6l+0e|3NB{>J`|`<wMQ z?XU4ai+`>Rjtqv3ri|Q7>`aNwsm#{QX3U^Gn#qvPu;t(8e>H#W|FZpM`g`Her9T`0 zZu~pp|HS_SjC_m+Oh!z4%-YP!%<0UsOj1m#3~3BJ|GEEj{Nwm%@z?tA^*@*Y<o+%A z+ws5U{}+ZI3||;OGJ^X9Ooy31GQMY=z%YrS>tE-;dw=izo&I;$-`js~{&D-~{!fQN zhv7BDO9mk(QKkt@y-apY4oskSqY{G>L&Lv@f2{x5{(brT`LEVLt$!c?efl?<VIqSQ zqYI-BqYmQ{#)FLK880*PFmf^mF@!Sw{`ccw!N1~vkN(~Jr~Xgp-{ODs{=NAB=06Jq zBg1Qkw+w3-S25Z!+A+2;HZksG*u$XtU+sV5|CIk?|Aqf6|5N*y{x9{P-+%xAstjrj ziy0Pz>+5ZdTNu3<{TLM(r5KGFtQh|P`~J`Mzt8{De+B=J{yq73?*AG8*%^2lSQ!5P zw_<c;WM%x%5XczD_?Yn?V=+S|!|nf9{`>t8{qOeA@t@>BnSagy8vlXXJ)pMCM1~0r zTNt-8ax-x;U1q$(Xv1j32<mgh{Ez&9>EHE##eehuCj3kNr~Y60zxIFK|3-|4jN2Hu zF&<$&%9zKL%e0^20K=XCcm8kszwy7!KiPi||33H|@-OV)^nX+T888?!JY{&sP{UZs zXvAd3w2*NgqcWok<NyB*42S<6__yHS(toS|F8#~$kMrN7|M&m1fPBF4pW!j%eMTon zcg9<c*BHGSeHnZH_khz~%fGgN8~<+jJM-U+e;@vR{`cVj-TxmMJ~0?G8Z$m)e8zZ! z@i-$3BO9X`gE7O$e_#Kd`FG;qoPP`dng28T*Y>~b|A+r?|C=*dGE^{@GjcI<F+OH^ z%pk=m#kl+b?*AqK%l;qvf9U_me;@xb{b&9k`akIZqW{bP+c8)(WH4khY-QNWaF^jW z!)%6m46_(!FbFURFr5B>=KqHO>;E76cle*ffBXMj4BQM${xAG*!{ER$m0==-GJ`t9 zeTKUXYZz8DFf*_)I5OBXEd0OZzukZ9|5pF){)_zQ`yc;5^?&*QqW_QoKmRYrC<1OX zSTR~Kx-xn&x-vL1FfcGPB>j*7AN?=x-;sX@{xSS#{xAGr=)WC<EdvuH8)Fn>DB~Q) z`HY5)MvUtj)-b&O|Nj5~f4}}k{EPi(@z3Pnx__JgmH#jP@5120kiZzrc!}`};}ph8 zjOC1#jMEvWGeG(?2mUerWBT{)@7KSA|3&}L_&@2t5rY{+3S%<k0ml7|#~DvDb}@D^ z_A~S|wES=Xzy9CKe<J^+{u%z${dfG|DR7w-#SqQl!|28Mi18`oY{nUk_KePq#SHlj z9{;`nzx((4U&_C<e`f#8|Hb}~{tv2u^cnOR{1|;1T^L;%FELzVc*yXO!I;6AVcP#` z|6Bey|L6YC^Z&`e$Nwh%pY;Fj|9Agy{=e}*mLZPeIKwf9dWL$2^$hD7K;s|U3|b7| z|9}5~^8cy-5B}Zz=ltL8|GNLH{=fP6;oqwN%m1e_WHS8x|Ls30?-ei>Fz#U3&Txg{ z8bdNeB7@q0jsFt=#s7c*_x&HJkNo`Kvwu7cd<@|Xp$ry`mW*mlYD`lZr!WdJ3NapF zIK=S&-|K&J|CIl={Hy=B_V1>@iT`5$<uVj9tYcWsP{dfmc$4WS(+$R}j87O|Fid3V zVTk>g^so4D{$EfZ>fzr<e^328{_h*Z4~A^UEXL=I&lxW<U1hq;c!4pVA&Ftz|1JOB z|GEG3{Oj{q`=9#1N&lw(d;9O@zYh$b86Gn}Vw}u4g)xsQhiM<<LB`MjKm4EbfBygS ze<lBV{`UP{^>4+$i~p|t<NeS5|0%;$hC0RuMsr3J#zTz98C@717;pW*{eR~Fng5ml zEBz1s7x7Q=zx@AQ|9Ab*{Gau|nxT?Gicy9U)Xv|)u!-R`!%2os|2O{^We{NyWe{aB z`EUCF#s3%oWf^1`RQ{{{-~E5je@+HYhM50R|K%B!7;Z6KW0=k`o8bY&T?UZfKz*Jg z|BwIQ@qg?8@_$wT{Qmj;i}@e@U*W&%e=!DrhTDvf7;_lY8M_#J89{a4-~WsZVgCdE z%ludU-}<-u@4UY&|33V8^`HHJ@BjN4wlMfHg)vny6*Gl1MKOW;%76a<`@iPjs(+xe zM&hr`U#q|Rf8YK4|L@=b=l``CJsDY<A2JCtTQhqxNi)?ku4i2Nzx@B&zYqR4{|)^6 z=a1fBzrV77&HktS-^$R<FqLs9V=S{hvjww1^MA%qjCUArGkpHX^55aF>|e#dVSgk3 z3jN*jSK!}||2_X>81FHrF`Z}p&$Nd5F_QulBjZg*BL=tsa{pxhAO5@bPx#;Bf3^QY z{?`24^#2yajQ<>rVN6q*%o$x74>3(-I?SN-?+?Q>L6d)CK}lluHbpu8+OxH`sx4GE zzbvJ*^t9F*;nTOTtF51PYT@h8^AeaFd6vsPW0)K+t@^@*qcB4Mm1L9TRI@`Tz6v*; zXIl2?;O2+6TORLt_*Gzy3G+sA2HlB2`@%0-s~XJB7B{>pvP4+h^1zXHq2e=b3*Q{u zdc9(;(7CXei>GekS@1tze1&YapBC4iAePwqnsQM$6xN9vzRp(B+R=aO@39Zd`gf^c zy?x=+`ZVr!H*U+9E0}ue%Ch*SM_tg+@mnjcFKKgsmqO0Y;#0Ga&tF%xv-gtlt)O-9 z_<lZSQTZz$=c}pY;PEIXN1fBXOmv;}{Oec6!}csZvg{bw*2>*8&+dETzA0MB=EGl2 zTe-Y|S}iO4)VQC@VOHWi=CWdE=JEs|aNd=BOk-cjey&r`J``=Q6}$6C(=b`iGH{vE zDs#h_849LGevEQ5QAev7$`2jdrhLTiP~EYVV{X554sMqE#QMO}SK+U}rH!XSZ#b*0 zsTTL=JCb|$?f9_vX!K^;gM!Dk&xaloW;<|ZfxH`kl2e1SqVH;#k6Ic*eG;as!p}TJ zqjv{Co^|xmrmX$W$G6^aIe3ZZ{q-NJlA@+w4Vsc3*51MDrQU~yekdNg@sW>Zx6!qG zNA_*rwm0qA*T>lh<_S%C%&Ze4<r*+qKf$RkKvlKdbvpMN`J{6**hTiroIQ9bYU`1G zpALt;RX(&!H2%#QqcyVAgV@cYYzl*XRMtA|WfGM;dW`LVz=76d#s@ZTH#q$D;KOep zj%rA(|MK4Qqr&pQ71kD}X98K3Sgl`vmzPdFwDH@`!*dQf?t8HF`>E3hU;jIGT2A`k zudnv9DmK3H_LKCd`aPGGFnjvCL(Je{#Je}g0uD~!tGlQC>fJ+2*y=Bzm(O8(;VPzK z<7Vo#N7K+tP5h+3^L-V8x<ic5qfVwBwA#ONpWVY3NAGg?-fB{5VVCjzp#8zt$0<~m z!<CI+R-5DMM~<yWk{*bhn0&zT(2o79-cCHlFZlXVt<GsaQJ>|8OU&AxFDqI*%w&#N zu{dqcu>6?p&BaH(_m>}6Ir#be{&R(5$*<*29mQsPvzYZ6#<=W~^R_AZen>X%DC>{y zN48&JKj^*Z?fJgL8VqHZ@5@$x-Rv-1;j^c_b+_JI*9NI~=8Ik&7nyXR>Ye}Lu#;2w zecV-eL*wXacBY#zRdfE&b+1(Kb5pTjuQSgrMmWSM@7`;^Cx_0yiau0+^xD4JyNVt} z9y`b(bc<DsizU*lOWVjk$G%bfn43MHqJihty&OzO>YtoG@c!VA{f#>-Uv`~{;%j&y zVHm`1=G$ht&6>^GQq#)y2+KaL<nyV_{l_96>^tCe@ZOO}yUae8o?a`!{lwhlD{rA! zh4Fvm-wxg?9FEq%|Epd)uJ~)mQMH@u2g44oJ(IH6{a^o;WEs(q^){|z*<L#>%k&i; zmrEVB(0e;U#_ZtZ_X<aLUV3*R{D8q#p#u{+F5QV%o%<`(`M#`=hn}5<_CEVw0ZqgF z2c5#g2l`$<KP+*6;o+czX%BxMW#&(K#I94xXytZ8$=IRTcC%Wy?H0B@S{p9wa*FKl zepGeH_jKqn(SuLkJUIPG-0ZcMsT)_lSDV%;8)b*piqck9e@?4xI9I}Af9U=F|NF|1 z*`8W@z~oEmxh8Sj*F4r|`2#%j^&-q>+b1eCTlsx%Q+Rwr@^8+;)SK(~-8`aq$@=iI z-z}GN70SOTIDQj->-xiBnTfiSo@Bcz-^<BT?@vAb9kAc@^6kBahpyauadhEd_e-9t zp+D7K??|aQh#Gw|c;R?a$kvGAalC}m8TB8R4vAf!bL8N$1^45RtYQ?s`buNZpICb{ z@iwc4#xHbh99=k<>CAo*A@Tma|F<&-mz|G2_4UNv=lhR2v1DH7&~s!=wYw)7WNdEy zMRSS0E@OaZ!tJ%f<rf}(*mUT^Ii`!pPfd6qcv6g~{62&6de&xZVVMkrNHYgTZcEi~ zdCL2*&E_>e%lTsBapy}Gw|LI|`~K+cH}Qq9Z<r=?JU2fq*QHZ#&Lrxuzw6C^IhN~< zT*+tWJ(f7bebwYq!g=+-O&5}6l|J&BdUGfk2`ZdZZ#7HhVbQ95ep|NWh6KCmxepKQ zFRZ%e|6<{}GRDr!`<3j!y)@?GJgFzFaz(Y!{0Gw|72C&tGP|xV{{Qx*!!7UY47c3g zOPy!q*nLx0N92E%@q6yYIv+Ib6l_d%fBcrKxR)%!c=^ZInWx=u<=->DbNh?zd3Pb* zCkynsnam7wd405R>HZe=*SY%sh4ig^GsT%M6}{)b;CWa6>GeDRzn?#AEz$JKPrsdU zuGVp07fnG!H9kl6e=pUfT^|UGWnIvFIr*~6{mHKz@4WuK^xS?q>yNSe`b;a->jc-U z?KL{a;;8ugX^^z`{Vsu+vz?C|Zlyh5`*F_gm5kFaeO4>|*`_PPG)Xl{%wO@K!Q7vY zQofISq#f^ga1@_=_dw+F_7@w!zP_QyWqj+pw&lMpji>*&tAxljOWxC7{GMI(`eR4g zzc&jQ)?Lth82mcs&GsKZt{Mvdc(6{7m9a)y@qeYVmEu0Z7i#7&s)e$isK|z2&;Rk@ z^3q4YKbE}>`?KlFLWwyq^z~meE>xJtD5Vslx|5wx;pyYkLOM@cq--xwcrSYE`m_G; zyWemzbYEGjc=zL0-AYDhIZ;*yg{SIk|4f%y_#i_#=+RG+<O^3`9C-NS^@rb6UVURd zeO*s;@6TQ>Uxp>Ji@9W^1=PJhISW-hI3>F8{zcxR3(KGKyt?th@n7jPc^;`dGjwPF zYgYC6S1G$j;DAWCO4~~TzMl`fB=+86V>@{<^vT+fI$wMlS{_XoihH<8-;dEm@%-QW zGN(jUcvmU>d(6uF<B@}8<jwDYuU%z%_WXO&*9NAp`!Z5yFJ|cnF#VF1`Ts+jUn-t? zztn;Ui+F1v{}*3*_0?B_yG^eS{+;*Li}mW=4n^Dd?{#t*?@Ik;sFlo=`T1j)h|v8M z{w<G}h!$ND{`luf-ur`$Pd_(uhTPks=Kf`(M)rR_NgbBQBDON0-m3~U-DeQG{cy5C z*A>=xo^Nfw1h8;@T*|lZ!56K+KU7p){%sJS%08FRM=IvUXP)>6%Y{wvdvN7nJN+i? zEBlWu_LJ{UiugTwr*r*xl7hp(4`Mmo3hZIx*B<qACqMKSId;2(`N2)=x95I~|4QNH ze6vA1@1=&`m4Az6cK$0A_2ql?_oPt%-A>NZhYy6V-;n-$`2M>0bxc2h@8pqv{Z_H~ z-3lF1hDu3A24A5i{90cv_}|~I=lb!$Ou+kk_>ZH{HhkK}=KR}9VCpM>HHJ^gng$FT z#9NpS@pSPezv<&%cV`OE|NG~8T5lA5Tl3!ddjglmuM;9IufM5J`aD&+;h(>#Hj5wI z9-e8>JGk}kv+=*W$IWSVclCG2?>~M%=g#@gBH8n%Ro(o{Wx4);_l1tK=KuHMUj0O! zSLC6F!0o#&thXLk{Mhz4<o62R*I%q<X1$41=lXV8%Jjbm|4!D7A8$A{9{lCL^3alB z_Fgpek7sT_rCGWE%@X|bC0btYt+eX<Z>L1({fpvmXSMjeip%8wJD!xs8~AqLo5U#b zX7<k_&PRV4geQMmp)~#7T$P4jWkRn1x!Da^3tr#iD7^EQE93Dxp8k6x|HD2X{>>&Z zk0C?M@6#TYYwsT_EdE`__vD{B<3r}hPfoD^zw?*t=wm+akcX%Ko%((DpQMNi<0eU+ zPqS6cK88uV|DMOi@o&O!Gv*r)#5vsWPvd_6xSR99lNJAtFn0WZD01N6W9e%j)YOtb zH%YAgE5PaapZ$9<%gno092NJMbKZUUk5%CLp+A}IsSKONX8-*rclASw`i}2yqAmXo z*!2EC{1D8t^rjcvq6cjpvJdYwA9`K)C!UXm`Le{hKZ_N`K2B7T`k5jy<zFQ8f&Wup zyRn+xGH17b{F=k;kpT1TPj!F81qGS@Nu2rVuYB=Chl0YdwY+x!OBmKL?0hD~rf?^e zL*vO=_RWvV8JGN=`fr`EH{)JOj_*RMQlErmKmUHj)%joeuPhVCqnT`4clWVJK6%S_ z<?*Zko(xI<Z;I+MI!WL9a!2*s=L`woKQr0C|2zAmk*VUYJ)8CeDUSb7-m_`E==fj6 zeu|M%od3V9?DNm5Du2Ix61@F8oi+J?|0hwVOSe5(tDmHEL_Kw5?R&q1;Q((w%RjNj ze_qON`np45!&esW@;`CR=KoH={>wD$9xwCfXR_Q{Z`GNu$rj1VhwMxI7;(zf(0jXt zqiMRn%3sD8FHSk^db(cqe(KWo2j{H!+@^S;_U~Oz363C>Swftlfg#*!n`}Ng?G%5b zblY_H&xim1Zuz@iW5u-lYc_8_y=9I1idBy%evXma%u{G`^p9z%p38}t)1i^pGi8jW zLiFc;snP5{-gzl{J>NFAjh+v@FW4U6dM#>2{cr78FLmDuvzwOkNIOmN-s0F0eNps` zTrR_Z%?Z!h`PvTXZErkw@~HQ<tSj^G-C6PK3&Zsk(U~G2wfuxj^h@nhj6#zxs59t) zW<4(V<lAAX%@0gYZa;o;{em0Kmo@LiY^u6F^-vMpACYVc0dZ4B7K14^6=@4~&CRz+ zhRbsC=PDV!?7Oh*;-@wD&aFPDc4qO;Z&!{UT=hne!(Hf}jI<V`&MR}9=xpbM?(4O? zrKSqJk=pxR^J(x2#^v+(hoAC4aqyJ#fmK`UpJ)BI5zAMU*1W8s;h7Wl&!^J+v*8qR zFNsXq-EUsLHb4Glqs0!{Q)Sy$pL95WV)ul{8$aw2x-Ok)t*@fs!Ro;r^vGYs`nf_9 z&t1{G@01wt9ZK27xN7g7n0-61{yV0<GySRIlOVZ$avLoENu2btb9D578f0w{qbMWr zN6z%ACY$oXYX{Y~A3d~cr~mnR7rpj}y!X6&OXxQDY@1Kgc`jSc);e_ho0}~+eaO)) z{q)&lzOV})ugu>jzQg!%!llhOjvmx_$#zOr=oZIPg9!1b*0T-P*<T5F)mdp~Bv7O9 z|9zwAvP<i){XHJJum9-dQyZ>w?#+99>$DzY=I?E4TO}S^{4k0zbo6yLE_B)@bycP1 z3yTQn)BP{1&aK+@{>aC}i?7xkX??KipxO_Q@28}1NQ&w&&@?t*@4wIFmh%MV64k9N z&!u-h?Rx(Ga_8P#N0^Uw9cMXk<=&IyE8drW-o;-c*lY4m`-9mJ_p9bIE_{Z`I?5cJ zV#i*de$R6K`O%>LUI%>-uRQ+l+NopzUR1q!#CwQ8!RV9naoZ4=5W9T$eiLD>%>w&m z4!wx_E^y`EiPihvj;HQ$JhJQ(|KZQCN}f$;uVwQ$YgL--a>vQkc7^i}%Lzt*g_kO_ zKb!c+;PT2#y}N%Ny1ix2!PLtuj<md<d2c>vC(BxkCWXbWx;Be#f4j$8#+p@%Bq@hH z_GNl@VbW!-1C2+%Y&mvt!bR%?N*_z^Npqb1XK7p`xzdBhUdLvK$9eMwRvprJwEdoV zvRGe?x_<Sj$Wi`HExXsBv){-3>DrBV|HZy*>E%m4@H%gI$n1do4HHcp3B~ieGoPh% z#9ZEVOZZ&(N!{&F4{SVraktgS=IfFFZGPIRtP?!o_Sizorqz3sp`Hbc>Q$XnA14Xq zUtDyX{o?OawY%+(@E%;aUG?3mtM$L<e4Qxb%J$CrgVAd1o$g`!{^l<Yyi6?q^UA2- z41GTB#_J1(2gFaU+xvH?+oPQ)EWc#FW#`ppTwt+Ax!3lfTa?ibn_I^FOtkn)HMifh z`ILD(>}t+&>x=$d&9?o&`|9wLPyb#pFwFZ}Yt|$8+Rn^HKwrvwlI1dstwMjbr#w>s zed%t<O|K)9&nRzi*>m;gkpo}fNIj@v?EN{>aDn)C`+mFiCcTc6EmxT>mGw5d`67_j z?*Z@K^b6;%8f*~R6@4yj`<2%}ZcBc;_{KrAnBT~Gg{`*1OnX;{zjm4Gi!JnCrg1Sp zx$&g-g74+XHPd%FpV8W}<JFR@te-;PN~r2_Yq<TjJZL88-esd}dqsbr4dcfbA_6yy z@2$L|eZ_RG_TK4xeb!ESr+hW|<DxfdGN)MN{kPcKTHo`swwY=7%yg-(>&H^j!fUb* z!Y^r@+qU-c-sQW5HtcxOc}Dz4`RB>fOq{G<w~g{#R|Kvz*R^#qcw%_)cfXv-#hDLV zFLs~i-7)p#h0VPi?!I6;o&AsHC%3Qw^FudI?X}L_zCi|c<_t#V2A>&DD`j6f`YQYS zj*FZ3g`O|k>am04@wFqXe(n7b$Cu2w!<tpL%*obumC+*GxrQ?ODLm`6eD4JOT6ZJq z%Hk6Y*KTf$J+Sw##QwKG-Cvzz(f-|FaGOup_L}8;-7uSa<6!*>LaTK|A6KzCJ<_|s z@WQ5BK075&xZiZzyY=JGd$GU2eBGud%3ff((NI<Ir(LRPpJAtLwxPi5^Mc8b?H<Qp zFSs*lyW{Ek=jyimez3Z6`1^`4?-VMTI_=)*#u<7#)|uxU-&8woy#0Nn<n~9#&u82S zxK+F*>&&BL8C#X!uDkI5+p^ECvJV)J+kaGlWXkQ5Z6#>gp=)5e`_n|ZBlo;sFSzD( z_0jrmCtvPw*;@ZP;^eC@Z{F+6db1e27OO2ZFLv2u#bWotK*J>T(_DG~TVC(vuAjeD zyy^bwTYEO_xbbSz(YN2FKd?(qXW?*aR1mWCaqcm_X<KSgW^n)eKE>rXKYuQ{lX3O; zu0`k9?k?Fk^>y`;_#X>jH4C@1{IZ`Zon*GmYL$VF-A;pa-8;Yk$n)O4@mKso{&l^B z1s7TNzCQlvdC8$)Ka^iQ;!|alwpbuyZt}$VrKW;)y1uaXab|I)M|ag(wmoUO=YHzM zRi{0>&rW~ta6I|P|3`)F8BAY|^aMnVW@t{(D730DT%&!IbB}!fqj%gJo~b_hf8pKr zu>E4!FFs^C(fe)3Z9}HEfAU&;IJ%7j6`R#onHv~5YWEA3E2=zOE0p%K?M?KJtXoF= zByP6c%RkNW#rul;Z;Kxi>P1`$hRssR%F|6VjD8tTkXWo>`pQ=#=*^_BXKtxo*WGJ= z)8)pk)9c<(J?;E6`0EPA$($vI@uCmZ>`ax6?i)Xomr?rs;lB+3>y^K^-`BZ0Wsl8u z-U}6H_rHrdx%AVL*KZ`Jv-_Le6gs3TrPpX&ZxN_rr#k<$tIUJf(^w8aJa_B;p1^BK zXCklEzp6gA_~Y?s$ztZ5?j}?CwX~LLD;ru_zSVlFeCNBdwBxf|tS6pi+*^6z#kIa; z&e!h0d3oy9C%H#|1wGl;nXeJl)Vi#auOnzaTZdmw;m100#;2mZZO@-R%{r8S<@(VX zw@<xMKO6fw?$&Gm9W0woU-NlspOXEgxyZCdXS3Sgf87%69@hz6c>eL_-ILW<dk+iV zv3^s2Vd^*U8?GE24EqgD1@>z`kqlG1V3@6wthJl*fSBuJ38C&cR-cM4#$VMs)_#xc z&7*7i-;}N>GB5efr_I7|uca<pqwro|PW!m_Th1)8ThI0j_r9zBzU{`1>$yin@4tL{ z_ZHLF?8{Yu#J~Plt>-(h^Gf)++<(n8+Dy9Fg|3KOymS^`{Z8t?-~EU?b%%TJ-F?t` zf6ll3%MX8sypL3T$77~<j(>*?zp|mGiOx6iHxl-5bVZooe_)Y+8vOA0k^grU?&Lp+ z{<i+I*Y`IsGNrDv8|y#dn<jr+VTp#TPNi(U^q&tNq6}~Ea0Wix{Pf|`Pq*(~4|?43 zb?UXP-^?Db6y3*~t}n@dS%E{wNcFh(b@}PCJYQA_tG>L#E%CDC<(^Z&?!;Zve(Lb$ z*bR}N5sxMdR4~8Q%jNY_mX=ah>eiH0`XRIT`x7CZ=VCk)-u!s`<y_Xiix-NYZuqKs zkMY-q2N~SU{v_*s;d!EDBX&y0U*(s=PPs{c%|-S-U(8?pHur1r)w~Dk=Odr3_}KnH z@%Q0-=h?pe(9?+JDpdU{d_l@Y$zCx`E`j;4Nc*!Y{_1yv-|O#Ad;I%c;WP2~oR9MU zeSNT<Ddy`Q#TRVVD&GaG#AeEEkozFp!XYhY^GZ=L^P~UY7muA^TsnW{x#a7gPkR15 zzn}cK;{6%vvrNZSb@>y-c1sJ$-IRI6?<~Ijt&B+ahiwekUO2p(dfxB(_s2GmJAXUe z@BSVBwp=WfAzponK)(1onVm99vVEdgB<ns%h%9{<&G`0B-P;crn4Swg(0fw-$N3TK z?^~~(1yBBs*3jgSm3EMJmANRbDA_5_@$IJY^Vidv4!(K!hWm=ci&?i`J@x&W`S`{k zt#|pncYZTzX!3556PJ~goG8gBDI}Wk<D`h;i*%+HZ>PVLy&?Si!u5dXdcVw`r8BC3 zSj2t$SG#&C*H8IZlKvv|#2UoX1uy?xCOrAsS{APN${$zXUGQGu=7-m-ex7)KkvZk# zFOGsAf=V*1kK|8FSP6X-Stc@>m;e715#47+Y#-m2ehh!Q^`rRB)o<o~kACrlJ?Zls zmiyms$d)oHD;kKO<n0%B5Sq%pi}AYfhG+I%h3|vDdcLapQg{2(r{piTFWuPheW+o% z{LNZ?@z31~Uj(l6PZo9JKgs@teZ8>Xo9_a@-fsCe^S#^mU$?!!9(@!2G?q>ALm=ay zuY!U{zx-9?6j&+1E>X&Vf@1~mbP?8%dqo1@9sJ?*(fW({U4^gq&zC<9W8C_hn`!!Y z8{XQlKjp4+m5BAqY!k5K(dF+G*!ROkO7yMs?}`rwANU?z`(gKB!;@!!b)TPSJn<um zJ>pZpq9w;<sk!oef|h)lBAWyXe?FB+eWmwj(+8LLQ|^EII_*C53&!70&-EGEfAVpj z{Qh39ouytzK;A>>x8OTL2~L&2E5-a@o%~zy;n+*Qr#wHnZ|A&@{;vLP6-&yWYUWel zugmOZ2v&%Y(-pWS@K8jP{VCI7v6hz$867@8d8_&C*U#9SSKoj7n(*9{b@Oj=wimy) zOPBrrFYhQGBbYAqfd44tBBo-YTQ8g0*Sy^GdjG4VzxLi+{B!oliO*+oi~g<WX!yTU zMCR*H`6eMhUQyvQ+-?6_Sjq)>UKa3jzK#F%{H^+L*#~U@tH1cXS<4ahwT;96-!~D> z&(hN3Y}fcbMgMbcU=(ER;$HujOH}a<@3+hk%s*E?zrynBW6tY)oNGU3a3%kL$Jg-w zgw#<cKi>1AF>JO>GHiFbnLnHqoAB25cf~jJA17WYGCF@?eLIuw&Fe_Eyx()V<vu5f zrv2^X^%pN>KhG(~;>JGjYq@05`^x`n-}F9ayuZx!{EgPTE+*q=dYp^?xw7Scy)3-* zx4XbZDOa|eylGr>*?E6Ci%Y+E_^<!-ℜ++JBN?S$#asVD@qa^WncuY}5W43IF(e zf$yGJCC^@=l{{Q5GygF0M|~DxwEOn<CGWe(KeS)y{dn_T_?0osxqru5HZgA#c=EeQ z)Im6!hfBznZ^^$c3{yF4-mGPq{`v8%t~V?{4IlmebM=SThl?x$|NpYjW4|nR{m*le ziCi!FbOr4Bihtk!oyV}_Z5&J42l03RUQPVY{`@f8>u>hoezC3nJBLS;>#PXJuMeV6 z829p&^WNr^{Qcuk%|G{-y6k1|etkLe{`Aku&x|<_{tW-!$ldtsJoha&N3pVBG9s}* zSvV$g+Hi6*%=(q|XVZ%#T#g@){(bgw;SaGl)!ga7xBtuLT==<#r+|q`@YQz){%fC| z*~B>4u(+`B|6Th3`I|MoTp!t(zkT=q`TfI3HuK+3|BAT|z3by*{q4=a=XVmX%a_ee z-`JnBGVn$G+skzMtr$<<S5@}LU+2DT`E=>O$nW@nFIZb%yK!XwwCCkwtmd5cEuJx% zV<L-~kRbyz^U4o8?2o>Lu)g@i^Xcv<%byp1H2v>l-}zxNtNAZ;o<;1Pd|&>SFod$D zu(k?$vF0-ieMtT9|3#Y7^v{cT6(2r+>is^S=_|9qx1%h=ztefW`S<hMGix!4GC8r` z64YS7#klmd!FQdH&i|_aczkgDT>i25(|Oh`W}kmXtQY>?<aowk%-_$-#Nzb#6Z0&t zG>)hLIllyb>UgjB$MsM7SN1QHKNWrn=GwyC$!^Bl_xBffD8Hmo1;=ORU*B#swlY6p zjro7-v+4)Aw-LW*{oL^T>^GI~AHP1}vSHTY&SWqDdyIQF$3B4>tZ6J&pL`kC{F%#^ z%e3fw?$@X9cKu`jbDZVH55M1AzdT~sXFA6f&ie1i3U<@~pLnk`?qT-(bm5=fA5Au8 zcGF)w|IT{<lWF3wI`;10lm51R7ho=6-pw|RUHp3|`;i~Kd@4-rtZYBu|K9Y6k=c$% z_O}homUoXCx_`E_nf`nB+xFM{-zrQOnEtbge643Y`Ms0-6-zVA`9D2>lo{qQhVUKy zSI)lq(~bWYzxtWw8H;~z`@QGe_kU7<S=g8VxX0r7)q!I<YcJb$rf+|LvoQX8$YLXr zqLr1hGCkTx!!}Mw)WBV*OjvV!!rtuTiie#~GHq;{KXbk2KfS*N%%_+l)DGCmmnr1j zRX=8sWx!$~E9Jp>b6N1Zl(QbEE^hN&xncR~E&KVin046Z^OW0gd(SGko0PBd-m<{7 z(z2gZ`d9nnn;U#i_#OPXM`umsjF)R!eoy@<FIUKOSo(vWdCG~T!%2!EM^%5Dh{(T@ z-*V&3Wrc-P*Owg(-YUI%!djIJv+ndt-{NZ3nW<-<BAsj)5%2R?Mbp?oAy}H>gwW~y zMI7794;gNswQ~8I19zT1^_5i>h}2tUpps!5QyLQP{zHY&V86&5?wyDBoSeNXZoly! zscjZ(6?d$D&H3(!EEB)6#XY;v>B-@~Zn+lcG)fH4vZnriy7BS8=B?+Bw(r=prD%Qa z;izAYzuM)`32-_ccX^v`5gKWA*C<^*OylX_SMQY9%I?$MVSV_)_U_G|yX`JTF&|~# zr!-k=ulIK!%fwaQpA16`X2_qHfBWq6%|B}r_EqlLdXR5J*2YO^>mR-57vQ#0<4{`= z@ilyA#9_xWEd?EQSt&`?D^;iOuZ-DUc!+D?*9|5c-(9zU=_Ogf?_e<5U|y_8EPJ4( zW4-!Pohbq~Tp~w%4o9pG-^aOIbaUk9*IN`{9{J28xsCU<#b@i{l=1{8*JZXr8i6J` z9HmUUI~exP-1Ps@^BtM%(>EX7rty8}w?qX&0VT&=XREXi(F^PkSl?HvFirV&>U+sX z=Y6ZU{yD<2HEJc-9{Yoy3{1cOD~s@L^XBzXiH{7~ZN_A7rDSQ~^76o2t__=yc<!k@ zD!b|8%KN8+E+lb>{S#6x7cmOm?rRV=$K#xKuxXKuwU*|cZ}*f|Pdw4PulRVvmg_6I zuH3yjPdJKcjh=~gU__?>{h;p-RXW>^b_klwoj5z=2E*n*=k#|kI3&7x-KPAfR?lAx z=l=U@z@sD@cf!xht;xhi{gu8WuehMiA?NcqH?O_Ce4qcp>h1Qs=e%?NwpXT#oyjUs z`(9*#&q6y^0}Ewt?eafo|EulQIXQht_=TT4LU$iKsCew|uRp(6%0A|maa(ES6ZOR- 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 A%K!iX literal 0 HcmV?d00001 diff --git a/ringtones/default.wav.LICENSE b/ringtones/default.wav.LICENSE new file mode 100644 index 0000000..98b99bf --- /dev/null +++ b/ringtones/default.wav.LICENSE @@ -0,0 +1,4 @@ +Original file name: 171324__swidmark__ringtone.wav +Download location: https://freesound.org/people/swidmark/sounds/171324 +Uploader: https://freesound.org/people/swidmark +License: CC0 1.0 Universal (CC0 1.0) (https://creativecommons.org/publicdomain/zero/1.0/) diff --git a/ringtones/konga.ul b/ringtones/konga.ul new file mode 100644 index 0000000..2191150 --- /dev/null +++ b/ringtones/konga.ul @@ -0,0 +1,11 @@ +�������������������������������������������������������������������������������������~����������~�������������������~������������������������~~�������������������������������~���}~{|~u}�w~z~z����iu�������k���i�z���r�j��������������������������������� +I�/$�����������������������% $5Ȭ�"��A/hnѡ������������PD? ;�������MH�ů�����������;1!"#.����cLG��Z<%.=ϾO0,,%'/Cཱུ���\7.$"$))+,//58<Xʺ��������������������������������������������qA84446>AA<2//4;>>=6/*'""$*,.+&"!#(++--+++*-.3>QS���nd������������������������������������������f���\D91//.)'*.26BA84.0/5;<41;>BEAOp˼�������qѾ���������Ȼ�����������������������e����XL>B]����OD;36//153/00,)).<GOU:18>N]SNNTVTID<??ELOD:;18=?Z~������J?Lu�����[EW�_Q��Ǿ��NMWx�ֻ�����\EROe���hF<:BD��YOOT_OPOJL��������\2/,087>@GKOF�bFD??=<<B]u��˼�jSj�����û���Ⱦ���������YS��^UGO�ý����ONLMEI�������xLL6/17COYfY���ECh���Ƿ��������T@CL`v�j^�����������Ƹ�����]�Z����RDCKt�kc��������|I>>FO`����nJCCENLGbmWJ>EIWWX[`���L=>:9<=Mr�����¿����̻������LK\���_SGE@GF_��ü����rW`��������Z<77AM����o�`REOkcb�����f@?FJOMKRPN^`e}����YXg�p�������NF:7>FGGDTu���ɾ������e\����������������������vh__\RSE?:9=::=U������{^gi\m]ZjVM]��������������������dNLSloYJGIUR]���������������������unk�ʼ����MJA<;=EMY\JG?<?EC?>@GFMa�������Ľ���NKFIPV^���z������������ne]t��l^dkbUKD>?IR[ZY`ov}�tv�iXU^m�����ÿ��������d\iprX]\XPK??>>===??CJSgho���u^s����y[W_����gVWY[\n��������˾�����YOq���jXUZ����^QHDHIKNdniv�b\a~��YZWX~�������_YW_dfWScz�������������rk\dq�v`]_geo{bVQOLKO_��������j����������������^WSNDCJKMJMSs���TMGHl���������������q]Xl������\WZTKGGJJKLNMPRLNVVOJJORU\���������ſ�����������p�����m]SXXZWNMOX\_e`ZXajcZSOQ_�������kWQKMQOPR_da^Z_m_XOMMRZYZk{���������in���������������xj]ds}yrjd]cdaTTKE>ACGKS[UOO[m���zc\Z_����������������������������z`YMLU[k���sVMFHGHIMPYi|�������o��������������������������jUOLNQOJKLKLR]c]VUSVTW[et�����xhi�������qy���������������������407=>LS5J��������U������( ')1�������;$& 03˟�L!#,������.6����-$N�����M.*8ì���0!����:&$'G��������D))7��������K9ϫ����L(&*+8Ӿ����H>6-3H��K:)#%0����r0$#$1��q?&$.=M���?-,+->ƫ�������Ȫ���H/.:Ͷ�������v.-:l�����I-.78I�ƹ���PE7469==61/358Ga���~?/$$+5Xϻ������������YC<=T�������ORTu�������Ͽ�����������������]@?J_Ƽ����C:55;99IohdK@FFLYlO9568;;FZ̾���QGDEI߿��þ��f�¾���������������jUM\ʽ�����YOQTR�½���wMIN����Z91..28Q�����U<-.07Q���QB9<>Eh����UJ?9=bµ����<89=�ø�����eOJD\f����h`Uj�ļ���NHJKX�¼���KC87:M����jKBFBLRT����L>?D]���vDB>>BO�Ž���J;78<I�ȿ���tnb��Ⱥ���G>;I忲���������������K<<DL�������NIMbͺ���L40/4Fa�����mD=<<J^t������yRFEN��qKDDO��������UE?F��ú���������������fJA@GV`q�SPY������mYL@61/1>CN\hg���a]_O_��[KIM^�����gIMKK\��Ƚ�������`^lml����ɽ������_HHNl����gOMDE\ndvfn���xWH?=7103EU������cMCDJWZf_bapk|f������gK?=DL�����_=4:=FOYOSQq����ټ�������˼���������ƿ�������X5--5<w�����UG<84873.,'$&(/8@BGA73-*.2?_ķ����SBGU����nH>AL�����������������������ǽ�����������������k������_D1+('(,6?KILG?;;;99:<=><;?ADPa�y^XID>=Lc�½��������ĺ������ey~����������ž����o]PQ[}������tC<78<AQc�p_^u������]J?>:<?CRYZYSOJFGKY]������jbZ]|��������������������������iYRVn�����������iWQLLQSgdz������VLIHM]^SKFFIIOOVV_b\TY^_n���ml`_UOQWp�����������~�����������������{l��������zTQXj������{{`^UMR^YONMLLS_{}kVJJJJN]j����j]NFHIOPSXUTaf~������eSRYc��������gho�����������������������������{VNZc��������pbjhZOPQPTV[[i���dYOOSY_ibh����qm\XX^]^lwx|�}y�����������������mico|��������������m`[^jonq���hYOMOUhwt|ne\^hjn�����kWV_n��ha]\Z^^\^o�������y`bn���������������nnnw���������bYZg�����u\Y^Zcl�����rs���zxmm_[Y[YNLS[^_f]NLQTg���������������p]SPRW]b|�����������������������sg_jj���������px}��ۼ������l�n�n�/0223FA34;?=;<;�÷���ƹ��������������\NNV`}XLA8679;>=<?Ol�����ȿ�������f^Od�Ⱦ��������|ROKE=?Nz����PG=;=?@AIV�����������aRPHHOd�þ������������r^RQ[m����}cYSLMMJJQ_{����ƿ�����zZMPs����������jWNHFFEJLNOMNVXTRNKFFJOZinit�����������}ssz�������������ia]_gmgeho�����������������������e][]l|�vfaYXchyr�mib^__`mehjhin��������tomnu���������oqpz�������w}nnojnwmb``is��������������{njewpp������������|gZY`hbj�����iWWURY[[cfgnwz���{svpivlp������{h`_cfp������ndmjim������yjrn^]bd���lv��������ui^^ft��������ccdgd_a]ce|��z�tu}xx{fxr�~���nyibgrqq������|��������~kilv���|r����{�����susx~�w����}niq����zdnjhcmw�������kd[\_nu��{��le^a`_^\]\^h���������{yqnro��y{����������}mnig������][aeg~~�����vu|�}�v�uqj��xj_]diq_h�����yx�zqd\\^kx�����}v|���vje_\Y[\i��������ln~�������h`j}�������|~o���ysolbicchjnqnhhmpumjw���ym_a\`^a^\fv|xy���������nkbls���������vy���oiuzy�������mi^b{�������tmkq~�������ytv���|mjhjca`dkbfcifcefix�����yxq�|qtw���zxww�������zffnn{�����������������zmorz�����������rhd^`fhijpojlqhed_^[\]\]_``br�������zk_^_f�������������{ypichz�������������{}v�������������}ufgfjkorssyswo`[[]_]]^^cfgt�������uha`agt{���������~uuonp����������������viifhflwxpwqxuwuv�������������������{wv~��yukgeeefed^a__cegu�����{��vnlo{�������xvqr������������vrrww}~wx����������}wwt�~{|���������|oihh{�����unlnty|yrvqqompz���x|oojhegmv���~yyz~�����~~tvp{������������������z}{��������zqnor������{tpphc`bckooqt�������{|yv����������{v|����zrpsrtzvnniiiimpu~������������������������~xpommntqqqkgedhly��|}vkgijpw������������������������}wumlkltv�}��~�}|~����������������������������}uvw{���|�}vnmlklkihjjkkkmv|�����}~�����~~��������������}|���������~xsw}|�~yvuvwx}�����������������}�{���zwnmpifmjlinkn��lrul���swk�l{ll�����mmp��j���������omxvoxtY�_k��jPf�����������_c>S'# +8�N� $�����R�������������������E50m&/-F�T�U(&#Ҧ�����������������������P3<�)$*\Z08:C()/+ />*,%$A�鷲��S�i�۬�������������������za/*3<=,!(318Z����������������������������U]UK@/..23))$ !&# %# "%=ͽ��nY]imϴ��������������������·����l9=H<D81-# !#+2.,-)))&"%+1BW�WE_ǯ����������������������������u?:0187?.+)+/24(*((,-,-,.FeZwf>?=Yо���������¹�������������j��LA<==IY�nIo<A9<J<Yd\YHG@AJ����[_S����z�ƻ���\��������OH߾�����_^CE6��{�IbC>UA>@>?�����[LOUU�����r��g������dOK?K����M�lKS>=D����[F;?;?c���\������ZǺ��ٿ������p��ƿ��I�OCS��wN91-@_osGX@:7;=<o���^Sk���������ܷ�����������ÿ��s�����S_�`MCV����WH?7<8.3;EKOOC@CSe���eMUv��ķ�������Ŀ��ҽ��|[NMX��Yt\@FB>:;:PFKERg]J<BcVw�����cmlOvo����aMk����LG>>���ʹ��~LM�b\\X^W|XbW`�����TNY��������iWU�`k�����LJ<?^]yKF^[�|^mTUgxf��WTBLPѼ���\��k��r�ͽ����d��������kMWXT`_u���Y_P?J?GN]REB=A?Dl�TJDLGS������������ɾ��������������������SeNFC>?768<BBIJTNOOI<<?EOg������p��������������������lWMHFgWdiYK=<=KTYg�lNLB<?Vv���iPk�Ļ����l�kZ_�ʾ������hZ��^G@EBKe�oWNNwsk�\__[�XYck���������������bUp��������������^OMLBCGORTUMMWNIGDGI[tfNFMx��û������������������miJ??ALH]aI??EMN���iMHX�����i]O]]�u�����_VKMd���PNPg�����ib�����������hO����iTIIJX]aTS\Z\e^Zbino�t`_������i]}���������nd^[f��UIORYa]x�jXSWW[UXhfp������������������x����SRKJPYaeielhd]][NSv���l��������k����`������vhx�z�vd^e^ZVf���bno\_`}db}��������������������njk����dZ_ja^beVUY[OMNOUn����������������������������cvY[Z[d_[YOICFKXyoZQS\Zt��������������������������������zUTSNNONPUSMQX]VPU^OIKMKWs����~��������������������������mz[X^UMIJHHISSLLJKKMOOQZr��������������������������{d[\f�ePKNIHLOOMOMJLOY[]d����~bs��������������������o������ma]ZXX[X\ejZUMMUPTOKMO]inmshbs}�������������������������|���f_WOOIOPOMOP~�ÿ����������������������ƻ����"#&$&&E�6%'%-7Ȫ�����������������ļ��O5'***&+&,0=?5<b�1!4:B13*%$.4;A3*%*6¹�bc����ͽ����������A,,/=�������I;49=D�ǻ���������A2+-5/*)('*'/;<;70.29M[]I?HQL<>O�;����MDB5,*$!"'0>@Ki������μ�������������������������������ŷ��������������Y>:64<CKF5/../42/,(&(*'#"$'/53.(%%',./00/.-.126C�徹��¿�������������������������������������OI=91/.,*)'%#!$%$%&'+-0357877::55=BIKSg��������������������������������������������`[MA@?CA=<<<=EJC>;:7779:==><;@@AAFo����\z������������������xfYQLKISOU_{{ddZUh�vdZNK?Nqol������dMLY\Z������zRNLHLN_ZOHFMO�fONINRVLFIMSy�h`nl_[F?ALYusenxgRik_Zlvkl�������û��Ǿ���������[\[h�������cJKTQMRRy����ucZUURKKP��q_cu_Wk\LJTn�������xUa����ƾ����������������������{�|mqo����zOMR[Rcn�[KFBFMOMLSY`^]][SJIM]op~�����~��ȿ�����_Zd����������s{[c�����������lONMWk�����WTWf�w_^YZTUT[Z|������q]\��������gZIIP^����W^]ZQNNULPY]p�p]VZi���������������������z������������{��zhypy�ma__WUNP[mrz��n^[neSKQW_�b\VNMIGIRTPPJHKPNJJO���������������������������������������_SPS[XUPQU[Z`ik�nm`VYYellf]_`eZZ]Zj��������RNMKLNTVagf^c_n���x_Za_p��������������vjdkkz������tnx�����|��b_m�|e_jeb^VKIIKLMLMU][k�����mjjd��������������zbftrb[]\XYTOORRRONMMPT\g�������������eiq}����������������m�������\S]ir{^WX]tolj`ZVWWVPQ[_\[agai|�����������������}������������{y��������tecXVQPSSV[_YW[_][]jp������w�����zomhss�����veYZTMOTWYY^k{����zj���������������������������fca\VXVSVVVWWYXRZ_YXTWZ[Z\_h���������������������������klsnkc]_binsxjnp��nh``eo�����vjb]XX\bihgoe_c`iqkhdco��������������ux�~�������}z�����{oeklm`]Z[[^bb_b^VTXZX[eb_^u��������uv���������������ykl���������yk^YTX\ky���jc^WXXWZ]]`kyxx�����r�����������������j�y��smm�x������2/L���V:;�������$ 60�����)������ + +#ɶ���! +#�����3ї���f&8�������F<+&6ʷ����0*:���/]���������$"'*:J�Ϭ���TFɬ��?E-'<�������8R�����Q4.&-�������79Ǭ���@+#"/E챞�����������B.=���B8Ȝ�����/9�����7%)<Ȫ����U/*(,=VSH><Vٷ������9>��������^���U:37/-,0���5-,-/,.8O�����>@˲���O������N:B����OEN�ú����X?6/,+3X����Ͻ��[PF���GBc�������e.+=W��D;436=X{SLFC85<JhgN>2((/:�ȱ���X<--;Fmy�������Ŵ��i9/..9Oī����{+*+2F����ϼ��o����LB@58Aį����5)!$3Mȸ���U:.-..03@�����_����hF:-.6N̽����JE?89=\�ļ�n_����������>>N�÷��kLC?GR�������d=>HQsŹ���������ν��k<47Alɹ�����MFEV�����^86=DS������C4<<iİ���O71/<W�������S:>CUƸ������]JCNڷ��J84=n������Y9..9Z�����o<9?EJ_�p���MA;<M���[F88O�º����[I41.2Do����������XL���YOKM������]MQHH^������W[���~iWJFDDHE�������W>5:Qϼ���I?<9Ht�����������jB:/.9W�Ƽ����VG=;AL������ngPc��ȼ�zC>;E�������jSLILKI`�����KHNv���bE=9;F�������A55Fb������M5,*0>�˹����OI[k��lR>;>JvϺ�����^A38=BԼ�����J:<G^�����C?EFGR����rL:>L㾾��VB426;R۽�����ND>Eo����������ſ���O=98=L]�ż����ZXS\oVQRIEFMt�¾���ZB>K^�����L768C_t������GD==??Mt����������\E>?@@D\���������PF>?FLYl^X���������Y@87?L�ž���TLFHR\�����eSMS`�����������wuqJ?:?I��ƾ����O>65?N���l��������x`D=>Bj�¼�����D@CN����TJGMe�����[XPc�������^KJIKO_�������VNMSRP\p��eVMN[{���~_^_SMSi�ļ���tIFM[��������}zml����bUURb�����mYOLOc������m^SOMZZm��zeYf������ZGBFMOZn������f\POKP[����������YSJMf���������OJHN_���������lsaQMUp���������kVPSVgo�������vZSQRVWh������jXTMKOMWo�������|oYTOQX`����������lh^[_k�x�hn����^OMVi�����{�����������SWh���������[VU_�����|VNJLTk��ona\\]i�����{_\]i��������eZZd�����re��������dYSQ\hk}���vigc[NN`�����h[Zc����������������kTOKVic�����lkcNN[cl����es�����zePV_h������oi\`kjo�i�����cP^\WYU]Xodޮ����������+/"2 >6� k�����NO����������������������'*' 0$'2<o0(Ī���˶��������8h�������?,|�.l���,-,"(/-' -̼¼���������������������������y<K^'"%( '(-:J^P������������������������������b:;?1(($! ((#++7G��^�����������������������������Y<6(#"##"$%#&+/0J�Z��������������������������������BJB=.(,+)'% #&&% (/77;A8D�ɾ�������������������e�����]mYG;32GJUJ?:F;U�����������ҿ�������Ű̸�̻���\I<BK���QG7*(32.9EE>E</..?8LX_U=HcNZVHN̻��������������ǻ�����EK@=O;_���JH99?>:8i˽�eO7C�g�Ƽ�l��¾���Ž��������QOgf7.=<>[�KE0(*+?�V??GC@N��|�Ŀ��z��ú�����μ������ڿ�����e_XbW�����?@F\YmpQh��wnA;?@C551//<Lp[@H<?Xig��ȶ���Ŀ����Ż�µ���������ɽ�Ͻ���KOQH\N{��I89@@>:CLINBK=C@;BEYh;Hf���x>98G�������ZU�Ľ�ƽ���u�e�o���II?J�whYNN�������������gcQ`���T[������������hICIMzo�[GF=HIIYiSHR^TH227O`����[\]Ou�����������v������YJEON�����YT[ozoOYQ]^��]�����ɺ��ĺ�������������f�WOLA@78473765<;>@B<?<CK<@?>B?[K�ƿ���¸���������ɻ��������������WZKBJ>EKMGCB69<FLFIB;?Dc������~��������RT^Zz�Ⱦ��RKTL\ZkUGCEVOYRVWOVVCGMW����������ü���������������������flTHF@=<;8=@<7988>ENQKCBRa�n�����¼��¾������������]YP]e�[G?@JLGj�I?:AO����y`hw�my]n����]`mݿ���`���Ż�������������Z[NB>ORaNF>78;DED?@HDIKNy�����t���»�����ľ�����þ�������p[INSNLAGDCHNZh[XaTURgwYV[k�����|b����������lYO^g{s\SS[^^XRONPac^YNVMT\dy�q[f��������������ǿ���������y�hubZ^_l_f^cpZMGLKNPWXJGNZY����ve����ykr�����r]������������_��������od����_�ho�����fr�_a[_k`�d\[NMVo��idn�����������zlj�����yw�����l_TQU[jpq_W\TYWYYW[OPX_vsp���pvqj�������������������������kp�����`bcjf`YMONKMT]TLIHSV]YUWez�������������������������~^Z^j��YY_ZY\[_YT[WYXYd\g�����b�������������������fgWg�yndmshh^^]tqm�t`ZZOTT[]PPKVXZclrkj��������������ͥ���ICL����I,&$$&$ܭ�����ZF~��ô�4$ "$'�������-&$)6=ũ�]-))2浤����L('*5������4)06ֽ�����L/ (/N괶��.#%%5è��N*+/A�������C,)):O������j<3G����E. $'7K����bGLHC㻵���JB;00<Ȭ�����YKO�����>58=Qjuí���:,()),:u�̹���EE\ɾ�X1-1;���������>/1Iί����H6<>=qؿ���TF>89BOTM@<>FMb¼����F/%&5O���������������wH;=Rپ�����a?0./9c��]PC>BJ����`��ZFG\���½�f@>K绯����d<867:DȺ������biUA;@UQIBGl�����W?619P��Ǿ���KJNX`�������bMRTz��nKFJV�ž��vJLD?ESs�������]XW��WE=>?Ga��Ǹ���M@>:<ES}������r[m��r\\JFO�Ž���Z?66?W��ƽ��cNB><>Gd����������pXMAFLX�ʿ���]`OF>CMc�������h\NIV|��LHLU�����WTU]n��������VV\WWr��������������L=8<Mg�������]JFHKMS}�]ROXmr�uXblr[Pl�Ǻ���yM;<AL�ľ�����WGAARc�������~O@AOVSHEGRcɽ�����d?<<?Z�ȿ��������j]f����_OMQ\���bSO[��������_C>:<LS_r�������kRQi��WOSy������\WTLMXi�������`XHDDBBJWlw������p\G?BIm�����pgRLZn����������q\J?;?Lz�������dNFELNVW`w����������tPLHMz�¿����ZRORY^������aT[flwwhULHFJ}������XC?HR�������\?:<?O�Ϳ��������iaXHADLa�ƾ�����`@<?BO������XJCGZ`����VOU\[[�����jLHS_�����eLDAHMn�������[[UYWXcmzt���������PD<<>Hl�������`THFKSb������������\QLLh������^IDDKTd������]OJFELW����������~ZLIIFLV��������mKGGJYl������������x[MLMVk�����|eSMO\m������of^[[\d�����������_NFIL[u�������VEAAGQVem�������jURNLOT_��������\QPTm������zmlj�����o��������mcVOIHN[�������gROKIMV������������aVVYVj�������^OHISg��������o]V[lkccfkm������ZTNOYj�������r[TQVZo���������vvf]PMQWk������i[POQUZg�������xlmmgfadt���������[TOT^o��������c`_[Zj����������kZTUV_h�������mXRPS^c�������|ohc``_i���������}ia[Z_l�������whj__^_djw��������ga[_v����������}no�����������oh^\]]]_x�����wcUOMOUan������|�utsnfj����������g^[[e���������kdbejt|������qlfb^_dmnhn������d[Z^y������������wz{jd^^m������i^_^TWcr������{s~viihf�����������tnfp��������m^da�Ƶ������������������������f�m��� !T�n.*'.�����������������������/*"+,%')/B��<&P���- *8;P������������C50)""I��������ļ�������������B2*%)F������g���6)(7iU>-'+-( &-/I�����N>+% $&)%&&)+.:ر��������������������������������������������[<-()*)-47*!#&/63*%!$!!! #'4Enǿ���ʹ�����������������������������������������_�sK=,% #""!!(-9HU_NKXWVKMZǰ�����������������������������������������ʿ�����cI::40///+(&""(/250***+-../3364303/.39743.1:=Wt~�����~HS��������������������������������������eGB@ER��QY^V^NQLWSkw_O\REFF:1102029:<=FUUID@=<>>CYXw����\MT�����Ȼ���������������Ƚ�����¹������������Ļ�Ǿ��|S:658>CDHEGMG==KPONMTx������hA95467<>Ar����������Ż��������Ǽ���TL`����Ž�������WKLQX~����nKFJKMGCKMHJACUnb\TY^�VE<;98AAPf����������ǽ������cIIi����~TNMMW��ǿ��������������h[M>=>Nx����lpVQFKYVZ����m]JGECA?DBACPYk�����\OQg}�������ZKC>CMPUYedw��ƽ������u_r��Ͻ������d^u��������aUNPKEC@>>><99?\���w_f_PSSXYbr�b_���������������������cYRWowdPNSj|���������������������r��~������XOKECAFEOSQLE>=CBDDBCLNbj������������YNKKTZbr�u�������������s``����|��f\MEDJMWd`^oyo�����q]VZci����ƿ������^XQ^kn^RRPPNLFFJIA??@??HL\a�����v�����m[_n����e]��������������������go|��sWOR^j����ngZVOSYXTRVTMMTZ\YOOMU\lw����t_TV^uf_ip�����������������oyt��v�zt��dUTONWb��������v�����������������lWXOJJNNONPYccfWJGGKp������������xuwcYY[p����wc[`VOSSU[]\acee[^_\VXXW]_ik���������������������jj����dX]efi]SPQR\e`\ZZ_^YUPS[u������r^SROQVVXX]][[\nzkf[Z\]b`r����������������������������^XZ^bkolhn{�|eYWNEDEFJQ_Z[\p}���vh``_���������������}whq���������zg^USZh�����xn_RURQUW[jv��������ln����������������������yrn]VTUSROKLMNU]hpwg\\^ZZkv�t��o~ku�uz���ϯ���U4),O@��* ���������ȱ����Z6�������+���$5������%!����� 7�����m.'2��������f!D��������"@��������8-�����O$$Qâ���^:1,(9���K)9����8 `��R( *CB�����]!*E��������˪����0!(M���������/"*=�����V&%(+E��8,$")+'" %)3L����W! 2��������¼��x��N+%*;��������K.+4O�������Ȳ����������Ⱦ�����R-,<ʩ����o(4���[@;-+,&(*))5^�����:'# 'Wǹ�����HO�ʺ��������ý�������ű�������YE8:Zǽ�����]>:8?>1%! %*7A|���5&%,38>?NYD=<Q��QAH35Uƨ�����<42B���������O>98Jժ���������VJ8/:?SŶ����:=1,&(9J�ɿ���K?80,2GWZ8/5C��^g:.244>��Ž���n?JFCMZɼ������������?3-?嶫�������x[YaU����ODLS^UK>GZVA=L]�����?%+@�ӻ���M.+),=H[\�ν���D::EKH88?Kȯ�������922=λ����������bVt˽���@=@G���D=>a�Ϳ���eN<.&$&-:?Uo�̾��zSFFUzL:8>kȿ���vB=?9=cܼ��������[MYLIO^��ҹ������?/0:I̽���WC97>x��������bOE>4,)*8BT�n�»�E,&#).4CXZIHFGK��M������λ�������������������KBBM�����H825K������7,())*7;BB:-$"6������T;;=<760+%$)*8Z�������CF�մ���������ɽ��������������������̼����I/,*+.3CM��[>/+**/57>>92.035:>A</'!"-6dȽ���qgLCJZw̿�ʿ������������¯��������Ź��������I;:78=]�����nr��T>0,('$'+18DIR|G3'"!#'-:>KI=<If������VE=;?R��ÿ����ʾ���������������������������]JNX��ĺ����`<70069:<<APUKGA<6/.+*++/2:Cr��mA4//4<SYRI?>AADOo�þ����������������ķ�������������������������zG?<958DU���`D4.,-279::;??;941/1;943568>Vt��L><;>Nzʽ���������������������������ǿ���������^NLSTo�����{YMMRSH?;6788?HHDFB<7/-04<EYZ`m[WKEKKDDLVV]y���������������������������������������������������x[IC@AGS^t�]WZPNMFE@=;;<;??DKNHC>;8:=FKMXZj����xo��������������������ǻ������������������������gUUW[cz����iWB=98=DECBC<;@EACEEDDFFMMYmt}xufZXZ\TOZy������k���¿���������������XR_����������ys������zZ]acZPOHDA?DHQ]�Ŵ�L�OsX���x�.))'')3,(*23///Qʰ���Ϸ���������������TU�}����@62211666=N��º���������U@?>B�Ƶ��������d=<;80.7E_���V>81/339:BLf^Vl���������o_f�˻�������Ǿ������jXVb�������]M>=96;>EJUk�˿�������L?@XԾ�����m_^RD><AHLJEB?>BDA@=<<<AHU^��������ʿ���������������������^SNNU]lbef�zjp����lKEHOXl������v[GCFJZ����}_SMNWSUPNIHHMU^_USRTY���������eUQh��Ŀ������s[ju������xn}���}ie_NLLOSUdbgi_gv�������}]\t�������k\_^gh`RMFJKKOXw����YJJFGKJQR\b��������������������������������lPMNPY|�����o_VNEDIJes�cgo���lUSWZUONMWjq���fTQNNPOPOY[}����m�~���������������������������ZRTp�������^TNNMJLMl��������]KKJMYgv����pibYb�~r�����doz����yzys�gUOWa�����k]TWcjkj���������������������v�t�y}s�����]QMKKOv���n\W\ab�s�����ls��ffo���o��{_UMMXaZg�����ierg_VW_g���������iiimuuuoe][Zl��������_`fl����e^NMT]ecfk�tj[XR_{�d`don����|he^[\aejr�������\WOSMU]i������ukkccpup^ZVfs���������|����tdfjh�������}gZ_l������e^_d��������p]YXZjlx���}e[XY\XY^r����ww���ylijfppq����������������g][bu�������}����������l_[Zduz������lc^YTRORY_go�m_bi_dc\[VUY`~�ohfo���������nfgv�����������������kbdmc^f��������}kfdh������������odY\aj|������h[QNQX__``^cc]`m������f\XZ^n}�����uwx�z{}���������������������ld^^as��������mafx{���������������ullhghhge\ZTPOPOOOOPT\_j������komkfi����������}~���������zvzx}����������x�������}z~y�yxqymmop|��}vc_\`fikkc^YWWZbiln����nbcjlxx��|{zvhim�����������������������������������������������~oibabr������wf`YWUTY\ejcbceifcbbgmqsmt�����|{�{�������xpmo{��������������������������������wrsyrvowz}tomhf`]YXY\binjgc^[XY^bu������pjeekw��������~�|{tzurq}��������zvm{����������������������������lfijprqorulf\[YZ[]_cmrnmdeadeghnjpw��������������������������������ynnuz����snmnty��������������������yvqmhfdaa_bghllkiljefinw�{xtztoy{����������������������|�����������yzou�y������n�Y[Tgfy���՜����� ����� ���-*��� + +o�����!5�����������������ȿ�?!0!+A!"'$(7"#Ϣ�������������A,_Ϋ���������NR��3!6U�( #7Z6@�������ſ����������������������/*1>)"$*&$&%-::gϺ��������������������������I4%$&(#$%& (.?CE::�����������������������������VCA0,2451,-#% "&%)1*-=F��T=/3߲�������������������������d��eIJBA<//$" $"))-0+)!!.>;LBFWHV�������������������������zy�i=:/3+)7:<:?1313:49FUR=9:49G�ŷ�̼�����������kw��ɭ���W;.4I?GK��MND:3EA9]5G=7ceZUXH����g�ij�����������������W^WPCoI@4(3/.342/SQL\;807BV����B������������������������Ke_EHB�?8*!#,2/$-&(*,,+6<A52/7eź�����������������������������_VZ<1,,/023.,,-/,+'('&$#"%.>�ǹ������˯���������������������sP�X7CH:;>7-+&,'*,2<?;/0??DANx}������ƻ����λ�������D���]oa==AH�����];7//-1:Fb�}RGS������ɿ��������Ƽ���n����e^�\_O@A=>CIDE>1.,11C�`\OBDO]���������yj���������Ƽ�������WLXNK^OOIM?60,--4=KLNEIJLSNU]Qz���ɾ�����ÿþ������������oeO_NW]SRE;533266<IZ��MFDEJ?KORVQjLkú�������������nV�jx����dOHfPTXZC@;8JLNVZWHK@:Ie���eKLN�Ϳ��������ǿ���I<JQ��Ÿ��UDLEKO[B>=@TW`����}cHGFZ~���������������������Tb��_q�����b]MA@CEFBBEJKFKVQ|����YEPU�������Ⱥ������ghX�������VKHHDE?;24=BK��_>:>E���������������dXSf�ɴ���UJKR�ÿ��VQ��������SXSEE[l�l[KCEFOT_MNYY�}_�������{������������������}ok^����LGJHIBHTROan������[SVi\Xc������������\m������UOOKLRQLVZ[]c|ex�e[KGIG]m��������i]���o��k�������r�cMNdnabdvfg����u|n�c`^g^an��kbo}j�����x�����aXUZSX|�������uq����i]n�������eUo���h��������c^XKILU^afiPLDCN[�_RYj����������������������������``gh���t^aZXNTLGE>?EHV\f��~VROO]�lhu|�����������������������wm�`nq_g_\KKKDEHJEBDEQ_jmc^yt�������Ͽ������������������ceo�_MMKIGMMLIKKIMOSNLQZ_m��f�������������������ʹ�����������������������������"+��-*.+Jʦ���������������������/%+,*$#*4���( ('$ (9i���-($*=ENΧ�����������EBK9, &>������|nlѿ������������e�?<J˿��cO?:7;2/*($(7I��E3+(# '<�и����V;3)" ,/38I[`[\Y�Ƿ�����������������ò��������������������������;.*+-9O���T8,+,-0/-)##!#+1.&""')(*+*,+++,/>Kݻ�����������������������������������������n?9473553*#!&*+**,-.45504:>=>Guɽ������������������������������������������ebJNTWUMA846=FKLF=3-)'$$'),*,+)''*4?FI?HSi���������������������ſ����������Ƚ�����k_OJ>8>M]�dO@@C??FRVW^B:9:?IS_�_K;69=M\_�����OUMRY��������I=9<GMRY�v[Qn��t�cYOFIS��Ⱦ����������������������o]��bY\[SKI??GPOLGD?A?:5225876:??;;8317?NX\n�����˺�������������������������������������PC?>AAJKK?=968>>?@HM[dcgYH:97:@CW�����tj_^l^������������������������»���������;�����fH@@FMLKIDB??>AEXg{fp_QGCCKPSWSW^UI=99<Lb������eNMNck������_^bhf`_�vee^g��ɾ���������������mgl�����������������[MGIOOYqbb^^dWI?ACJNMMONMME@?<:6558>??H_���������������������������������������k]fmjZMIGGDDKNOYYb[Y[VVZOIHHKLGC@@FMPk�����NJGBCDJL]nfdb]W^WLLRZ���������¾�������ln�����nw~�c~������|gWOOR__YVXQLLE?BEJNYWTPLIJMN^akemo{������Ƽ�������hjwvk}|��jRNNONKKJKOQv��������������|o�����eVQOQ_t��������������_RNSSVTNJKMOQRUVSSORQUZfaWSOLMR_}�����������������������������������������fNJHHIKLLJFFFA@BHPX����aUUcf������������������j`ooihi~�����o_Yk�����������������p�������~icaWUX^ZZ^^ZYSNLMLHDFIKRU]^s����v�������������������k`[[q�������f]\Y[f��������������ye_ZZbiimifd^_]]a^YX[_mtg_]_q��������~sm{��������������lbimgd^]\]kmc[WSKILNOYbowqv�����������������������������������{qc\WQNOW[k}�~^TMIGGIKOSX^bffrv���m��������������������������z_^ZY\YVY^\bginj_YWZYYa^ji�oin\]XP�ngd[j����������������ƒ���7..rJ�{:ŗ������A:L:=��F*�������# +%���(2�����[ +[�����=,�������"������ 쐑�� ̔����R( #������N(1����F$6ī���,'-:L������-&*&,Ǩ����:A�������, (8J�>J�����/+- ,Xߪ����ƻ���R,!.�������5+������%!/E������<%&-I[?2/>W{�������$ �����������WU��9"&>������1"ޯ��P5+:m�������r:8O�ĸ���;+,?������m$)8������S74HL/#%=庿��������6))D��������S@FY����M?N]>../3EUrB60>_����J8?DBG\��̶����KIJN���J953<Fgҭ����>>/'(3E������i��Ź�dD-,1]������=#%8���b,##-��������a�\H:$%(-C֫����b;,&&<{�������MTI>Uľ�A5=Q�����Q5/5<ϳ�����t7268<D{�;��ȹ�����;)!#,=Ư�����A;58>AI{��~B>Iz���IMm��Y�mŲ���X5'*5V��������?376@Ln�ĺ����N4,;?KAD_�θ�������2+&)>W������nv[H?@@̷��J4/4A˵��s;4>H��ɺ���`3+(1=IYʿ������SHReJ3-/Eɯ����P84//:Iں�����EA:773/6L��ʵ����dE=+)8ؾ�����U>77?Lb�˿������];/$#->n������R=0.68@Ib��������a_�VH@9<Nɲ����J:;<Brf������K?BU����TG:7:Kĵ����R/,2>q�������.'%(5K϶�����MSJ>=?40/3E߷������N,&).=b������>48O|ž��E<Geoc�����T7/6?������V5/02?rǼ����w_IE>;I`n�t�ÿ�����O1)(-6cų�����T>505Bs��{Z^e������iQ<:Gw�����m;804;Eʽ����G<7558D|������ɿ��P>85/2<�˸�����=527?I����_AAS]ɻ����F?9<?Ea������nOW������qRKMOZk������������V@457:Fh������M6/.0:?am��������aSMBC@?FN����fF;<Hd�����_IKJb�����dcj������{VD96<U�������J;977BZƿ����zc_~�lYFA@>L�ƻ����Q?79?X��������dWJQx�m_U[Yo�����G?==JS�Ĺ�����E<9?E_�������i`e���TKQWjp������ZNJKW^l����iVMO`�����TQLFRm�����rH>>FP��������\Y[SMZ�����������_KKMOUdm�˿���]GBCQ[����������hTKDBFZ��������tZFCDIf��������oOLHHNVu�������x[MEFPn��������l\TX�����������n]XW_]b_m�������M@??CJb������dituj\ON^���������SMDBLg������_^UY\bw����zlj_Z]ahnw���]Wi�����sNR_����������������rXHDIRl�����q^SCCKVf����nw���tf\ZUYiy��������ePTUVay�����q�q\SZQMRYo������md^]SNs�������nT[_N^n��ܟ����� �����짶�>[!� +m�����&������������������ܬ��?:)K�! 'BE/7F+*���ղ������^43CXױ�������S*'G�F+8BAʼ�^!'' 2иж�������������������������������~=��<3&( #,(%),2>պ�������������������������JMU����pJ>;><50+-)%+&1C}ƻ��|��Ȳ���������������������p�N�L=30401.(& #5>8?A98>ݫ�����������������������������m�QOaRn60('""%().+(#'3CFK=6:48H亭���ȿ������������g�L79=9?62'%""-76.3*/-0A;Naȿ���������������������������������lBET;;:<3-.-'!&#$.(+)'+(++++=OMQI?>JX]���������ź����]Z[IK��bK3LIDMG;8��ɺooF�\��Ŀ�ɮ���������������������Ľ�}=?@5AQC//()&##)+,6;?F;4=K�϶�������������������������ſ�SVlC85=G<:1./2/53//08:20,/;o�Ĺ�����ϼ���������������ȸ��dhOA:I?/41(,,-+,,61;9>FD:4:�fis��ź��������������������Xʽ����X?::HFQNG799083=:JLPG:69@LLOJ>AOWGF[Lr�����~fQG}Կ����������������cR�ھ������������ο��XMAf���¿���OqSOWYc�dbSMH<A7:AD9:2.02C]��RGFAJTZ��q��������������̼�������������W�g����ID><<@FO�����ZLGCMSk���_cHM��Ŀ������Zi�m�hUq`\�xO@=;:KFNGH>845<CMPO><<8:DVm���g��Ļ�����������»�������Ž��o]�z���hQECWM[QVPKMJ@D?BW~���f_ORaTunVUPOb����X]i�rbh����v~ZKORLLGIMOWMMWb�����oS��Ǿ�����ü���������������R@=<>E^L?:8>CDa�I=8>J����oMKOf|�ih��\PNZfڿ���Zam�Ƽ���g\�����������TJcm�rVUMHLVVVMNgs��t����������������������������jal�{dI>@CIELXQEEGBKIKJGGKY���n|������������ͽ�����o������������������eSZSdg���_TXYhVPY^V[ql]^�����YQWPKITYQX\�rff��^Y\cye^ee_o���yhv�������g�������}���������������������������^S����nrk`hh�fUKLNJNOV[Z\UHHC@JZ�XOY\u�������tir������������������������j`lYXNHHJNJObd|�����b[X^�����������������~����������od__TTNOPROFHJGHOWNKKFMY[\Y]����������������������������v]^n��]XSNQUZ\SQPMMLMNNSlvz�iQYTg����������������h^Y^{����ggnf_`�d����B9>[Q�S<(!#%���������������i&%%&/�������) $2:ϭ�6"*4ǭ����2'/�����}-#-2ί������9&&+:[�����@%%'>����E().9�������?$!%,A˭�����90O����M3#%-.Dϴ�������]ٳ����I95)*4������I:8<վ��\9,/7>hQȲ���P,+,,3P˺�����zeָ���<./:V��������.&(4v����Y:.066L�����]J=9;Dh��[GMV{߹�����C0$&6M�����������bT_vV9/0>V¹����M=/,.5aƼ��VBK�ñ������w|���ø���C@Wθ�����Q:.,,-9V������WJOB529IMF@G���F;7<��Ŀ����OMNXg����p�~_LHJMNSULDEW�����]HIFCJf��ɾ���������vLB?BKY��ĺ���K<:68>DLXg\m�aOFNVkWGI<:B^½���[B9:Jy��������SIA?FVƾ��������^LE<AIU������OVKA;;IZ��������mWNY���fV`������UWbn�������oUADGAACP_f�h��������eD:6>Hl̾������]TT_c����������������g��Ǿ����?866C]�������H>;<HJZ^������K@@IUXHDMZ�ƺ�����xC>=Dl����������oWSU����nLHIR���s^Wl���������SC>>HY^���¼����OQ_�kNJKe�����xVMJA@KT��þ��~XO@???BIc���������|XBAN]�����lYMGNYat��������ZK?:68Kd��������TLGOQ]h������������zXJEKV������WMIGIMN\�����VOV^inpaRNKIT�������iLEOp�������[>::=Nn�»���xrh[ONI?::ANz������jN;9=BO�������LGKV�����kbw��t�����}NJUe������MDBDJU�������aVNRON[cjll��������YC<;<I^�ƿ����[MDCEKT_f^��������b\LHHT������XGDEMXi������o\VNKNa�����������_MHFDIU���Ŀ���XJBCGL_����{��������YLKIPh������kUONWs�������]ZTUY`v����������\NFGKQl�������ZK@?FXh����������^WNJNO_{�������]KGIWl���u_]XWU[]ajhfq������{xi_QLLOo�������zXUMKS^������������[TSRO\�������XHBDM^��������~gYZtxgm���������YSMNZi�������lTNJKOXo��������lneYLKO\}�������i]XUZ\s��������olked^]jt~������nXJGIM[p������hVWROQ_����������m_VV[av��������]ROR\f�������lc_\\][cq��������wd]XZ`l��������qnbddgou���������o[UXf���������k_Y[hk��{������o^iachw�������pmhfghmx�������ukihimnv��������oifglp~�������~ukhilw���������~xtont}������ \ No newline at end of file diff --git a/setavatardialog.cpp b/setavatardialog.cpp new file mode 100644 index 0000000..2d0d387 --- /dev/null +++ b/setavatardialog.cpp @@ -0,0 +1,224 @@ +/************************************************************************** +* Copyright (C) 2018 by Savoir-faire Linux * +* Author: Isa Nanic <isa.nanic@savoirfairelinux.com> * +* * +* This program is free software; you can redistribute it and/or modify * +* it under the terms of the GNU General Public License as published by * +* the Free Software Foundation; either version 3 of the License, or * +* (at your option) any later version. * +* * +* This program is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU General Public License for more details. * +* * +* You should have received a copy of the GNU General Public License * +* along with this program. If not, see <https://www.gnu.org/licenses/>. * +**************************************************************************/ + +#include <QtMultimedia\QCameraInfo> +#include <QFileDialog> +#include <QAbstractScrollArea> +#include <QScreen> +#include <QWindow> +#include <QtMultimedia\QCameraImageCapture> +#include <QBuffer> + +#include "setavatardialog.h" +#include "ui_setavatardialog.h" + +#include "lrcinstance.h" +#include "accountlistmodel.h" +#include "currentaccountcombobox.h" + +SetAvatarDialog::SetAvatarDialog(QWidget* parent) + : QDialog(parent), + ui(new Ui::SetAvatarDialog), + videoWidget_(new QCameraViewfinder(this)), + camera_(new QCamera) +{ + ui->setupUi(this); + + connect(ui->cancelButton, &QPushButton::clicked, [&]() { + done(0); + } + ); + + connect(ui->saveButton, &QPushButton::clicked, this, &SetAvatarDialog::saveAvatar); + + connect(ui->selectFileButton, &QPushButton::clicked, this, &SetAvatarDialog::openFileManager); + + connect(ui->takePictureButton, &QPushButton::clicked, this, &SetAvatarDialog::captureImage); + + connect(ui->cameraButton, &QPushButton::clicked, this, &SetAvatarDialog::pictureMode); + + ui->graphicsView->setAvatarSize(avatarSize_); + + videoWidget_->setGeometry(ui->graphicsView->x(), ui->graphicsView->y(), + ui->graphicsView->width(), ui->graphicsView->height()); + + pictureMode(); + startCamera(); + + ui->horizontalLayout_2->update(); +} + +SetAvatarDialog::~SetAvatarDialog() +{ + disconnect(this); + delete mediaPlayer_; + delete videoWidget_; + delete imageCapture_; + delete camera_; + delete ui; +} + +void +SetAvatarDialog::startCamera() +{ + imageCapture_ = new QCameraImageCapture(camera_, this); + camera_->setCaptureMode(QCamera::CaptureViewfinder); + connect(imageCapture_, SIGNAL(imageSaved(int, const QString&)), + this, SLOT(imageCaptureSlot(int, const QString&))); +} + +bool +SetAvatarDialog::checkCamAvailable() +{ + if (QCameraInfo::availableCameras().count() > 0) { + return true; + } + else { + return false; + } +} + +// no support yet for back-facing camera [todo]; no support for portrait mode [todo] +void +SetAvatarDialog::pictureMode() +{ + if (checkCamAvailable()) { + camera_ = new QCamera(QCamera::FrontFace); + camera_->setViewfinder(videoWidget_); + + ui->graphicsView->hide(); + videoWidget_->show(); + + camera_->start(); + + ui->saveButton->hide(); + ui->cameraButton->hide(); + + ui->takePictureButton->show(); + ui->selectFileButton->show(); + } + else { + openFileManager(); // no camera detected so open file manager + } +} + +void +SetAvatarDialog::editMode() +{ + camera_->unlock(); + camera_->stop(); + + ui->takePictureButton->hide(); + + ui->saveButton->show(); + ui->cameraButton->show(); + ui->selectFileButton->show(); + + videoWidget_->hide(); + ui->graphicsView->show(); + configureAvatarScene(rawPixmap_); +} + +void +SetAvatarDialog::openFileManager() +{ + rawPixmap_.load(QFileDialog::getOpenFileName(this, + tr("Open Image"), "", tr("Image Files (*.png *.jpg *.bmp)"))); + editMode(); +} + +void +SetAvatarDialog::configureAvatarScene(const QPixmap& pixMap) +{ + if (!pixMap.isNull()) { + const int margin = 8; + QPen pen; + pen.setStyle(Qt::NoPen); + + graphicsScene_.clear(); + + graphicsScene_.addPixmap(pixMap); + graphicsScene_.addRect(-(pixMap.width()*margin - avatarSize_) / 2, + -(pixMap.height() * margin - avatarSize_) / 2, pixMap.width() * margin, pixMap.height() * margin, pen, QBrush()); + ui->graphicsView->setScene(&graphicsScene_); + } +} + +void +SetAvatarDialog::captureImage() +{ + startCamera(); + + camera_->setCaptureMode(QCamera::CaptureStillImage); + imageCapture_->setCaptureDestination(QCameraImageCapture::CaptureToFile); + + if (imageCapture_->isCaptureDestinationSupported(QCameraImageCapture::CaptureToFile)) { + camera_->searchAndLock(); + camera_->start(); + imageCapture_->capture(); + } +} + +// save avatar image and exit SetAvatarDialog +void +SetAvatarDialog::saveAvatar() +{ + avatarSize_ *= 2; + + QRect avatarRect((ui->graphicsView->width() - avatarSize_)/2 + ui->graphicsView->x(), (ui->graphicsView->height() - avatarSize_)/2 + ui->graphicsView->y(), + avatarSize_, avatarSize_); + + QRegion avatarRegion(avatarRect.x() - ui->graphicsView->x(), avatarRect.y() - ui->graphicsView->y(), + avatarSize_, avatarSize_, QRegion::Ellipse); + ui->graphicsView->setMask(avatarRegion); + + finalAvatarPixmap_ = grab(avatarRect); + + done(0); +} + +void +SetAvatarDialog::done(int exCode) +{ + QDialog::done(exCode); + if (!finalAvatarPixmap_.isNull()) { + QByteArray ba; + QBuffer bu(&ba); + finalAvatarPixmap_.save(&bu, "PNG"); + emit pixmapSignal(ba.toBase64().toStdString()); + } + else { + emit pixmapSignal(std::string()); + } + camera_->unlock(); + camera_->stop(); +} + +void +SetAvatarDialog::imageCaptureSlot(int useless, const QString& text) +{ + Q_UNUSED(useless); + + rawPixmap_ = rawPixmap_.fromImage(QImage(text)); + + if (!rawPixmap_.isNull()){ + editMode(); + } + QFile file(text); + file.remove(); // erase file +} diff --git a/setavatardialog.h b/setavatardialog.h new file mode 100644 index 0000000..97780b0 --- /dev/null +++ b/setavatardialog.h @@ -0,0 +1,82 @@ +/************************************************************************** +* Copyright (C) 2018 by Savoir-faire Linux * +* Author: Isa Nanic <isa.nanic@savoirfairelinux.com> * +* * +* This program is free software; you can redistribute it and/or modify * +* it under the terms of the GNU General Public License as published by * +* the Free Software Foundation; either version 3 of the License, or * +* (at your option) any later version. * +* * +* This program is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU General Public License for more details. * +* * +* You should have received a copy of the GNU General Public License * +* along with this program. If not, see <https://www.gnu.org/licenses/>. * +**************************************************************************/ + +#pragma once + +#include <QPushButton> + +#include <QAction> +#include <QDialog> +#include <QRegion> +#include <QtMultimedia\QCamera> +#include <QGraphicsScene> +#include <QtMultimedia\QMediaPlayer> +#include <QtMultimedia\QCameraImageCapture> +#include <QtMultimediaWidgets\QCameraViewfinder> +#include <QtMultimedia\QCameraImageCapture> + + +#include "accountlistmodel.h" +#include "avatargraphicsview.h" +#include "settingswidget.h" + +namespace Ui { + class SetAvatarDialog; +} + +class SetAvatarDialog : public QDialog +{ + Q_OBJECT + SetAvatarDialog(const SetAvatarDialog& cpy); + +public: + SetAvatarDialog(QWidget* parent = nullptr); + ~SetAvatarDialog(); + +signals: + void pixmapSignal(const std::string& avatarInBase64String); + +private slots: + void done(int exCode); + void imageCaptureSlot(int useless, const QString& text); + void pictureMode(); + void captureImage(); + void openFileManager(); + void saveAvatar(); + +private: + Ui::SetAvatarDialog* ui; + void startCamera(); + + void configureAvatarScene(const QPixmap& pixMap); + void editMode(); + + bool checkCamAvailable(); + + int avatarSize_ = 130; + + QMediaPlayer* mediaPlayer_; + + QCameraViewfinder* videoWidget_; + QCameraImageCapture* imageCapture_; + QCamera* camera_; + QGraphicsScene graphicsScene_; + + QPixmap rawPixmap_; + QPixmap finalAvatarPixmap_; +}; \ No newline at end of file diff --git a/setavatardialog.ui b/setavatardialog.ui new file mode 100644 index 0000000..b91ca9c --- /dev/null +++ b/setavatardialog.ui @@ -0,0 +1,226 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>SetAvatarDialog</class> + <widget class="QDialog" name="SetAvatarDialog"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>530</width> + <height>373</height> + </rect> + </property> + <property name="minimumSize"> + <size> + <width>530</width> + <height>373</height> + </size> + </property> + <property name="maximumSize"> + <size> + <width>530</width> + <height>373</height> + </size> + </property> + <property name="baseSize"> + <size> + <width>800</width> + <height>590</height> + </size> + </property> + <property name="windowTitle"> + <string>Change Your Avatar Image</string> + </property> + <property name="styleSheet"> + <string notr="true">background: white;</string> + </property> + <layout class="QVBoxLayout" name="verticalLayout"> + <item> + <layout class="QVBoxLayout" name="verticalLayout_2"> + <item> + <layout class="QHBoxLayout" name="horizontalLayout_2" stretch="1,0,1"> + <item> + <spacer name="horizontalSpacer"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>40</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + <item> + <widget class="AvatarGraphicsView" name="graphicsView" native="true"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Fixed" vsizetype="Fixed"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="minimumSize"> + <size> + <width>500</width> + <height>300</height> + </size> + </property> + <property name="maximumSize"> + <size> + <width>16777215</width> + <height>16777215</height> + </size> + </property> + <property name="cursor"> + <cursorShape>CrossCursor</cursorShape> + </property> + <property name="mouseTracking"> + <bool>true</bool> + </property> + <property name="styleSheet"> + <string notr="true"/> + </property> + </widget> + </item> + <item> + <spacer name="horizontalSpacer_2"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>40</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + </layout> + </item> + <item> + <spacer name="verticalSpacer"> + <property name="orientation"> + <enum>Qt::Vertical</enum> + </property> + <property name="sizeType"> + <enum>QSizePolicy::MinimumExpanding</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>20</width> + <height>5</height> + </size> + </property> + </spacer> + </item> + <item> + <layout class="QHBoxLayout" name="horizontalLayout"> + <property name="spacing"> + <number>10</number> + </property> + <item> + <widget class="QPushButton" name="saveButton"> + <property name="minimumSize"> + <size> + <width>80</width> + <height>30</height> + </size> + </property> + <property name="styleSheet"> + <string notr="true">background: rgb(245, 245, 245); border: 0px; border-radius: 3px;</string> + </property> + <property name="text"> + <string>Save</string> + </property> + <property name="flat"> + <bool>false</bool> + </property> + </widget> + </item> + <item> + <widget class="QPushButton" name="takePictureButton"> + <property name="minimumSize"> + <size> + <width>80</width> + <height>30</height> + </size> + </property> + <property name="styleSheet"> + <string notr="true">background: rgb(245, 245, 245); border: 0px; border-radius: 3px;</string> + </property> + <property name="text"> + <string>Take Picture</string> + </property> + </widget> + </item> + <item> + <widget class="QPushButton" name="cameraButton"> + <property name="minimumSize"> + <size> + <width>80</width> + <height>30</height> + </size> + </property> + <property name="styleSheet"> + <string notr="true">background: rgb(245, 245, 245); border: 0px; border-radius: 3px;</string> + </property> + <property name="text"> + <string>Camera</string> + </property> + </widget> + </item> + <item> + <widget class="QPushButton" name="selectFileButton"> + <property name="minimumSize"> + <size> + <width>80</width> + <height>30</height> + </size> + </property> + <property name="styleSheet"> + <string notr="true">background: rgb(245, 245, 245); border: 0px; border-radius: 3px;</string> + </property> + <property name="text"> + <string>Select A File</string> + </property> + <property name="flat"> + <bool>false</bool> + </property> + </widget> + </item> + <item> + <widget class="QPushButton" name="cancelButton"> + <property name="minimumSize"> + <size> + <width>80</width> + <height>30</height> + </size> + </property> + <property name="styleSheet"> + <string notr="true">background: rgb(245, 245, 245); border: 0px; border-radius: 3px;</string> + </property> + <property name="text"> + <string>Cancel</string> + </property> + <property name="flat"> + <bool>false</bool> + </property> + </widget> + </item> + </layout> + </item> + </layout> + </item> + </layout> + </widget> + <customwidgets> + <customwidget> + <class>AvatarGraphicsView</class> + <extends>QWidget</extends> + <header>avatargraphicsview.h</header> + </customwidget> + </customwidgets> + <resources/> + <connections/> +</ui> diff --git a/settingsitemwidget.cpp b/settingsitemwidget.cpp new file mode 100644 index 0000000..dfee4f4 --- /dev/null +++ b/settingsitemwidget.cpp @@ -0,0 +1,134 @@ +/**************************************************************************** + * Copyright (C) 2018 Savoir-faire Linux * + * Author: Isa Nanic <isa.nanic@savoirfairelinux.com> * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Lesser General Public * + * License as published by the Free Software Foundation; either * + * version 2.1 of the License, or (at your option) any later version. * + * * + * This library is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program. If not, see <https://www.gnu.org/licenses/>. * + ***************************************************************************/ + +#include "settingsitemwidget.h" + +#include "lrcinstance.h" +#include "api/newdevicemodel.h" +#include "ringthemeutils.h" + + +SettingsItemWidget::SettingsItemWidget(int height, int index, bool banned, QListWidget* parent) + : QListWidgetItem(parent), + banned_(banned), + index_(index), + height_(height), + nameEdit_(new QLineEdit(parent)), + idlabel_(new QLabel(parent)), + button_(new QPushButton(parent)) +{ + setFlags(Qt::NoItemFlags); + // for all items: + button_->setGeometry(parent->width() - 50, verMargin_ + height_ * index_, 30, 36); + nameEdit_->setStyleSheet("border: 0px; border-radius: 3px; background: transparent;"); + idlabel_->setStyleSheet("border: 0px; border-radius: 3px; background: transparent;"); + button_->setStyleSheet("border: 0px; border-radius: 3px; background: transparent;"); + button_->setIconSize(QSize(22, 22)); + + nameEdit_->setGeometry(horMargin_, verMargin_ + height_ * index_, 300, 22); + nameEdit_->setReadOnly(true); + + idlabel_->setGeometry(horMargin_, verMargin_ + 20 + height_ * index_, 400, 22); + idlabel_->setTextInteractionFlags(Qt::NoTextInteraction); + + // end all items + + if (index_ % 2) { + setBackgroundColor(Qt::white); + } + else { + setBackgroundColor(RingTheme::smartlistHighlight_); + } + + if (!banned_) { // populate the device list + auto deviceList = LRCInstance::getCurrentAccountInfo().deviceModel->getAllDevices(); + auto it = deviceList.begin(); + std::advance(it, index_); + + nameEdit_->setText(QString::fromStdString(it->name)); + idlabel_->setText(QString::fromStdString(it->id)); + + if (!index_) { + button_->setIcon(QPixmap(":/images/icons/round-edit-24px.svg")); + button_->setToolTip(QObject::tr("Edit Device Name")); + + QObject::connect(button_, &QPushButton::pressed, [this]() { toggleEditable(); }); + } + else { + button_->setIcon(QPixmap(":/images/icons/round-remove_circle-24px.svg")); + button_->setToolTip(QObject::tr("Unlink Device From Account")); + } + nameEdit_->show(); + idlabel_->show(); + button_->show(); + } + else { // populate the banned contacts list + auto bannedContactList = LRCInstance::getCurrentAccountInfo().contactModel->getBannedContacts(); + auto it = bannedContactList.begin(); + std::advance(it, index_); + + auto contactInfo = LRCInstance::getCurrentAccountInfo().contactModel->getContact(*it); + + nameEdit_->setText(QString::fromStdString(contactInfo.registeredName)); + idlabel_->setText(QString::fromStdString(contactInfo.profileInfo.uri)); + button_->setIcon(QPixmap(":/images/icons/round-undo-24px.svg")); + button_->setToolTip(QObject::tr("Unblock Contact")); + + nameEdit_->show(); + idlabel_->show(); + button_->show(); + } + + QObject::connect(nameEdit_, &QLineEdit::editingFinished, [this]() { finishEdit(); }); +} + +SettingsItemWidget::~SettingsItemWidget() +{ + delete nameEdit_; + delete idlabel_; + delete button_; +} + +void +SettingsItemWidget::toggleEditable() +{ + if (!editable_) { + nameEdit_->setReadOnly(false); + nameEdit_->setStyleSheet("border: 0px; border-radius: 3px; background: white;"); + nameEdit_->setFocus(); + button_->setIcon(QPixmap(":/images/icons/round-save_alt-24px.svg")); + } + else { + finishEdit(); + } + editable_ =! editable_; +} + +void +SettingsItemWidget::finishEdit() +{ + if (!index_) { + nameEdit_->setReadOnly(true); + nameEdit_->setStyleSheet("border: 0px; border-radius: 3px; background: transparent;"); + button_->setIcon(QPixmap(":/images/icons/round-edit-24px.svg")); + + auto confProps = LRCInstance::accountModel().getAccountConfig(LRCInstance::getCurrAccId()); + confProps.deviceName = nameEdit_->text().toStdString(); + LRCInstance::editableAccountModel()->setAccountConfig(LRCInstance::getCurrAccId(), confProps); + } +} diff --git a/settingsitemwidget.h b/settingsitemwidget.h new file mode 100644 index 0000000..44c4d9d --- /dev/null +++ b/settingsitemwidget.h @@ -0,0 +1,50 @@ +/**************************************************************************** + * Copyright (C) 2018 Savoir-faire Linux * + * Author: Isa Nanic <isa.nanic@savoirfairelinux.com> * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Lesser General Public * + * License as published by the Free Software Foundation; either * + * version 2.1 of the License, or (at your option) any later version. * + * * + * This library is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program. If not, see <http://www.gnu.org/licenses/>. * + ***************************************************************************/ +#include <QListWidgetItem> +#include <QLineEdit> +#include <QLabel> +#include <QPushButton> + + + +class SettingsItemWidget : public QListWidgetItem +{ +public: + SettingsItemWidget(int height, int index, bool banned, QListWidget* parent = nullptr); + ~SettingsItemWidget(); + + QPushButton* button_; + +private: + bool selected_ = false; + bool banned_ = false; + const int index_; + const int height_; + + const int horMargin_ = 15; + const int verMargin_ = 8; + + QLineEdit* nameEdit_; + QLabel* idlabel_; + + void toggleEditable(); + void finishEdit(); + + bool editable_ = false; +}; + diff --git a/settingswidget.cpp b/settingswidget.cpp new file mode 100644 index 0000000..e372699 --- /dev/null +++ b/settingswidget.cpp @@ -0,0 +1,926 @@ +/*************************************************************************** + * Copyright (C) 2018 by Savoir-faire Linux * + * Author: Isa Nanic <isa.nanic@savoirfairelinux.com> * + * Author: Edric Ladent Milaret <edric.ladent-milaret@savoirfairelinux.com>* + * Author: Anthony L�onard <anthony.leonard@savoirfairelinux.com> * + * Author: Olivier Soldano <olivier.soldano@savoirfairelinux.com> * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 3 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program. If not, see <https://www.gnu.org/licenses/>. * + **************************************************************************/ +#include <QPixmap> +#include <QTimer> +#include <QModelIndex> +#include <QFileDialog> +#include <QInputDialog> +#include <QStandardPaths> +#include <QMessageBox> + +// account settings +#include "api/newdevicemodel.h" +#include "settingsitemwidget.h" + +#include "settingswidget.h" +#include "ui_settingswidget.h" + +#include "ui_advancedsettingswidget.h" + +#include "passworddialog.h" + +#include "regnamedialog.h" +#include "ui_regnamedialog.h" + +#include "setavatardialog.h" +#include "ui_setavatardialog.h" + +#include "deleteaccountdialog.h" +#include "ui_deleteaccountdialog.h" + + +// general Settings +#include "winsparkle.h" +#include "media/recordingmodel.h" + +// av setttings +#include "audio/settings.h" +#include "audio/outputdevicemodel.h" +#include "audio/inputdevicemodel.h" + +#include "video/devicemodel.h" +#include "video/channel.h" +#include "video/resolution.h" +#include "video/rate.h" +#include "video/previewmanager.h" + +#include "callmodel.h" + + + + +SettingsWidget::SettingsWidget(QWidget* parent) + : NavWidget(parent), + ui(new Ui::SettingsWidget), + scrollArea_(new QScrollArea), + deviceModel_(&Video::DeviceModel::instance()), + gif(new QMovie(":/images/ajax-loader.gif")) +{ + ui->setupUi(this); + + ui->accountSettingsButton->setAutoFillBackground(true); + ui->generalSettingsButton->setAutoFillBackground(true); + ui->avSettingsButton->setAutoFillBackground(true); + + ui->accountSettingsButton->setChecked(true); + + ui->exitSettingsButton->setIconSize(QSize(24, 24)); + ui->exitSettingsButton->setIcon(QPixmap(":/images/icons/round-close-24px.svg")); + + + // display name (aka alias) + ui->displayNameLineEdit->setAlignment(Qt::AlignHCenter); + ui->displayNameLineEdit->setPlaceholderText(tr("Enter the displayed name")); + + + setSelected(Button::accountSettingsButton); + + ui->currentRegisteredID->setReadOnly(true); + ui->currentRegisteredID->setStyleSheet("border : 0px;"); + + ui->currentRingID->setReadOnly(true); + + avatarSize_ = ui->currentAccountAvatar->width(); + + ui->currentAccountAvatar->setIconSize(QSize(avatarSize_, avatarSize_)); + + // create ellipse-selectable avatar image + QRegion avatarClickableRegion(-1, -1, + ui->currentAccountAvatar->width() + 2, ui->currentAccountAvatar->height() + 2, QRegion::Ellipse); + ui->currentAccountAvatar->setMask(avatarClickableRegion); + + QString styleS( + "QPushButton{" + " background-color: rgb(245, 245, 245);" + " border: 0px;" + "}" + " QPushButton:hover{" + " background-color: rgb(250, 250, 250);" + " border: 0px;" + " }" + + "QPushButton:checked{" + " background-color: white;" + " border: 0px;" + "}" + ); + + ui->accountSettingsButton->setStyleSheet(styleS); + ui->generalSettingsButton->setStyleSheet(styleS); + ui->avSettingsButton->setStyleSheet(styleS); + + ui->advancedAccountSettingsPButton->setIcon(QPixmap(":/images/icons/round-arrow_drop_down-24px.svg")); + ui->linkDevPushButton->setIcon(QPixmap(":/images/icons/round-add-24px.svg")); + ui->blockedContactsBtn->setIcon(QPixmap(":/images/icons/round-arrow_drop_up-24px.svg")); + + ui->advancedSettingsOffsetLabel->show(); + + setConnections(); +} + +void +SettingsWidget::leaveSettingsSlot() +{ + emit NavigationRequested(ScreenEnum::CallScreen); + if (advancedSettingsDropped_) { + toggleAdvancedSettings(); + } + + if (avSettingsHaveAppeared) { + ui->videoWidget->previewStopped(); + ui->videoWidget->renderingStopped(); + avSettingsHaveAppeared = false; + } +} + +SettingsWidget::~SettingsWidget() +{ + delete advancedSettingsWidget_; + delete scrollArea_; + delete ui; +} + +// called at every callwidget -> settingsWidget navigation +void +SettingsWidget::updateSettings(int size) +{ + setSelected(Button::accountSettingsButton); + resize(size); + updateAccountInfoDisplayed(); +} + +void +SettingsWidget::resize(int size) +{ + ui->rightSettingsWidget->setGeometry(size, 0, this->width() - size, this->height()); + ui->accountSettingsButton->setFixedWidth(size); +} + +void +SettingsWidget::setSelected(Button sel) +{ + switch (sel) + { + case Button::accountSettingsButton: + if (advancedSettingsDropped_) { toggleAdvancedSettings(); } + + ui->stackedWidget->setCurrentWidget(ui->currentAccountSettingsScrollWidget); + if (pastButton_ == Button::generalSettingsButton) { + ui->accountSettingsButton->setChecked(true); + ui->generalSettingsButton->setChecked(false); + break; + } + else { + ui->accountSettingsButton->setChecked(true); + ui->avSettingsButton->setChecked(false); + break; + } + case Button::generalSettingsButton: + ui->stackedWidget->setCurrentWidget(ui->generalSettings); + populateGeneralSettings(); + if (pastButton_ == Button::avSettingsButton) { + ui->generalSettingsButton->setChecked(true); + ui->avSettingsButton->setChecked(false); + break; + } + else { + ui->generalSettingsButton->setChecked(true); + ui->accountSettingsButton->setChecked(false); + break; + } + case Button::avSettingsButton: + ui->stackedWidget->setCurrentWidget(ui->avSettings); + if (!avSettingsHaveAppeared) { populateAVSettings(); } + if (pastButton_ == Button::accountSettingsButton) { + ui->avSettingsButton->setChecked(true); + ui->accountSettingsButton->setChecked(false); + break; + } + else { + ui->avSettingsButton->setChecked(true); + ui->generalSettingsButton->setChecked(false); + break; + } + } + pastButton_ = sel; +} + +// called to update current settings information when navigating to settingsWidget +void +SettingsWidget::updateAccountInfoDisplayed() +{ + ui->currentRegisteredID->setText(QString::fromStdString(LRCInstance::getCurrentAccountInfo().registeredName)); + ui->currentRingID->setText(QString::fromStdString(LRCInstance::getCurrentAccountInfo().profileInfo.uri)); + + ui->currentRegisteredID->setReadOnly(true); + +// if no registered name is found for account + if (LRCInstance::getCurrentAccountInfo().registeredName.empty()) { + ui->currentRegisteredID->setReadOnly(false); + } + else { + ui->currentRegisteredID->setReadOnly(true); + setRegNameUi(RegName::BLANK); + } + + ui->currentAccountAvatar->setIcon(LRCInstance::getCurrAccPixmap(). + scaledToHeight(avatarSize_, Qt::SmoothTransformation)); + + ui->accountEnableCheckBox->setChecked(LRCInstance::getCurrentAccountInfo().enabled); + + ui->displayNameLineEdit->setText(QString::fromStdString(LRCInstance::getCurrentAccountInfo().profileInfo.alias)); + + updateAndShowDevicesSlot(); + if (!LRCInstance::getCurrentAccountInfo().contactModel->getBannedContacts().size()){ + ui->blockedContactsBtn->hide(); + } else { + ui->blockedContactsBtn->show(); + } + bannedContactsShown_ = false; +} + +void +SettingsWidget::passwordClicked() +{ + PasswordDialog passwdDialog(this); + passwdDialog.exec(); +} + +void +SettingsWidget::toggleAdvancedSettings() +{ + if (advancedSettingsDropped_) { + ui->advancedAccountSettingsPButton->setIcon(QPixmap(":/images/icons/round-arrow_drop_down-24px.svg")); + ui->currentAccountSettingsScrollLayout->removeWidget(advancedSettingsWidget_); + ui->scrollBarLabel->show(); + ui->advancedSettingsOffsetLabel->hide(); + delete advancedSettingsWidget_; + } + else { // will show advanced settings next + ui->advancedAccountSettingsPButton->setIcon(QPixmap(":/images/icons/round-arrow_drop_up-24px.svg")); + advancedSettingsWidget_ = new AdvancedSettingsWidget(ui->scrollAreaWidgetContents); + advancedSettingsWidget_->setMaximumWidth(ui->scrollAreaWidgetContents->width() - 10); + ui->currentAccountSettingsScrollLayout->addWidget(advancedSettingsWidget_); + ui->advancedSettingsOffsetLabel->show(); + ui->scrollBarLabel->hide(); + } + advancedSettingsDropped_ = !advancedSettingsDropped_; +} + +void +SettingsWidget::toggleBannedContacts() +{ + if (bannedContactsShown_) { // will show linked devices next + updateAndShowDevicesSlot(); + } + else { // will show banned contacts next + updateAndShowBannedContactsSlot(); + } +} + +void +SettingsWidget::resizeEvent(QResizeEvent* event) +{ + QWidget::resizeEvent(event); + scrollArea_->resize(ui->currentAccountSettingsScrollWidget->width(), this->height()); +} + +void +SettingsWidget::avatarClicked() +{ + SetAvatarDialog avatarDialog(this); + + // return new avatar pixmap from setAvatarDialog + connect(&avatarDialog, &SetAvatarDialog::pixmapSignal, [&](const std::string& pixString) { + if (!pixString.empty()) { + LRCInstance::setCurrAccAvatar(pixString); + updateAccountInfoDisplayed(); + } + } + ); + avatarDialog.exec(); +} + +void +SettingsWidget::verifyRegisteredNameSlot() +{ + if (!LRCInstance::getCurrentAccountInfo().registeredName.empty()) { + setRegNameUi(RegName::BLANK); + } + else { + registeredName_ = ui->currentRegisteredID->text().simplified(); + + if (!registeredName_.isEmpty()) { + if (validateRegNameForm(registeredName_)) { // name has valid form + setRegNameUi(RegName::SEARCHING); + QTimer::singleShot(300, this, SLOT(beforeNameLookup())); + } else { // name does not have valid form + setRegNameUi(RegName::INVALIDFORM); + } + } else { + setRegNameUi(RegName::BLANK); + } + } +} + +// returns true if name is valid registered name +bool +SettingsWidget::validateRegNameForm(const QString& regName) +{ + QRegularExpression regExp(" "); + if (regName.size() > 2 && !regName.contains(regExp)) { + return true; + } + else { + return false; + } +} + +void +SettingsWidget::receiveRegNameSlot(const std::string& accountID, + lrc::api::account::LookupStatus status, const std::string& address, const std::string& name) +{ + Q_UNUSED(accountID); Q_UNUSED(address); + afterNameLookup(status, name); +} + +void +SettingsWidget::beforeNameLookup() +{ + NameDirectory::instance().lookupName(nullptr, QString(), registeredName_); +} + +void +SettingsWidget::afterNameLookup(lrc::api::account::LookupStatus status, const std::string& regName) +{ + if (registeredName_.toStdString() == regName && regName.length() > 2) { + if (status == lrc::api::account::LookupStatus::NOT_FOUND) { + setRegNameUi(RegName::FREE); + } + else { + setRegNameUi(RegName::TAKEN); + } + } + else { + setRegNameUi(RegName::BLANK); + } +} + +void SettingsWidget::setRegNameUi(RegName stat) +{ + disconnect(gif, SIGNAL(frameChanged(int)), this, SLOT(setButtonIconSlot(int))); + disconnect(ui->regNameButton, &QPushButton::clicked, this, &SettingsWidget::regNameRegisteredSlot); + + switch (stat) { + case RegName::BLANK: + ui->currentRegisteredID->setStyleSheet("padding-left: 5px; border: 0px; border-radius: 3px; border: 1px solid rgb(245, 245, 245);"); + regNameBtn_ = false; + ui->currentRegisteredID->setToolTip(tr("")); + ui->regNameButton->setIcon(QPixmap()); + ui->regNameButton->setEnabled(false); + break; + + case RegName::INVALIDFORM: + ui->currentRegisteredID->setStyleSheet("padding-left: 5px; border: 1px solid red; border-radius: 3px;"); + regNameBtn_ = false; + ui->currentRegisteredID->setToolTip(tr("A registered name should not have any spaces and must be at least three letters long")); + ui->regNameButton->setIcon(QPixmap(":/images/icons/round-error-24px.svg")); + ui->regNameButton->setToolTip(tr("A registered name should not have any spaces and must be at least three letters long")); + ui->regNameButton->setEnabled(true); + break; + + case RegName::TAKEN: + ui->currentRegisteredID->setStyleSheet("padding-left: 5px; border: 1px solid orange; border-radius: 3px;"); + regNameBtn_ = false; + ui->currentRegisteredID->setToolTip(tr("This name is already taken")); + ui->regNameButton->setIcon(QPixmap(":/images/icons/round-error-24px.svg")); + ui->regNameButton->setToolTip(tr("This registered name is already taken")); + ui->regNameButton->setEnabled(true); + break; + + case RegName::FREE: + ui->currentRegisteredID->setStyleSheet("padding-left: 5px; border: 1px solid green; border-radius: 3px;"); + regNameBtn_ = true; + ui->currentRegisteredID->setToolTip(tr("This name is available")); + ui->regNameButton->setIcon(QPixmap(":/images/icons/round-check_circle-24px.svg")); + ui->regNameButton->setToolTip(tr("Register this name")); + ui->regNameButton->setEnabled(true); + + connect(ui->regNameButton, &QPushButton::clicked, this, &SettingsWidget::regNameRegisteredSlot); + + break; + + case RegName::SEARCHING: + ui->currentRegisteredID->setStyleSheet("padding-left: 5px; border: 1px solid rgb(2, 187, 213); border-radius: 3px;"); + regNameBtn_ = false; + ui->currentRegisteredID->setToolTip(tr("")); + + connect(gif, SIGNAL(frameChanged(int)), this, SLOT(setButtonIconSlot(int))); + gif->start(); + ui->regNameButton->setEnabled(false); + + break; + } +} +void SettingsWidget::setButtonIconSlot(int frame) +{ + Q_UNUSED(frame); + ui->regNameButton->setIcon(QIcon(gif->currentPixmap())); +} + +void +SettingsWidget::regNameRegisteredSlot() +{ + if (!regNameBtn_) { return; } + + RegNameDialog regNameDialog(registeredName_, this); + if (regNameDialog.exec() == QDialog::Accepted) { // if user confirms regName choice + ui->currentRegisteredID->setReadOnly(true); + } + else { + ui->currentRegisteredID->setText(""); + registeredName_ = ""; + } + setRegNameUi(RegName::BLANK); +} + +void +SettingsWidget::setAccEnableSlot(int state) +{ + LRCInstance::editableAccountModel()->enableAccount(LRCInstance::getCurrAccId(), (bool)state); + + auto confProps = LRCInstance::accountModel().getAccountConfig(LRCInstance::getCurrAccId()); + LRCInstance::editableAccountModel()->setAccountConfig(LRCInstance::getCurrAccId(), confProps); +} + +void +SettingsWidget::delAccountSlot() +{ + DeleteAccountDialog delDialog(this); + delDialog.exec(); + + if (!LRCInstance::accountModel().getAccountList().size()) { + emit NavigationRequested(ScreenEnum::WizardScreen); + } +} + +void +SettingsWidget::removeDeviceSlot(int index) +{ + if (!index) { return; } + + auto deviceList = LRCInstance::getCurrentAccountInfo().deviceModel->getAllDevices(); + auto it = deviceList.begin(); + + std::advance(it, index); + QString psswd; + + bool ok = false; + if (LRCInstance::getCurrAccConfig().archiveHasPassword) { + psswd = QInputDialog::getText(this, tr("Remove Device"), + tr("Enter the password on this device to confirm the removal of this device"), QLineEdit::Password, + QDir::home().dirName(), &ok); + } + else { + psswd = ""; + QMessageBox devDel; + devDel.setText(tr("Please confirm that you wish to remove this device")); + devDel.setStandardButtons(QMessageBox::Ok | QMessageBox::Cancel); + devDel.setDefaultButton(QMessageBox::Cancel); + if (devDel.exec() == QMessageBox::Ok) { goto delete_; } + } + + if (ok) { + delete_: + LRCInstance::getCurrentAccountInfo().deviceModel->revokeDevice(it->id, psswd.toStdString()); + updateAndShowDevicesSlot(); + } +} + +void +SettingsWidget::unban(int index) +{ + auto bannedContactList = LRCInstance::getCurrentAccountInfo().contactModel->getBannedContacts(); + auto it = bannedContactList.begin(); + std::advance(it, index); + + auto contactInfo = LRCInstance::getCurrentAccountInfo().contactModel->getContact(*it); + + LRCInstance::getCurrentAccountInfo().contactModel->addContact(contactInfo); + updateAndShowBannedContactsSlot(); +} + +void +SettingsWidget::exportAccountSlot() +{ + QFileDialog dialog(this); + QString dir = QFileDialog::getExistingDirectory(this, tr("Export Account Here"), + QDir::homePath() + "/Desktop", QFileDialog::ShowDirsOnly | QFileDialog::DontResolveSymlinks); + + if (!dir.isEmpty()) { + LRCInstance::accountModel().exportToFile(LRCInstance::getCurrAccId(), (dir + "/export.gz").toStdString()); + } +} + +void +SettingsWidget::updateAndShowDevicesSlot() +{ + ui->settingsListWidget->clear(); + + ui->label->setText(tr("Linked Devices")); + ui->blockedContactsBtn->setText(tr("Blocked Contacts")); + ui->linkDevPushButton->show(); + + auto deviceList = LRCInstance::getCurrentAccountInfo().deviceModel->getAllDevices(); + + int i = 0; + + for (auto it = deviceList.begin(); it != deviceList.end(); ++it, ++i) { + SettingsItemWidget* item = new SettingsItemWidget(itemHeight_, i, false, ui->settingsListWidget); + item->setSizeHint(QSize(ui->settingsListWidget->width(), itemHeight_)); + ui->settingsListWidget->addItem(item); + + if (i) { + connect(item->button_, &QPushButton::clicked, [this, i]() { + removeDeviceSlot(i); + } + ); + } + } + bannedContactsShown_ = false; +} + +void +SettingsWidget::updateAndShowBannedContactsSlot() +{ + ui->settingsListWidget->clear(); + + ui->label->setText(tr("Blocked Contacts")); + ui->blockedContactsBtn->setText(tr("Linked Devices")); + ui->linkDevPushButton->hide(); + + auto bannedContactList = LRCInstance::getCurrentAccountInfo().contactModel->getBannedContacts(); + + int i = 0; + + for (auto it = bannedContactList.begin(); it != bannedContactList.end(); ++it, ++i) { + SettingsItemWidget* item = new SettingsItemWidget(itemHeight_, i, true, ui->settingsListWidget); + item->setSizeHint(QSize(ui->settingsListWidget->width(), itemHeight_)); + ui->settingsListWidget->addItem(item); + + connect(item->button_, &QPushButton::clicked, [this, i]() { + unban(i); + } + ); + } + bannedContactsShown_ = true; + if (!bannedContactList.size()) { updateAndShowDevicesSlot(); ui->blockedContactsBtn->hide(); } +} + +void +SettingsWidget::showLinkDevSlot() +{ + if (!advancedSettingsWidget_) { delete advancedSettingsWidget_; } + + linkDevWidget = new LinkDevWidget(ui->scrollAreaWidgetContents); + linkDevWidget->setMinimumWidth(600); + + ui->accountHorLayout->insertWidget(1, linkDevWidget); + + linkDevWidget->show(); + ui->centralWidget->hide(); + + connect(linkDevWidget->cancelBtn(), &QPushButton::clicked, this, &SettingsWidget::showCurrentAccountSlot); + connect(linkDevWidget->endCancelBtn(), &QPushButton::clicked, this, &SettingsWidget::showCurrentAccountSlot); +} + +void +SettingsWidget::showCurrentAccountSlot() +{ + disconnect(linkDevWidget); + + delete linkDevWidget; + ui->centralWidget->show(); +} + +void +SettingsWidget::setConnections() +{ + // exitSettingsButton + connect(ui->exitSettingsButton, &QPushButton::clicked, this, &SettingsWidget::leaveSettingsSlot); + + connect(ui->accountSettingsButton, &QPushButton::clicked, [this]() { + setSelected(Button::accountSettingsButton); } + ); + + connect(ui->generalSettingsButton, &QPushButton::clicked, [this]() { + setSelected(Button::generalSettingsButton); } + ); + + connect(ui->avSettingsButton, &QPushButton::clicked, [this]() { + setSelected(Button::avSettingsButton); } + ); + + connect(ui->passwdPushButton, &QPushButton::clicked, [this]() { + passwordClicked(); } + ); + + connect(ui->currentAccountAvatar, &QPushButton::clicked, [this]() { + avatarClicked(); } + ); + + connect(ui->advancedAccountSettingsPButton, &QPushButton::clicked, this, &SettingsWidget::toggleAdvancedSettings); + + connect(ui->currentRegisteredID, &QLineEdit::textChanged, this, &SettingsWidget::verifyRegisteredNameSlot); + + connect(&LRCInstance::accountModel(), &lrc::api::NewAccountModel::registeredNameFound, + this, &SettingsWidget::receiveRegNameSlot); + + //connect "export account" button + connect(ui->btnExportAccount, &QPushButton::clicked, this, &SettingsWidget::exportAccountSlot); + + // connect "delete account" button + connect(ui->btnDeletAccount, &QPushButton::clicked, this, &SettingsWidget::delAccountSlot); + + // connect "banned contacts" button + connect(ui->blockedContactsBtn, &QPushButton::clicked, this, &SettingsWidget::toggleBannedContacts); + + // connect "link device" button + connect(ui->linkDevPushButton, &QPushButton::clicked, this, &SettingsWidget::showLinkDevSlot); + + // update banned accounts automatically + connect(LRCInstance::getCurrentAccountInfo().contactModel.get(), &lrc::api::ContactModel::modelUpdated, + this, &SettingsWidget::updateAndShowBannedContactsSlot); + + // update linked devices automatically + QObject::connect(LRCInstance::getCurrentAccountInfo().deviceModel.get(), &lrc::api::NewDeviceModel::deviceUpdated, + this, &SettingsWidget::updateAndShowDevicesSlot); + + // account settings setters { + connect(ui->accountEnableCheckBox, &QCheckBox::stateChanged, this, &SettingsWidget::setAccEnableSlot); + + connect(ui->displayNameLineEdit, &QLineEdit::textChanged, [this](const QString& displayName) { + LRCInstance::setCurrAccDisplayName(displayName.toStdString()); + } + ); + + // general settings + + connect(ui->notificationCheckBox, &QCheckBox::stateChanged, this, &SettingsWidget::setNotificationsSlot); + + connect(ui->closeOrMinCheckBox, &QCheckBox::stateChanged, this, &SettingsWidget::setClosedOrMinSlot); + + connect(ui->downloadButton, &QPushButton::clicked, this, &SettingsWidget::openDownloadFolderSlot); + + connect(ui->alwaysRecordingCheckBox, &QCheckBox::stateChanged, this, &SettingsWidget::setAlwaysRecordingSlot); + + connect(ui->checkUpdateButton, &QPushButton::clicked, this, &SettingsWidget::checkForUpdateSlot); + + connect(ui->intervalUpdateCheckSpinBox, QOverload<int>::of(&QSpinBox::valueChanged), this, &SettingsWidget::setUpdateIntervalSlot); + + connect(ui->autoUpdateCheckBox, &QCheckBox::stateChanged, this, &SettingsWidget::setUpdateAutomaticSlot); + + // audio / visual settings + + connect(ui->recordPathButton, &QPushButton::clicked, this, &SettingsWidget::openRecordFolderSlot); +} + + +// ************************* General Settings ************************* + +void SettingsWidget::populateGeneralSettings() +{ + settings_ = new QSettings; + + // settings + ui->downloadButton->setText(QStandardPaths::writableLocation(QStandardPaths::DownloadLocation)); + ui->closeOrMinCheckBox->setChecked(settings_->value(SettingsKey::closeOrMinimized).toBool()); + ui->notificationCheckBox->setChecked(settings_->value(SettingsKey::enableNotifications).toBool()); + + //recordings + ui->alwaysRecordingCheckBox->setChecked(media::RecordingModel::instance().isAlwaysRecording()); + + if (media::RecordingModel::instance().recordPath().isEmpty()) { + QString recordPath = QDir::toNativeSeparators(QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation)); + media::RecordingModel::instance().setRecordPath(recordPath); + } + ui->recordPathButton->setText(media::RecordingModel::instance().recordPath()); + + + ui->autoUpdateCheckBox->setChecked(win_sparkle_get_automatic_check_for_updates()); + ui->intervalUpdateCheckSpinBox->setValue(win_sparkle_get_update_check_interval() / 86400); + +} + +void +SettingsWidget::setNotificationsSlot(int state) +{ + if (state == Qt::CheckState::Unchecked) { + settings_->setValue(SettingsKey::enableNotifications, false); + } else { + settings_->setValue(SettingsKey::enableNotifications, true); + } +} + +void +SettingsWidget::setClosedOrMinSlot(int state) +{ + if (state == Qt::CheckState::Unchecked) { + settings_->setValue(SettingsKey::closeOrMinimized, false); + } + else { + settings_->setValue(SettingsKey::closeOrMinimized, true); + } +} + +void +SettingsWidget::checkForUpdateSlot() +{ + win_sparkle_check_update_with_ui(); +} + +void +SettingsWidget::setUpdateIntervalSlot(int value) +{ + win_sparkle_set_update_check_interval(value * 86400); +} + +void +SettingsWidget::setUpdateAutomaticSlot(int state) +{ + if (state == Qt::CheckState::Unchecked) { + win_sparkle_set_automatic_check_for_updates(false); + ui->intervalUpdateCheckSpinBox->setEnabled(false); + } else { + win_sparkle_set_automatic_check_for_updates(true); + ui->intervalUpdateCheckSpinBox->setEnabled(true); + } +} + +void +SettingsWidget::openDownloadFolderSlot() +{ + QString dir = QFileDialog::getExistingDirectory(this, tr("Select A Folder For Your Downloads"), + QStandardPaths::writableLocation(QStandardPaths::DownloadLocation), QFileDialog::ShowDirsOnly + | QFileDialog::DontResolveSymlinks); + + if (!dir.isEmpty()) { + QStandardPaths::writableLocation(QStandardPaths::DownloadLocation) = dir; + ui->downloadButton->setText(dir); + } +} + +void +SettingsWidget::setAlwaysRecordingSlot(int state) +{ + if (state == Qt::CheckState::Unchecked) { + media::RecordingModel::instance().setAlwaysRecording(false); + } else { + media::RecordingModel::instance().setAlwaysRecording(true); + } +} + +void +SettingsWidget::openRecordFolderSlot() +{ + QString dir = QFileDialog::getExistingDirectory(this, tr("Select A Folder For Your Recordings"), + media::RecordingModel::instance().recordPath(), QFileDialog::ShowDirsOnly | QFileDialog::DontResolveSymlinks); + + if (!dir.isEmpty()) { + media::RecordingModel::instance().setRecordPath(dir); + ui->recordPathButton->setText(media::RecordingModel::instance().recordPath()); + } +} + + +// ************************* Audio/Visual Settings ************************* + +void +SettingsWidget::populateAVSettings() +{ + ui->deviceBox->setModel(deviceModel_); + connect(deviceModel_, SIGNAL(currentIndexChanged(int)), + this, SLOT(deviceIndexChanged(int))); + + if (ui->deviceBox->count() > 0) { + ui->deviceBox->setCurrentIndex(0); + deviceBoxCurrentIndexChangedSlot(0); + } + + // Audio settings + auto inputModel = Audio::Settings::instance().inputDeviceModel(); + auto outputModel = Audio::Settings::instance().outputDeviceModel(); + + ui->outputComboBox->setModel(outputModel); + ui->inputComboBox->setModel(inputModel); + if (ui->outputComboBox->count() > 0) { + ui->outputComboBox->setCurrentIndex(0); + } + if (ui->inputComboBox->count() > 0) { + ui->inputComboBox->setCurrentIndex(0); + } + + connect(ui->outputComboBox, QOverload<int>::of(&QComboBox::currentIndexChanged), + this, &SettingsWidget::outputDevIndexChangedSlot); + connect(ui->inputComboBox, QOverload<int>::of(&QComboBox::currentIndexChanged), + this, &SettingsWidget::inputdevIndexChangedSlot); + + connect(ui->deviceBox, QOverload<int>::of(&QComboBox::currentIndexChanged), this, + &SettingsWidget::deviceBoxCurrentIndexChangedSlot); + connect(ui->sizeBox, QOverload<int>::of(&QComboBox::currentIndexChanged), this, + &SettingsWidget::sizeBoxCurrentIndexChangedSlot); + + isLoading_ = true; + avSettingsHaveAppeared = true; + + showPreview(); +} + +void +SettingsWidget::showPreview() +{ + if (!CallModel::instance().getActiveCalls().size()) { + ui->previewUnavailableLabel->hide(); + ui->videoWidget->show(); + Video::PreviewManager::instance().startPreview(); + ui->videoWidget->setIsFullPreview(true); + } else { + ui->previewUnavailableLabel->show(); + ui->videoWidget->hide(); + } +} + +void +SettingsWidget::deviceBoxCurrentIndexChangedSlot(int index) +{ + if (index < 0) { + return; + } + + if (!isLoading_) + deviceModel_->setActive(index); + + auto device = deviceModel_->activeDevice(); + + ui->sizeBox->clear(); + + isLoading_ = true; + if (device->channelList().size() > 0) { + for (auto resolution : device->channelList()[0]->validResolutions()) { + ui->sizeBox->addItem(resolution->name()); + } + } + ui->sizeBox->setCurrentIndex( + device->channelList()[0]->activeResolution()->relativeIndex()); + isLoading_ = false; +} + +void +SettingsWidget::sizeBoxCurrentIndexChangedSlot(int index) +{ + auto device = deviceModel_->activeDevice(); + + if (index < 0) return; + + device->channelList()[0]->setActiveResolution(device->channelList()[0]->validResolutions()[index]); +} + +void +SettingsWidget::deviceIndexChanged(int index) +{ + ui->deviceBox->setCurrentIndex(index); + + ui->videoLayout->update(); +} + +void +SettingsWidget::outputDevIndexChangedSlot(int index) +{ + auto outputModel = Audio::Settings::instance().outputDeviceModel(); + outputModel->selectionModel()->setCurrentIndex(outputModel->index(index), QItemSelectionModel::ClearAndSelect); +} + +void +SettingsWidget::inputdevIndexChangedSlot(int index) +{ + auto inputModel = Audio::Settings::instance().inputDeviceModel(); + inputModel->selectionModel()->setCurrentIndex(inputModel->index(index), QItemSelectionModel::ClearAndSelect); +} \ No newline at end of file diff --git a/settingswidget.h b/settingswidget.h new file mode 100644 index 0000000..5fb68d1 --- /dev/null +++ b/settingswidget.h @@ -0,0 +1,158 @@ +/*************************************************************************** + * Copyright (C) 2018 by Savoir-faire Linux * + * Author: Isa Nanic <isa.nanic@savoirfairelinux.com> * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 3 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program. If not, see <https://www.gnu.org/licenses/>. * + **************************************************************************/ + +#pragma once +#include <QScrollArea> +#include <QSettings> +#include <QMovie> + +#include "navwidget.h" +#include "accountdetails.h" +#include "accountstatedelegate.h" +#include "lrcinstance.h" + +#include "advancedsettingswidget.h" +#include "bannedlistmodel.h" + +#include "linkdevwidget.h" +#include "ui_linkdevwidget.h" + + // general settings +#include "api/datatransfermodel.h" +#include "typedefs.h" + +// av settings +#include "video/devicemodel.h" + + +namespace Ui { + class SettingsWidget; +} + +class SettingsWidget : public NavWidget +{ + Q_OBJECT + SettingsWidget(const SettingsWidget& cpy); + +public: + explicit SettingsWidget(QWidget* parent = nullptr); + ~SettingsWidget(); + void resize(int size); + +public slots: + void updateSettings(int size); + +private: + enum Button {accountSettingsButton, generalSettingsButton, avSettingsButton}; + enum RegName {BLANK, INVALIDFORM, TAKEN, FREE, SEARCHING}; + enum List {DevList, BannedContacts}; + + void setSelected(Button sel); + void updateAccountInfoDisplayed(); + + void resizeEvent(QResizeEvent* event); + bool avSettingsHaveAppeared = false; + + Ui::SettingsWidget* ui; + + // ************************* Account Settings ************************* + void passwordClicked(); + void avatarClicked(); + + void afterNameLookup(lrc::api::account::LookupStatus status, const std::string& regName); + QString registeredName_; + + bool validateRegNameForm(const QString& regName); + + AdvancedSettingsWidget* advancedSettingsWidget_; + QScrollArea* scrollArea_; + Button pastButton_ = Button::generalSettingsButton; + bool advancedSettingsDropped_ = false; + bool bannedContactsShown_ = false; + + int avatarSize_; + + void setRegNameUi(RegName stat); + bool regNameBtn_ = false; + + const int itemHeight_ = 55; + + void removeDeviceSlot(int index); + void unban(int index); + + void setConnections(); + QMovie* gif; + + LinkDevWidget* linkDevWidget; + + +private slots: + void leaveSettingsSlot(); + void verifyRegisteredNameSlot(); + void beforeNameLookup(); + void receiveRegNameSlot(const std::string& accountID, lrc::api::account::LookupStatus status, + const std::string& address, const std::string& name); + void regNameRegisteredSlot(); + void setAccEnableSlot(int state); + void delAccountSlot(); + + void toggleAdvancedSettings(); + void toggleBannedContacts(); + void exportAccountSlot(); + + void updateAndShowDevicesSlot(); + void updateAndShowBannedContactsSlot(); + + void showLinkDevSlot(); + void showCurrentAccountSlot(); + + void setButtonIconSlot(int frame); + + + + // ************************* General Settings ************************* +private: + void populateGeneralSettings(); + + QSettings* settings_; + +private slots: + void setNotificationsSlot(int state); + void checkForUpdateSlot(); + void setClosedOrMinSlot(int state); + void openDownloadFolderSlot(); + void setAlwaysRecordingSlot(int state); + void openRecordFolderSlot(); + void setUpdateIntervalSlot(int value); + void setUpdateAutomaticSlot(int state); + + // ************************* Audio/Visual Settings ************************* +private: + void populateAVSettings(); + Video::DeviceModel* deviceModel_; + void showPreview(); + bool isLoading_; + +private slots: + void deviceIndexChanged(int index); + void deviceBoxCurrentIndexChangedSlot(int index); + void sizeBoxCurrentIndexChangedSlot(int index); + void outputDevIndexChangedSlot(int index); + void inputdevIndexChangedSlot(int index); + +}; diff --git a/settingswidget.ui b/settingswidget.ui new file mode 100644 index 0000000..636aee8 --- /dev/null +++ b/settingswidget.ui @@ -0,0 +1,2820 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>SettingsWidget</class> + <widget class="QWidget" name="SettingsWidget"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>936</width> + <height>860</height> + </rect> + </property> + <property name="windowTitle"> + <string>Form</string> + </property> + <property name="styleSheet"> + <string notr="true">background: white;</string> + </property> + <layout class="QHBoxLayout" name="horizontalLayout_3"> + <property name="spacing"> + <number>0</number> + </property> + <property name="leftMargin"> + <number>0</number> + </property> + <property name="topMargin"> + <number>0</number> + </property> + <property name="rightMargin"> + <number>0</number> + </property> + <property name="bottomMargin"> + <number>0</number> + </property> + <item> + <widget class="QWidget" name="leftSettingsWidget" native="true"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Fixed" vsizetype="Preferred"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="minimumSize"> + <size> + <width>0</width> + <height>0</height> + </size> + </property> + <property name="maximumSize"> + <size> + <width>16777215</width> + <height>16777215</height> + </size> + </property> + <property name="baseSize"> + <size> + <width>0</width> + <height>0</height> + </size> + </property> + <property name="styleSheet"> + <string notr="true">background: rgb(245, 245,245);</string> + </property> + <layout class="QVBoxLayout" name="leftVerticalLayout" stretch="0,0,0,1,0,0,0,5"> + <property name="spacing"> + <number>0</number> + </property> + <property name="leftMargin"> + <number>0</number> + </property> + <property name="topMargin"> + <number>0</number> + </property> + <property name="rightMargin"> + <number>0</number> + </property> + <property name="bottomMargin"> + <number>0</number> + </property> + <item> + <spacer name="verticalSpacer_5"> + <property name="orientation"> + <enum>Qt::Vertical</enum> + </property> + <property name="sizeType"> + <enum>QSizePolicy::Fixed</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>20</width> + <height>15</height> + </size> + </property> + </spacer> + </item> + <item> + <layout class="QHBoxLayout" name="horizontalLayout"> + <property name="spacing"> + <number>0</number> + </property> + <property name="rightMargin"> + <number>9</number> + </property> + <item> + <spacer name="horizontalSpacer_8"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeType"> + <enum>QSizePolicy::Fixed</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>40</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + <item> + <widget class="QLabel" name="label_10"> + <property name="font"> + <font> + <pointsize>14</pointsize> + <underline>false</underline> + </font> + </property> + <property name="text"> + <string>Settings</string> + </property> + </widget> + </item> + <item> + <spacer name="horizontalSpacer_2"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeType"> + <enum>QSizePolicy::MinimumExpanding</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>40</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + <item> + <widget class="QPushButton" name="exitSettingsButton"> + <property name="minimumSize"> + <size> + <width>30</width> + <height>30</height> + </size> + </property> + <property name="maximumSize"> + <size> + <width>30</width> + <height>30</height> + </size> + </property> + <property name="styleSheet"> + <string notr="true">QPushButton {background: white; border: 0px; border-radius: 8px;} +QPushButton:hover {background: rgb(237,237, 237); border: 0px; border-radius: 8px;} +QPushButton:pressed {background: rgb(230,230, 230); border: 0px; border-radius: 8px;}</string> + </property> + <property name="text"> + <string/> + </property> + </widget> + </item> + </layout> + </item> + <item> + <spacer name="verticalSpacer_4"> + <property name="orientation"> + <enum>Qt::Vertical</enum> + </property> + <property name="sizeType"> + <enum>QSizePolicy::Fixed</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>20</width> + <height>15</height> + </size> + </property> + </spacer> + </item> + <item> + <spacer name="verticalSpacer_6"> + <property name="orientation"> + <enum>Qt::Vertical</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>20</width> + <height>40</height> + </size> + </property> + </spacer> + </item> + <item> + <widget class="QPushButton" name="accountSettingsButton"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Minimum" vsizetype="MinimumExpanding"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="minimumSize"> + <size> + <width>200</width> + <height>60</height> + </size> + </property> + <property name="maximumSize"> + <size> + <width>16777215</width> + <height>60</height> + </size> + </property> + <property name="font"> + <font> + <pointsize>12</pointsize> + </font> + </property> + <property name="mouseTracking"> + <bool>true</bool> + </property> + <property name="styleSheet"> + <string notr="true"/> + </property> + <property name="text"> + <string>Account</string> + </property> + <property name="checkable"> + <bool>true</bool> + </property> + <property name="flat"> + <bool>true</bool> + </property> + </widget> + </item> + <item> + <widget class="QPushButton" name="generalSettingsButton"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Minimum" vsizetype="MinimumExpanding"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="minimumSize"> + <size> + <width>200</width> + <height>60</height> + </size> + </property> + <property name="maximumSize"> + <size> + <width>16777215</width> + <height>60</height> + </size> + </property> + <property name="font"> + <font> + <pointsize>12</pointsize> + </font> + </property> + <property name="mouseTracking"> + <bool>true</bool> + </property> + <property name="styleSheet"> + <string notr="true"/> + </property> + <property name="text"> + <string>General</string> + </property> + <property name="checkable"> + <bool>true</bool> + </property> + <property name="flat"> + <bool>true</bool> + </property> + </widget> + </item> + <item> + <widget class="QPushButton" name="avSettingsButton"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Minimum" vsizetype="MinimumExpanding"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="minimumSize"> + <size> + <width>200</width> + <height>60</height> + </size> + </property> + <property name="maximumSize"> + <size> + <width>16777215</width> + <height>60</height> + </size> + </property> + <property name="font"> + <font> + <pointsize>12</pointsize> + </font> + </property> + <property name="mouseTracking"> + <bool>true</bool> + </property> + <property name="styleSheet"> + <string notr="true"/> + </property> + <property name="text"> + <string>Audio / Video</string> + </property> + <property name="checkable"> + <bool>true</bool> + </property> + <property name="default"> + <bool>false</bool> + </property> + <property name="flat"> + <bool>true</bool> + </property> + </widget> + </item> + <item> + <spacer name="verticalSpacer"> + <property name="orientation"> + <enum>Qt::Vertical</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>20</width> + <height>40</height> + </size> + </property> + </spacer> + </item> + </layout> + </widget> + </item> + <item> + <widget class="QWidget" name="rightSettingsWidget" native="true"> + <property name="sizePolicy"> + <sizepolicy hsizetype="MinimumExpanding" vsizetype="MinimumExpanding"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="maximumSize"> + <size> + <width>16777215</width> + <height>16777215</height> + </size> + </property> + <layout class="QHBoxLayout" name="horizontalLayout_4" stretch="0"> + <property name="spacing"> + <number>0</number> + </property> + <property name="leftMargin"> + <number>0</number> + </property> + <property name="topMargin"> + <number>0</number> + </property> + <property name="rightMargin"> + <number>0</number> + </property> + <property name="bottomMargin"> + <number>0</number> + </property> + <item> + <widget class="QStackedWidget" name="stackedWidget"> + <property name="sizePolicy"> + <sizepolicy hsizetype="MinimumExpanding" vsizetype="MinimumExpanding"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="minimumSize"> + <size> + <width>500</width> + <height>850</height> + </size> + </property> + <property name="maximumSize"> + <size> + <width>80000</width> + <height>16777215</height> + </size> + </property> + <property name="styleSheet"> + <string notr="true">background: white;</string> + </property> + <property name="currentIndex"> + <number>1</number> + </property> + <widget class="QWidget" name="generalSettings"> + <property name="sizePolicy"> + <sizepolicy hsizetype="MinimumExpanding" vsizetype="Preferred"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="minimumSize"> + <size> + <width>600</width> + <height>850</height> + </size> + </property> + <property name="maximumSize"> + <size> + <width>16777215</width> + <height>16777215</height> + </size> + </property> + <layout class="QVBoxLayout" name="verticalLayout" stretch="0"> + <property name="leftMargin"> + <number>9</number> + </property> + <property name="rightMargin"> + <number>9</number> + </property> + <item> + <layout class="QHBoxLayout" name="horizontalLayout_5" stretch="2,0,3"> + <item> + <spacer name="horizontalSpacer_16"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>50</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + <item> + <widget class="QWidget" name="widget" native="true"> + <property name="minimumSize"> + <size> + <width>580</width> + <height>0</height> + </size> + </property> + <property name="maximumSize"> + <size> + <width>580</width> + <height>16777215</height> + </size> + </property> + <layout class="QVBoxLayout" name="verticalLayout_5"> + <item> + <layout class="QVBoxLayout" name="verticalLayout_4" stretch="1,0,0,0,0,0,0,0,0,0,0,0,0,0,3"> + <item> + <spacer name="verticalSpacer_2"> + <property name="orientation"> + <enum>Qt::Vertical</enum> + </property> + <property name="sizeType"> + <enum>QSizePolicy::MinimumExpanding</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>20</width> + <height>40</height> + </size> + </property> + </spacer> + </item> + <item> + <widget class="QLabel" name="label_4"> + <property name="font"> + <font> + <pointsize>13</pointsize> + </font> + </property> + <property name="text"> + <string>System</string> + </property> + </widget> + </item> + <item> + <spacer name="verticalSpacer_19"> + <property name="orientation"> + <enum>Qt::Vertical</enum> + </property> + <property name="sizeType"> + <enum>QSizePolicy::Fixed</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>20</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + <item> + <layout class="QHBoxLayout" name="horizontalLayout_19"> + <property name="leftMargin"> + <number>40</number> + </property> + <property name="topMargin"> + <number>5</number> + </property> + <item> + <widget class="QCheckBox" name="notificationCheckBox"> + <property name="font"> + <font> + <pointsize>10</pointsize> + </font> + </property> + <property name="toolTip"> + <string>enable notifications checkbox</string> + </property> + <property name="styleSheet"> + <string notr="true">color: rgb(77, 77, 77);</string> + </property> + <property name="text"> + <string>Enable desktop notifications</string> + </property> + </widget> + </item> + </layout> + </item> + <item> + <layout class="QHBoxLayout" name="horizontalLayout_20"> + <property name="leftMargin"> + <number>40</number> + </property> + <item> + <widget class="QCheckBox" name="closeOrMinCheckBox"> + <property name="font"> + <font> + <pointsize>10</pointsize> + </font> + </property> + <property name="toolTip"> + <string>keep minimized on close checkbox</string> + </property> + <property name="styleSheet"> + <string notr="true">color: rgb(77, 77, 77);</string> + </property> + <property name="text"> + <string>Keep minimized on close</string> + </property> + </widget> + </item> + </layout> + </item> + <item> + <spacer name="verticalSpacer_11"> + <property name="orientation"> + <enum>Qt::Vertical</enum> + </property> + <property name="sizeType"> + <enum>QSizePolicy::Fixed</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>20</width> + <height>15</height> + </size> + </property> + </spacer> + </item> + <item> + <layout class="QHBoxLayout" name="horizontalLayout_22"> + <property name="leftMargin"> + <number>50</number> + </property> + <property name="topMargin"> + <number>0</number> + </property> + <property name="rightMargin"> + <number>0</number> + </property> + <item> + <widget class="QLabel" name="label_3"> + <property name="font"> + <font> + <pointsize>10</pointsize> + </font> + </property> + <property name="text"> + <string>Download folder</string> + </property> + </widget> + </item> + <item> + <spacer name="horizontalSpacer_18"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>40</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + <item> + <widget class="QPushButton" name="downloadButton"> + <property name="enabled"> + <bool>false</bool> + </property> + <property name="minimumSize"> + <size> + <width>150</width> + <height>30</height> + </size> + </property> + <property name="maximumSize"> + <size> + <width>16777215</width> + <height>30</height> + </size> + </property> + <property name="styleSheet"> + <string notr="true">QPushButton {background: rgb(245, 245, 245); border: 0px; border-radius: 3px; padding: 5px;} +QPushButton:hover {background: rgb(237,237, 237); border: 0px; border-radius: 3px;} +QPushButton:pressed {background: rgb(230,230, 230); border: 0px; border-radius: 3px;}</string> + </property> + <property name="text"> + <string/> + </property> + <property name="icon"> + <iconset> + <normaloff>images/icons/round-folder-24px.svg</normaloff>images/icons/round-folder-24px.svg</iconset> + </property> + <property name="iconSize"> + <size> + <width>24</width> + <height>24</height> + </size> + </property> + </widget> + </item> + </layout> + </item> + <item> + <spacer name="verticalSpacer_18"> + <property name="orientation"> + <enum>Qt::Vertical</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>20</width> + <height>40</height> + </size> + </property> + </spacer> + </item> + <item> + <layout class="QVBoxLayout" name="verticalLayout_11"> + <item> + <layout class="QHBoxLayout" name="horizontalLayout_28"> + <item> + <widget class="QLabel" name="label_2"> + <property name="font"> + <font> + <pointsize>12</pointsize> + </font> + </property> + <property name="text"> + <string>Recordings</string> + </property> + </widget> + </item> + </layout> + </item> + <item> + <spacer name="verticalSpacer_20"> + <property name="orientation"> + <enum>Qt::Vertical</enum> + </property> + <property name="sizeType"> + <enum>QSizePolicy::Fixed</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>20</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + <item> + <layout class="QHBoxLayout" name="horizontalLayout_29"> + <property name="leftMargin"> + <number>50</number> + </property> + <property name="topMargin"> + <number>5</number> + </property> + <item> + <widget class="QLabel" name="label_5"> + <property name="font"> + <font> + <pointsize>10</pointsize> + </font> + </property> + <property name="text"> + <string>Save in</string> + </property> + </widget> + </item> + <item> + <spacer name="horizontalSpacer_12"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeType"> + <enum>QSizePolicy::MinimumExpanding</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>40</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + <item> + <widget class="QPushButton" name="recordPathButton"> + <property name="minimumSize"> + <size> + <width>150</width> + <height>30</height> + </size> + </property> + <property name="maximumSize"> + <size> + <width>16777215</width> + <height>30</height> + </size> + </property> + <property name="styleSheet"> + <string notr="true">QPushButton {background: rgb(245, 245, 245); border: 0px; border-radius: 3px; padding: 5px;} +QPushButton:hover {background: rgb(237,237, 237); border: 0px; border-radius: 3px;} +QPushButton:pressed {background: rgb(230,230, 230); border: 0px; border-radius: 3px;}</string> + </property> + <property name="text"> + <string/> + </property> + <property name="icon"> + <iconset> + <normaloff>images/icons/round-folder-24px.svg</normaloff>images/icons/round-folder-24px.svg</iconset> + </property> + <property name="iconSize"> + <size> + <width>24</width> + <height>24</height> + </size> + </property> + </widget> + </item> + </layout> + </item> + <item> + <layout class="QHBoxLayout" name="horizontalLayout_30"> + <property name="leftMargin"> + <number>20</number> + </property> + <item> + <widget class="QCheckBox" name="alwaysRecordingCheckBox"> + <property name="font"> + <font> + <pointsize>10</pointsize> + </font> + </property> + <property name="text"> + <string>Always Recording</string> + </property> + </widget> + </item> + </layout> + </item> + </layout> + </item> + <item> + <spacer name="verticalSpacer_14"> + <property name="orientation"> + <enum>Qt::Vertical</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>20</width> + <height>40</height> + </size> + </property> + </spacer> + </item> + <item> + <widget class="QLabel" name="label_6"> + <property name="font"> + <font> + <pointsize>12</pointsize> + </font> + </property> + <property name="text"> + <string>Updates</string> + </property> + </widget> + </item> + <item> + <spacer name="verticalSpacer_21"> + <property name="orientation"> + <enum>Qt::Vertical</enum> + </property> + <property name="sizeType"> + <enum>QSizePolicy::Fixed</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>20</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + <item> + <layout class="QHBoxLayout" name="horizontalLayout_6"> + <property name="leftMargin"> + <number>40</number> + </property> + <property name="topMargin"> + <number>5</number> + </property> + <item> + <widget class="QCheckBox" name="autoUpdateCheckBox"> + <property name="font"> + <font> + <pointsize>10</pointsize> + </font> + </property> + <property name="acceptDrops"> + <bool>false</bool> + </property> + <property name="toolTip"> + <string>Autamatic update checks checkbox</string> + </property> + <property name="styleSheet"> + <string notr="true">color: rgb(77, 77, 77);</string> + </property> + <property name="text"> + <string>Check for updates automatically every</string> + </property> + <property name="checked"> + <bool>true</bool> + </property> + </widget> + </item> + <item> + <widget class="QSpinBox" name="intervalUpdateCheckSpinBox"> + <property name="enabled"> + <bool>true</bool> + </property> + <property name="maximumSize"> + <size> + <width>60</width> + <height>16777215</height> + </size> + </property> + <property name="toolTip"> + <string>Interval between update checks in days selector</string> + </property> + <property name="suffix"> + <string> days</string> + </property> + <property name="minimum"> + <number>1</number> + </property> + <property name="value"> + <number>3</number> + </property> + </widget> + </item> + </layout> + </item> + <item> + <layout class="QHBoxLayout" name="horizontalLayout_17"> + <property name="topMargin"> + <number>0</number> + </property> + <item> + <spacer name="horizontalSpacer_5"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>40</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + <item> + <widget class="QPushButton" name="checkUpdateButton"> + <property name="sizePolicy"> + <sizepolicy hsizetype="MinimumExpanding" vsizetype="Preferred"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="minimumSize"> + <size> + <width>0</width> + <height>30</height> + </size> + </property> + <property name="font"> + <font> + <pointsize>9</pointsize> + </font> + </property> + <property name="toolTip"> + <string>Check for updates now button</string> + </property> + <property name="styleSheet"> + <string notr="true">QPushButton {background: rgb(245, 245, 245); border: 0px; border-radius: 3px; padding: 5px;} +QPushButton:hover {background: rgb(237,237, 237); border: 0px; border-radius: 3px;} +QPushButton:pressed {background: rgb(230,230, 230); border: 0px; border-radius: 3px;}</string> + </property> + <property name="text"> + <string>Check for updates now</string> + </property> + </widget> + </item> + <item> + <spacer name="horizontalSpacer_4"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>40</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + </layout> + </item> + <item> + <spacer name="accountSettingsBottom"> + <property name="orientation"> + <enum>Qt::Vertical</enum> + </property> + <property name="sizeType"> + <enum>QSizePolicy::MinimumExpanding</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>20</width> + <height>40</height> + </size> + </property> + </spacer> + </item> + </layout> + </item> + </layout> + </widget> + </item> + <item> + <spacer name="horizontalSpacer_17"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>50</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + </layout> + </item> + </layout> + </widget> + <widget class="QWidget" name="currentAccountSettingsScrollWidget"> + <property name="sizePolicy"> + <sizepolicy hsizetype="MinimumExpanding" vsizetype="Preferred"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="minimumSize"> + <size> + <width>600</width> + <height>860</height> + </size> + </property> + <property name="maximumSize"> + <size> + <width>16777215</width> + <height>16777215</height> + </size> + </property> + <property name="styleSheet"> + <string notr="true"/> + </property> + <layout class="QVBoxLayout" name="verticalLayout_2"> + <item> + <widget class="QScrollArea" name="scrollArea"> + <property name="frameShape"> + <enum>QFrame::NoFrame</enum> + </property> + <property name="frameShadow"> + <enum>QFrame::Plain</enum> + </property> + <property name="verticalScrollBarPolicy"> + <enum>Qt::ScrollBarAsNeeded</enum> + </property> + <property name="horizontalScrollBarPolicy"> + <enum>Qt::ScrollBarAlwaysOff</enum> + </property> + <property name="sizeAdjustPolicy"> + <enum>QAbstractScrollArea::AdjustIgnored</enum> + </property> + <property name="widgetResizable"> + <bool>true</bool> + </property> + <widget class="QWidget" name="scrollAreaWidgetContents"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>701</width> + <height>883</height> + </rect> + </property> + <property name="styleSheet"> + <string notr="true"/> + </property> + <layout class="QHBoxLayout" name="horizontalLayout_12" stretch="0"> + <item> + <layout class="QHBoxLayout" name="accountHorLayout" stretch="2,0,0,3"> + <item> + <spacer name="horizontalSpacer_6"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>460</width> + <height>811</height> + </size> + </property> + </spacer> + </item> + <item> + <widget class="QWidget" name="centralWidget" native="true"> + <property name="minimumSize"> + <size> + <width>600</width> + <height>0</height> + </size> + </property> + <layout class="QVBoxLayout" name="currentAccountSettingsScrollLayout" stretch="2,0,0,0,0,0,0,0,0,3,0,2"> + <item> + <spacer name="verticalSpacer_7"> + <property name="orientation"> + <enum>Qt::Vertical</enum> + </property> + <property name="sizeType"> + <enum>QSizePolicy::MinimumExpanding</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>20</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + <item> + <spacer name="horizontalSpacer_19"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeType"> + <enum>QSizePolicy::Fixed</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>600</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + <item> + <layout class="QHBoxLayout" name="horizontalLayout_56"> + <property name="bottomMargin"> + <number>0</number> + </property> + <item> + <layout class="QVBoxLayout" name="verticalLayout_17"> + <property name="spacing"> + <number>0</number> + </property> + <property name="leftMargin"> + <number>10</number> + </property> + <item> + <widget class="QPushButton" name="currentAccountAvatar"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Fixed" vsizetype="Fixed"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="minimumSize"> + <size> + <width>160</width> + <height>160</height> + </size> + </property> + <property name="maximumSize"> + <size> + <width>160</width> + <height>160</height> + </size> + </property> + <property name="font"> + <font> + <stylestrategy>PreferAntialias</stylestrategy> + </font> + </property> + <property name="cursor"> + <cursorShape>PointingHandCursor</cursorShape> + </property> + <property name="styleSheet"> + <string notr="true">border: none;</string> + </property> + <property name="text"> + <string/> + </property> + <property name="iconSize"> + <size> + <width>160</width> + <height>160</height> + </size> + </property> + <property name="flat"> + <bool>false</bool> + </property> + </widget> + </item> + </layout> + </item> + <item> + <layout class="QVBoxLayout" name="verticalLayout_18"> + <property name="topMargin"> + <number>10</number> + </property> + <item> + <layout class="QHBoxLayout" name="horizontalLayout_58" stretch="0,40"> + <property name="spacing"> + <number>0</number> + </property> + <property name="sizeConstraint"> + <enum>QLayout::SetDefaultConstraint</enum> + </property> + <item> + <widget class="QWidget" name="widget_4" native="true"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Fixed" vsizetype="Preferred"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="minimumSize"> + <size> + <width>110</width> + <height>0</height> + </size> + </property> + <property name="maximumSize"> + <size> + <width>110</width> + <height>16777215</height> + </size> + </property> + <layout class="QVBoxLayout" name="verticalLayout_19"> + <property name="spacing"> + <number>0</number> + </property> + <property name="leftMargin"> + <number>0</number> + </property> + <property name="topMargin"> + <number>0</number> + </property> + <property name="rightMargin"> + <number>0</number> + </property> + <property name="bottomMargin"> + <number>0</number> + </property> + <item> + <layout class="QHBoxLayout" name="horizontalLayout_16"> + <property name="bottomMargin"> + <number>5</number> + </property> + <item> + <spacer name="horizontalSpacer_14"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeType"> + <enum>QSizePolicy::MinimumExpanding</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>1</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + <item> + <widget class="QLabel" name="label_11"> + <property name="minimumSize"> + <size> + <width>0</width> + <height>40</height> + </size> + </property> + <property name="maximumSize"> + <size> + <width>16777215</width> + <height>40</height> + </size> + </property> + <property name="font"> + <font> + <pointsize>8</pointsize> + <weight>50</weight> + <bold>false</bold> + </font> + </property> + <property name="layoutDirection"> + <enum>Qt::LeftToRight</enum> + </property> + <property name="text"> + <string>Account</string> + </property> + <property name="alignment"> + <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> + </property> + </widget> + </item> + </layout> + </item> + <item> + <layout class="QHBoxLayout" name="horizontalLayout_60"> + <property name="bottomMargin"> + <number>0</number> + </property> + <item> + <spacer name="horizontalSpacer_42"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeType"> + <enum>QSizePolicy::MinimumExpanding</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>1</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + <item> + <widget class="QLabel" name="currentRegisteredIDLabel"> + <property name="minimumSize"> + <size> + <width>90</width> + <height>32</height> + </size> + </property> + <property name="maximumSize"> + <size> + <width>16777215</width> + <height>32</height> + </size> + </property> + <property name="text"> + <string>Registered Name</string> + </property> + </widget> + </item> + </layout> + </item> + <item> + <layout class="QHBoxLayout" name="horizontalLayout_59"> + <property name="bottomMargin"> + <number>3</number> + </property> + <item> + <spacer name="horizontalSpacer_41"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeType"> + <enum>QSizePolicy::MinimumExpanding</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>1</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + <item> + <widget class="QLabel" name="currentRingIDMessage"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Fixed" vsizetype="Preferred"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="minimumSize"> + <size> + <width>0</width> + <height>40</height> + </size> + </property> + <property name="maximumSize"> + <size> + <width>150</width> + <height>40</height> + </size> + </property> + <property name="font"> + <font> + <pointsize>8</pointsize> + <stylestrategy>PreferAntialias</stylestrategy> + </font> + </property> + <property name="text"> + <string>RingID</string> + </property> + </widget> + </item> + </layout> + </item> + <item> + <layout class="QHBoxLayout" name="horizontalLayout_7"> + <item> + <spacer name="horizontalSpacer_25"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>40</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + <item> + <widget class="QLabel" name="label_7"> + <property name="minimumSize"> + <size> + <width>0</width> + <height>30</height> + </size> + </property> + <property name="maximumSize"> + <size> + <width>16777215</width> + <height>30</height> + </size> + </property> + <property name="text"> + <string>Password</string> + </property> + </widget> + </item> + </layout> + </item> + <item> + <spacer name="verticalSpacer_28"> + <property name="orientation"> + <enum>Qt::Vertical</enum> + </property> + <property name="sizeType"> + <enum>QSizePolicy::MinimumExpanding</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>20</width> + <height>8</height> + </size> + </property> + </spacer> + </item> + </layout> + </widget> + </item> + <item> + <layout class="QVBoxLayout" name="verticalLayout_20"> + <property name="spacing"> + <number>0</number> + </property> + <property name="leftMargin"> + <number>10</number> + </property> + <item> + <layout class="QHBoxLayout" name="horizontalLayout_14"> + <property name="bottomMargin"> + <number>5</number> + </property> + <item> + <widget class="QCheckBox" name="accountEnableCheckBox"> + <property name="sizePolicy"> + <sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="minimumSize"> + <size> + <width>0</width> + <height>40</height> + </size> + </property> + <property name="maximumSize"> + <size> + <width>140</width> + <height>40</height> + </size> + </property> + <property name="font"> + <font> + <pointsize>9</pointsize> + </font> + </property> + <property name="layoutDirection"> + <enum>Qt::LeftToRight</enum> + </property> + <property name="styleSheet"> + <string notr="true"/> + </property> + <property name="text"> + <string>Enable</string> + </property> + </widget> + </item> + <item> + <spacer name="horizontalSpacer_15"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeType"> + <enum>QSizePolicy::MinimumExpanding</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>1</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + </layout> + </item> + <item> + <layout class="QHBoxLayout" name="horizontalLayout_61"> + <item> + <widget class="QLineEdit" name="currentRegisteredID"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Fixed" vsizetype="Preferred"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="minimumSize"> + <size> + <width>250</width> + <height>32</height> + </size> + </property> + <property name="maximumSize"> + <size> + <width>144444</width> + <height>32</height> + </size> + </property> + <property name="font"> + <font> + <pointsize>9</pointsize> + <stylestrategy>PreferAntialias</stylestrategy> + </font> + </property> + <property name="mouseTracking"> + <bool>true</bool> + </property> + <property name="styleSheet"> + <string notr="true">padding-left: 10; border: 1px solid black;</string> + </property> + <property name="text"> + <string/> + </property> + <property name="frame"> + <bool>false</bool> + </property> + <property name="alignment"> + <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set> + </property> + <property name="readOnly"> + <bool>false</bool> + </property> + <property name="placeholderText"> + <string>Type here to register a username</string> + </property> + <property name="clearButtonEnabled"> + <bool>false</bool> + </property> + </widget> + </item> + <item> + <widget class="QPushButton" name="regNameButton"> + <property name="minimumSize"> + <size> + <width>32</width> + <height>32</height> + </size> + </property> + <property name="maximumSize"> + <size> + <width>32</width> + <height>32</height> + </size> + </property> + <property name="text"> + <string/> + </property> + <property name="iconSize"> + <size> + <width>24</width> + <height>24</height> + </size> + </property> + <property name="flat"> + <bool>true</bool> + </property> + </widget> + </item> + <item> + <spacer name="horizontalSpacer_9"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeType"> + <enum>QSizePolicy::MinimumExpanding</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>1</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + </layout> + </item> + <item> + <layout class="QHBoxLayout" name="horizontalLayout_62"> + <property name="spacing"> + <number>0</number> + </property> + <item> + <widget class="QLineEdit" name="currentRingID"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Preferred" vsizetype="Preferred"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="minimumSize"> + <size> + <width>290</width> + <height>40</height> + </size> + </property> + <property name="maximumSize"> + <size> + <width>16777215</width> + <height>40</height> + </size> + </property> + <property name="font"> + <font> + <pointsize>9</pointsize> + <stylestrategy>PreferAntialias</stylestrategy> + </font> + </property> + <property name="layoutDirection"> + <enum>Qt::RightToLeft</enum> + </property> + <property name="styleSheet"> + <string notr="true">border: 0px; padding: 1px;</string> + </property> + <property name="text"> + <string/> + </property> + <property name="alignment"> + <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set> + </property> + </widget> + </item> + <item> + <spacer name="horizontalSpacer_10"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeType"> + <enum>QSizePolicy::MinimumExpanding</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>1</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + </layout> + </item> + <item> + <layout class="QHBoxLayout" name="horizontalLayout_63"> + <property name="leftMargin"> + <number>5</number> + </property> + <property name="topMargin"> + <number>0</number> + </property> + <item> + <widget class="QPushButton" name="passwdPushButton"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Fixed" vsizetype="Fixed"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="minimumSize"> + <size> + <width>134</width> + <height>30</height> + </size> + </property> + <property name="maximumSize"> + <size> + <width>134</width> + <height>30</height> + </size> + </property> + <property name="font"> + <font> + <pointsize>9</pointsize> + <underline>false</underline> + </font> + </property> + <property name="styleSheet"> + <string notr="true">QPushButton {background: rgb(245, 245, 245); border: 0px; border-radius: 3px;} +QPushButton:hover {background: rgb(237,237, 237); border: 0px; border-radius: 3px;} +QPushButton:pressed {background: rgb(230,230, 230); border: 0px; border-radius: 3px;}</string> + </property> + <property name="text"> + <string>Change Password</string> + </property> + <property name="checkable"> + <bool>true</bool> + </property> + </widget> + </item> + <item> + <spacer name="horizontalSpacer_7"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>40</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + </layout> + </item> + <item> + <spacer name="verticalSpacer_8"> + <property name="orientation"> + <enum>Qt::Vertical</enum> + </property> + <property name="sizeType"> + <enum>QSizePolicy::MinimumExpanding</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>20</width> + <height>8</height> + </size> + </property> + </spacer> + </item> + </layout> + </item> + </layout> + </item> + </layout> + </item> + </layout> + </item> + <item> + <layout class="QHBoxLayout" name="horizontalLayout_64" stretch="0,0"> + <property name="spacing"> + <number>10</number> + </property> + <property name="topMargin"> + <number>0</number> + </property> + <item> + <widget class="QLineEdit" name="displayNameLineEdit"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Fixed" vsizetype="Fixed"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="minimumSize"> + <size> + <width>180</width> + <height>30</height> + </size> + </property> + <property name="maximumSize"> + <size> + <width>180</width> + <height>50</height> + </size> + </property> + <property name="font"> + <font> + <stylestrategy>PreferAntialias</stylestrategy> + </font> + </property> + <property name="styleSheet"> + <string notr="true">border: 0px; border-radius: 3px; background: rgb(245, 245, 245);</string> + </property> + <property name="text"> + <string/> + </property> + </widget> + </item> + <item> + <spacer name="horizontalSpacer_45"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeType"> + <enum>QSizePolicy::MinimumExpanding</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>400</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + </layout> + </item> + <item> + <layout class="QGridLayout" name="gridLayout_8"> + <property name="topMargin"> + <number>30</number> + </property> + <property name="bottomMargin"> + <number>0</number> + </property> + <item row="1" column="0"> + <spacer name="verticalSpacer_30"> + <property name="orientation"> + <enum>Qt::Vertical</enum> + </property> + <property name="sizeType"> + <enum>QSizePolicy::Fixed</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>20</width> + <height>32</height> + </size> + </property> + </spacer> + </item> + <item row="0" column="0"> + <layout class="QHBoxLayout" name="horizontalLayout_65"> + <property name="spacing"> + <number>50</number> + </property> + <property name="leftMargin"> + <number>50</number> + </property> + <property name="topMargin"> + <number>20</number> + </property> + <property name="rightMargin"> + <number>50</number> + </property> + <property name="bottomMargin"> + <number>20</number> + </property> + <item> + <widget class="QPushButton" name="btnExportAccount"> + <property name="minimumSize"> + <size> + <width>0</width> + <height>30</height> + </size> + </property> + <property name="styleSheet"> + <string notr="true">border: 0px; border-radius: 3px; background: #e8f5e9;</string> + </property> + <property name="text"> + <string>Export Account</string> + </property> + <property name="flat"> + <bool>true</bool> + </property> + </widget> + </item> + <item> + <widget class="QPushButton" name="btnDeletAccount"> + <property name="minimumSize"> + <size> + <width>0</width> + <height>30</height> + </size> + </property> + <property name="styleSheet"> + <string notr="true">border: 0px; border-radius: 3px; background:#ffebee;</string> + </property> + <property name="text"> + <string>Delete Account</string> + </property> + <property name="flat"> + <bool>true</bool> + </property> + </widget> + </item> + </layout> + </item> + <item row="2" column="0"> + <widget class="QLabel" name="label"> + <property name="maximumSize"> + <size> + <width>16777215</width> + <height>30</height> + </size> + </property> + <property name="font"> + <font> + <pointsize>11</pointsize> + </font> + </property> + <property name="text"> + <string>Linked Devices</string> + </property> + </widget> + </item> + </layout> + </item> + <item> + <layout class="QHBoxLayout" name="horizontalLayout_66"> + <property name="leftMargin"> + <number>0</number> + </property> + <property name="topMargin"> + <number>0</number> + </property> + <property name="rightMargin"> + <number>1</number> + </property> + <property name="bottomMargin"> + <number>3</number> + </property> + <item> + <spacer name="horizontalSpacer_46"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>40</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + <item> + <widget class="QLabel" name="label_12"> + <property name="minimumSize"> + <size> + <width>0</width> + <height>30</height> + </size> + </property> + <property name="text"> + <string/> + </property> + </widget> + </item> + <item> + <widget class="QPushButton" name="linkDevPushButton"> + <property name="minimumSize"> + <size> + <width>150</width> + <height>30</height> + </size> + </property> + <property name="maximumSize"> + <size> + <width>80000</width> + <height>30</height> + </size> + </property> + <property name="styleSheet"> + <string notr="true">border: 0px; border-radius: 3px; background: rgb(245, 245, 245); +padding: 5px; +</string> + </property> + <property name="text"> + <string>Link Another Device</string> + </property> + <property name="iconSize"> + <size> + <width>24</width> + <height>24</height> + </size> + </property> + <property name="flat"> + <bool>false</bool> + </property> + </widget> + </item> + </layout> + </item> + <item> + <widget class="QListWidget" name="settingsListWidget"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Expanding" vsizetype="MinimumExpanding"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="minimumSize"> + <size> + <width>600</width> + <height>0</height> + </size> + </property> + <property name="maximumSize"> + <size> + <width>16777215</width> + <height>200</height> + </size> + </property> + <property name="styleSheet"> + <string notr="true">border: 1px solid grey;</string> + </property> + <property name="frameShadow"> + <enum>QFrame::Plain</enum> + </property> + <property name="editTriggers"> + <set>QAbstractItemView::NoEditTriggers</set> + </property> + <property name="showDropIndicator" stdset="0"> + <bool>false</bool> + </property> + <property name="alternatingRowColors"> + <bool>false</bool> + </property> + <property name="selectionMode"> + <enum>QAbstractItemView::NoSelection</enum> + </property> + <property name="uniformItemSizes"> + <bool>true</bool> + </property> + </widget> + </item> + <item> + <layout class="QHBoxLayout" name="horizontalLayout_67"> + <property name="topMargin"> + <number>5</number> + </property> + <item> + <widget class="QPushButton" name="blockedContactsBtn"> + <property name="minimumSize"> + <size> + <width>120</width> + <height>25</height> + </size> + </property> + <property name="maximumSize"> + <size> + <width>180</width> + <height>25</height> + </size> + </property> + <property name="layoutDirection"> + <enum>Qt::RightToLeft</enum> + </property> + <property name="styleSheet"> + <string notr="true">border: 0px; border-radius: 3px; background: rgb(245, 245, 245); +padding-right: 20px; +padding-left: 15px; +</string> + </property> + <property name="text"> + <string>Blocked Contacts</string> + </property> + <property name="iconSize"> + <size> + <width>24</width> + <height>24</height> + </size> + </property> + </widget> + </item> + <item> + <spacer name="horizontalSpacer_47"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>40</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + </layout> + </item> + <item> + <widget class="QLabel" name="advancedSettingsOffsetLabel"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Preferred" vsizetype="Fixed"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="minimumSize"> + <size> + <width>0</width> + <height>4</height> + </size> + </property> + <property name="maximumSize"> + <size> + <width>16777215</width> + <height>4</height> + </size> + </property> + <property name="text"> + <string/> + </property> + </widget> + </item> + <item> + <spacer name="verticalSpacer_10"> + <property name="orientation"> + <enum>Qt::Vertical</enum> + </property> + <property name="sizeType"> + <enum>QSizePolicy::MinimumExpanding</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>20</width> + <height>15</height> + </size> + </property> + </spacer> + </item> + <item> + <layout class="QHBoxLayout" name="horizontalLayout_68" stretch="1,0,1"> + <property name="topMargin"> + <number>4</number> + </property> + <property name="bottomMargin"> + <number>15</number> + </property> + <item> + <spacer name="horizontalSpacer_48"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeType"> + <enum>QSizePolicy::MinimumExpanding</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>40</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + <item> + <widget class="QPushButton" name="advancedAccountSettingsPButton"> + <property name="minimumSize"> + <size> + <width>180</width> + <height>30</height> + </size> + </property> + <property name="maximumSize"> + <size> + <width>600</width> + <height>30</height> + </size> + </property> + <property name="layoutDirection"> + <enum>Qt::RightToLeft</enum> + </property> + <property name="styleSheet"> + <string notr="true">border: 0px; border-radius: 3px; background: rgb(245, 245, 245); +padding-right: 20px; +padding-left: 15px; +</string> + </property> + <property name="text"> + <string>Advanced Account Settings</string> + </property> + <property name="iconSize"> + <size> + <width>24</width> + <height>24</height> + </size> + </property> + </widget> + </item> + <item> + <spacer name="horizontalSpacer_49"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeType"> + <enum>QSizePolicy::MinimumExpanding</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>40</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + </layout> + </item> + <item> + <spacer name="verticalSpacer_9"> + <property name="orientation"> + <enum>Qt::Vertical</enum> + </property> + <property name="sizeType"> + <enum>QSizePolicy::MinimumExpanding</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>20</width> + <height>40</height> + </size> + </property> + </spacer> + </item> + </layout> + </widget> + </item> + <item> + <widget class="QLabel" name="scrollBarLabel"> + <property name="minimumSize"> + <size> + <width>4</width> + <height>0</height> + </size> + </property> + <property name="maximumSize"> + <size> + <width>4</width> + <height>16777215</height> + </size> + </property> + <property name="toolTip"> + <string notr="true"/> + </property> + <property name="whatsThis"> + <string notr="true"/> + </property> + <property name="text"> + <string/> + </property> + <property name="textFormat"> + <enum>Qt::PlainText</enum> + </property> + </widget> + </item> + <item> + <spacer name="horizontalSpacer_3"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>697</width> + <height>811</height> + </size> + </property> + </spacer> + </item> + </layout> + </item> + </layout> + </widget> + </widget> + </item> + </layout> + </widget> + <widget class="QWidget" name="avSettings"> + <property name="sizePolicy"> + <sizepolicy hsizetype="MinimumExpanding" vsizetype="Preferred"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <layout class="QGridLayout" name="gridLayout_3"> + <property name="leftMargin"> + <number>0</number> + </property> + <property name="topMargin"> + <number>0</number> + </property> + <property name="rightMargin"> + <number>0</number> + </property> + <property name="bottomMargin"> + <number>0</number> + </property> + <item row="0" column="0"> + <layout class="QVBoxLayout" name="verticalLayout_3"> + <item> + <layout class="QHBoxLayout" name="horizontalLayout_2" stretch="2,0,3"> + <property name="spacing"> + <number>0</number> + </property> + <item> + <spacer name="horizontalSpacer"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>40</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + <item> + <widget class="QWidget" name="widget_2" native="true"> + <property name="minimumSize"> + <size> + <width>580</width> + <height>0</height> + </size> + </property> + <property name="maximumSize"> + <size> + <width>580</width> + <height>16777215</height> + </size> + </property> + <property name="styleSheet"> + <string notr="true"/> + </property> + <layout class="QVBoxLayout" name="verticalLayout_8" stretch="2,0,0,0,0,0,0,5"> + <item> + <spacer name="verticalSpacer_23"> + <property name="orientation"> + <enum>Qt::Vertical</enum> + </property> + <property name="sizeType"> + <enum>QSizePolicy::MinimumExpanding</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>20</width> + <height>40</height> + </size> + </property> + </spacer> + </item> + <item> + <layout class="QVBoxLayout" name="verticalLayout_9"> + <item> + <widget class="QLabel" name="label_16"> + <property name="minimumSize"> + <size> + <width>0</width> + <height>30</height> + </size> + </property> + <property name="maximumSize"> + <size> + <width>16777215</width> + <height>30</height> + </size> + </property> + <property name="font"> + <font> + <pointsize>13</pointsize> + </font> + </property> + <property name="text"> + <string>Audio</string> + </property> + </widget> + </item> + <item> + <layout class="QVBoxLayout" name="verticalLayout_12"> + <property name="spacing"> + <number>0</number> + </property> + <property name="leftMargin"> + <number>20</number> + </property> + <item> + <spacer name="verticalSpacer_13"> + <property name="orientation"> + <enum>Qt::Vertical</enum> + </property> + <property name="sizeType"> + <enum>QSizePolicy::Fixed</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>20</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + <item> + <layout class="QHBoxLayout" name="horizontalLayout_32"> + <property name="spacing"> + <number>0</number> + </property> + <item> + <widget class="QLabel" name="label_18"> + <property name="minimumSize"> + <size> + <width>0</width> + <height>0</height> + </size> + </property> + <property name="maximumSize"> + <size> + <width>200</width> + <height>16777215</height> + </size> + </property> + <property name="font"> + <font> + <pointsize>11</pointsize> + </font> + </property> + <property name="text"> + <string>Microphone</string> + </property> + </widget> + </item> + <item> + <spacer name="horizontalSpacer_20"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>40</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + <item> + <widget class="QComboBox" name="inputComboBox"> + <property name="minimumSize"> + <size> + <width>320</width> + <height>0</height> + </size> + </property> + <property name="toolTip"> + <string>Audio input device selector</string> + </property> + </widget> + </item> + </layout> + </item> + <item> + <layout class="QHBoxLayout" name="horizontalLayout_31"> + <property name="spacing"> + <number>0</number> + </property> + <item> + <widget class="QLabel" name="label_17"> + <property name="minimumSize"> + <size> + <width>0</width> + <height>0</height> + </size> + </property> + <property name="maximumSize"> + <size> + <width>100</width> + <height>16777215</height> + </size> + </property> + <property name="font"> + <font> + <pointsize>11</pointsize> + </font> + </property> + <property name="text"> + <string>Output Device</string> + </property> + </widget> + </item> + <item> + <spacer name="horizontalSpacer_13"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>40</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + <item> + <widget class="QComboBox" name="outputComboBox"> + <property name="minimumSize"> + <size> + <width>320</width> + <height>0</height> + </size> + </property> + <property name="maximumSize"> + <size> + <width>200</width> + <height>16777215</height> + </size> + </property> + <property name="toolTip"> + <string>Choose the output device</string> + </property> + </widget> + </item> + </layout> + </item> + <item> + <spacer name="verticalSpacer_22"> + <property name="orientation"> + <enum>Qt::Vertical</enum> + </property> + <property name="sizeType"> + <enum>QSizePolicy::Fixed</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>20</width> + <height>30</height> + </size> + </property> + </spacer> + </item> + </layout> + </item> + </layout> + </item> + <item> + <layout class="QHBoxLayout" name="horizontalLayout_9"> + <item> + <widget class="QLabel" name="label_19"> + <property name="minimumSize"> + <size> + <width>0</width> + <height>30</height> + </size> + </property> + <property name="maximumSize"> + <size> + <width>16777215</width> + <height>30</height> + </size> + </property> + <property name="font"> + <font> + <pointsize>13</pointsize> + </font> + </property> + <property name="text"> + <string>Video</string> + </property> + </widget> + </item> + </layout> + </item> + <item> + <layout class="QVBoxLayout" name="verticalLayout_13"> + <property name="leftMargin"> + <number>20</number> + </property> + <item> + <layout class="QHBoxLayout" name="horizontalLayout_33"> + <property name="spacing"> + <number>0</number> + </property> + <item> + <widget class="QLabel" name="label_20"> + <property name="font"> + <font> + <pointsize>11</pointsize> + </font> + </property> + <property name="text"> + <string>Device</string> + </property> + </widget> + </item> + <item> + <spacer name="horizontalSpacer_21"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>40</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + <item> + <widget class="QComboBox" name="deviceBox"> + <property name="sizePolicy"> + <sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="minimumSize"> + <size> + <width>320</width> + <height>0</height> + </size> + </property> + <property name="maximumSize"> + <size> + <width>16777215</width> + <height>16777215</height> + </size> + </property> + <property name="toolTip"> + <string>Video device selector</string> + </property> + </widget> + </item> + </layout> + </item> + <item> + <layout class="QHBoxLayout" name="horizontalLayout_34"> + <property name="spacing"> + <number>0</number> + </property> + <item> + <widget class="QLabel" name="label_21"> + <property name="font"> + <font> + <pointsize>11</pointsize> + </font> + </property> + <property name="text"> + <string>Resolution</string> + </property> + </widget> + </item> + <item> + <spacer name="horizontalSpacer_22"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>40</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + <item> + <widget class="QComboBox" name="sizeBox"> + <property name="sizePolicy"> + <sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="minimumSize"> + <size> + <width>320</width> + <height>0</height> + </size> + </property> + <property name="maximumSize"> + <size> + <width>16777215</width> + <height>16777215</height> + </size> + </property> + <property name="toolTip"> + <string>Video device resolution selector</string> + </property> + </widget> + </item> + </layout> + </item> + </layout> + </item> + <item> + <spacer name="verticalSpacer_3"> + <property name="orientation"> + <enum>Qt::Vertical</enum> + </property> + <property name="sizeType"> + <enum>QSizePolicy::MinimumExpanding</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>20</width> + <height>40</height> + </size> + </property> + </spacer> + </item> + <item> + <layout class="QHBoxLayout" name="videoLayout" stretch="1,0,1"> + <property name="spacing"> + <number>0</number> + </property> + <item> + <spacer name="horizontalSpacer_23"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeType"> + <enum>QSizePolicy::MinimumExpanding</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>40</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + <item> + <widget class="VideoWidget" name="videoWidget" native="true"> + <property name="enabled"> + <bool>true</bool> + </property> + <property name="sizePolicy"> + <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="minimumSize"> + <size> + <width>520</width> + <height>300</height> + </size> + </property> + <property name="maximumSize"> + <size> + <width>16777215</width> + <height>16777215</height> + </size> + </property> + <property name="baseSize"> + <size> + <width>550</width> + <height>300</height> + </size> + </property> + <property name="styleSheet"> + <string notr="true"/> + </property> + </widget> + </item> + <item> + <spacer name="horizontalSpacer_24"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeType"> + <enum>QSizePolicy::MinimumExpanding</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>40</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + </layout> + </item> + <item> + <widget class="QLabel" name="previewUnavailableLabel"> + <property name="font"> + <font> + <pointsize>10</pointsize> + </font> + </property> + <property name="text"> + <string>Preview unavailable during call</string> + </property> + </widget> + </item> + <item> + <spacer name="verticalSpacer_24"> + <property name="orientation"> + <enum>Qt::Vertical</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>20</width> + <height>40</height> + </size> + </property> + </spacer> + </item> + </layout> + </widget> + </item> + <item> + <spacer name="horizontalSpacer_11"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>40</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + </layout> + </item> + </layout> + </item> + </layout> + </widget> + </widget> + </item> + </layout> + </widget> + </item> + </layout> + </widget> + <customwidgets> + <customwidget> + <class>VideoWidget</class> + <extends>QWidget</extends> + <header>videowidget.h</header> + <container>1</container> + </customwidget> + </customwidgets> + <resources/> + <connections/> +</ui> diff --git a/smartlistmodel.h b/smartlistmodel.h index 1da0a65..a37cbb1 100644 --- a/smartlistmodel.h +++ b/smartlistmodel.h @@ -66,5 +66,4 @@ public: private: const AccountInfo& acc_; - }; diff --git a/smartlistview.h b/smartlistview.h index 126c1a2..ac13600 100644 --- a/smartlistview.h +++ b/smartlistview.h @@ -42,5 +42,4 @@ signals: void btnAcceptInviteClicked(const QModelIndex& index) const; void btnBlockInviteClicked(const QModelIndex& index) const; void btnIgnoreInviteClicked(const QModelIndex& index) const; - }; diff --git a/stylesheet.css b/stylesheet.css index 63150a8..1b5294d 100644 --- a/stylesheet.css +++ b/stylesheet.css @@ -266,10 +266,6 @@ QToolButton#qrButton:checked { background-color: rgb(237, 237, 237); } -QPushButton#deleteAccountBtn, QToolButton#addAccountButton{ - background: transparent; -} - QPushButton#btnvideo{ background-color: #3AC0D2; border-radius: 15px; @@ -315,7 +311,7 @@ QWidget#messagingPage, QWidget#contactRequestPage{ } QPushButton#nextButton, QPushButton#playButton, QPushButton#clearHistoryButton, QPushButton#doTransferButton, -QPushButton#checkUpdateButton, QPushButton#photoButton, QPushButton#takePhotoButton, QPushButton#importButton, +QPushButton#photoButton, QPushButton#takePhotoButton, QPushButton#importButton, QPushButton#existingPushButton, QPushButton#newAccountButton, QPushButton#previousButton, QPushButton#exportButton, QPushButton#cancelAddButton, QPushButton#exportOnRingButton, QPushButton#addDeviceButton, QPushButton#exportEndedOkButton, QPushButton#errorPushButton, QPushButton#registerButton, QPushButton#acceptCRButton, QPushButton#discardCRButton, QPushButton#deleteCancelBtn, @@ -326,7 +322,7 @@ QPushButton#dhtImportBtn, QPushButton#fileImportBtn, QPushButton#changePassBtn, font: 14px; } -QPushButton#blockCRButton, QPushButton#deleteAcceptBtn, QPushButton#debanButton, QPushButton#deleteButton, QPushButton#deleteBanBtn, +QPushButton#blockCRButton, QPushButton#debanButton, QPushButton#deleteBanBtn, QPushButton#cancelChangeBtn { background-color: rgb(251, 72, 71); border: 0px; @@ -335,7 +331,7 @@ QPushButton#cancelChangeBtn { } QPushButton#nextButton:hover, QPushButton#playButton:hover, QPushButton#clearHistoryButton:hover, -QPushButton#checkUpdateButton:hover, QPushButton#doTransferButton:hover, QPushButton#photoButton:hover, +QPushButton#doTransferButton:hover, QPushButton#photoButton:hover, QPushButton#takePhotoButton:hover, QPushButton#importButton:hover, QPushButton#existingPushButton:hover, QPushButton#newAccountButton:hover, QPushButton#previousButton:hover, QPushButton#exportButton:hover, QPushButton#cancelAddButton:hover, QPushButton#exportOnRingButton:hover, @@ -352,7 +348,7 @@ QPushButton#deleteButton:hover, QPushButton#deleteBanBtn:hover, QPushButton#canc } QPushButton#nextButton:pressed, QPushButton#playButton:pressed, QPushButton#clearHistoryButton:pressed, -QPushButton#checkUpdateButton:pressed, QPushButton#doTransferButton:pressed, QPushButton#photoButton:pressed, +QPushButton#doTransferButton:pressed, QPushButton#photoButton:pressed, QPushButton#takePhotoButton:pressed, QPushButton#importButton:pressed, QPushButton#existingPushButton:pressed, QPushButton#newAccountButton:pressed, QPushButton#previousButton:pressed, QPushButton#exportButton:pressed, QPushButton#cancelAddButton:pressed, QPushButton#exportOnRingButton:pressed, @@ -692,3 +688,18 @@ QLabel#accountIdLabel{ QLabel#accountAliasLabel{ font-weight: bold; } + +/* setAvatarDialog { */ +QPushButton#pictureButton:default, QPushButton#fileButton:default { + background-color: rgb(0, 192, 213,); +} + +QPushButton#pictureButton:checked, QPushButton#fileButton:checked { + background-color: rgb(0, 0, 213); +} +/* } setAvatarDialog */ + + +/* SettingsWidget { */ + +/* } SettingsWidget */ \ No newline at end of file diff --git a/utils.cpp b/utils.cpp index 870da11..ad5a1b3 100644 --- a/utils.cpp +++ b/utils.cpp @@ -129,7 +129,6 @@ Utils::GetRingtonePath() { QString ringtonePath = QString::fromWCharArray(workingDirectory); ringtonePath += QStringLiteral("\\ringtones\\default.wav"); - return ringtonePath; #else return QString("/usr/local"); -- GitLab