mirror of
https://github.com/nextcloud/desktop.git
synced 2024-11-25 14:36:01 +03:00
Make use of bandwidth limiting, split general/network settings.
Fixes #14
This commit is contained in:
parent
a400a2e0bb
commit
bca295183b
15 changed files with 717 additions and 257 deletions
|
@ -11,6 +11,7 @@
|
|||
<file>resources/view-refresh.png</file>
|
||||
<file>resources/warning-16.png</file>
|
||||
<file>resources/settings.png</file>
|
||||
<file>resources/network.png</file>
|
||||
<file>resources/owncloud_logo_blue.png</file>
|
||||
</qresource>
|
||||
</RCC>
|
||||
|
|
BIN
resources/network.png
Normal file
BIN
resources/network.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.1 KiB |
|
@ -21,6 +21,7 @@ mirall/owncloudwizardresultpage.ui
|
|||
mirall/sslerrordialog.ui
|
||||
mirall/settingsdialog.ui
|
||||
mirall/generalsettings.ui
|
||||
mirall/networksettings.ui
|
||||
mirall/accountsettings.ui
|
||||
mirall/ignorelisteditor.ui
|
||||
mirall/fileitemdialog.ui
|
||||
|
@ -160,8 +161,9 @@ set(mirall_SRCS
|
|||
mirall/fileitemdialog.cpp
|
||||
mirall/settingsdialog.cpp
|
||||
mirall/generalsettings.cpp
|
||||
mirall/ignorelisteditor.cpp
|
||||
mirall/networksettings.cpp
|
||||
mirall/accountsettings.cpp
|
||||
mirall/ignorelisteditor.cpp
|
||||
)
|
||||
|
||||
set(mirall_HEADERS
|
||||
|
@ -177,6 +179,7 @@ set(mirall_HEADERS
|
|||
mirall/fileitemdialog.h
|
||||
mirall/settingsdialog.h
|
||||
mirall/generalsettings.h
|
||||
mirall/networksettings.h
|
||||
mirall/accountsettings.h
|
||||
mirall/ignorelisteditor.h
|
||||
)
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>639</width>
|
||||
<width>607</width>
|
||||
<height>385</height>
|
||||
</rect>
|
||||
</property>
|
||||
|
|
|
@ -315,6 +315,24 @@ void CSyncThread::startSync()
|
|||
// cleans up behind us and emits finished() to ease error handling
|
||||
CSyncRunScopeHelper helper(_csync_ctx, this);
|
||||
|
||||
// maybe move this somewhere else where it can influence a running sync?
|
||||
MirallConfigFile cfg;
|
||||
|
||||
int downloadLimit = 0;
|
||||
if (cfg.useDownloadLimit()) {
|
||||
downloadLimit = cfg.downloadLimit();
|
||||
}
|
||||
csync_set_module_property(_csync_ctx, "bandwidth_limit_download", &downloadLimit);
|
||||
|
||||
int uploadLimit = -75; // 75%
|
||||
int useDlLimit = cfg.useDownloadLimit();
|
||||
if ( useDlLimit > 1) {
|
||||
uploadLimit = cfg.downloadLimit();
|
||||
} else if (useDlLimit == 0) {
|
||||
uploadLimit = 0;
|
||||
}
|
||||
csync_set_module_property(_csync_ctx, "bandwidth_limit_upload", &uploadLimit);
|
||||
|
||||
csync_set_file_progress_callback( _csync_ctx, cb_file_progress );
|
||||
csync_set_overall_progress_callback( _csync_ctx, cb_overall_progress );
|
||||
|
||||
|
|
|
@ -30,15 +30,6 @@ GeneralSettings::GeneralSettings(QWidget *parent) :
|
|||
{
|
||||
_ui->setupUi(this);
|
||||
|
||||
_ui->hostLineEdit->setPlaceholderText(tr("Hostname of proxy server"));
|
||||
_ui->userLineEdit->setPlaceholderText(tr("Username for proxy server"));
|
||||
_ui->passwordLineEdit->setPlaceholderText(tr("Password for proxy server"));
|
||||
|
||||
_ui->typeComboBox->addItem(tr("HTTP(S) proxy"), QNetworkProxy::HttpProxy);
|
||||
_ui->typeComboBox->addItem(tr("SOCKS5 proxy"), QNetworkProxy::Socks5Proxy);
|
||||
|
||||
MirallConfigFile cfgFile;
|
||||
_ui->desktopNotificationsCheckBox->setChecked(cfgFile.optionalDesktopNotifications());
|
||||
connect(_ui->desktopNotificationsCheckBox, SIGNAL(toggled(bool)),
|
||||
SLOT(slotToggleOptionalDesktopNotifications(bool)));
|
||||
|
||||
|
@ -54,28 +45,10 @@ GeneralSettings::GeneralSettings(QWidget *parent) :
|
|||
_ui->aboutLabel->setOpenExternalLinks(true);
|
||||
}
|
||||
|
||||
_ui->authRequiredcheckBox->setEnabled(true);
|
||||
|
||||
connect(_ui->manualProxyRadioButton, SIGNAL(toggled(bool)),
|
||||
_ui->manualSettings, SLOT(setEnabled(bool)));
|
||||
connect(_ui->manualProxyRadioButton, SIGNAL(toggled(bool)),
|
||||
_ui->typeComboBox, SLOT(setEnabled(bool)));
|
||||
connect(_ui->authRequiredcheckBox, SIGNAL(toggled(bool)),
|
||||
_ui->authWidgets, SLOT(setEnabled(bool)));
|
||||
|
||||
loadProxySettings();
|
||||
loadMiscSettings();
|
||||
|
||||
// misc
|
||||
connect(_ui->monoIconsCheckBox, SIGNAL(toggled(bool)), SLOT(saveMiscSettings()));
|
||||
|
||||
// proxy
|
||||
connect(_ui->typeComboBox, SIGNAL(currentIndexChanged(int)), SLOT(saveProxySettings()));
|
||||
connect(_ui->proxyButtonGroup, SIGNAL(buttonClicked(int)), SLOT(saveProxySettings()));
|
||||
connect(_ui->hostLineEdit, SIGNAL(editingFinished()), SLOT(saveProxySettings()));
|
||||
connect(_ui->userLineEdit, SIGNAL(editingFinished()), SLOT(saveProxySettings()));
|
||||
connect(_ui->passwordLineEdit, SIGNAL(editingFinished()), SLOT(saveProxySettings()));
|
||||
connect(_ui->portSpinBox, SIGNAL(editingFinished()), SLOT(saveProxySettings()));
|
||||
}
|
||||
|
||||
GeneralSettings::~GeneralSettings()
|
||||
|
@ -83,44 +56,11 @@ GeneralSettings::~GeneralSettings()
|
|||
delete _ui;
|
||||
}
|
||||
|
||||
void GeneralSettings::loadProxySettings()
|
||||
{
|
||||
// load current proxy settings
|
||||
Mirall::MirallConfigFile cfgFile;
|
||||
int type = cfgFile.proxyType();
|
||||
switch (type) {
|
||||
case QNetworkProxy::NoProxy:
|
||||
_ui->noProxyRadioButton->setChecked(true);
|
||||
break;
|
||||
case QNetworkProxy::DefaultProxy:
|
||||
_ui->systemProxyRadioButton->setChecked(true);
|
||||
break;
|
||||
case QNetworkProxy::Socks5Proxy:
|
||||
case QNetworkProxy::HttpProxy:
|
||||
_ui->typeComboBox->setCurrentIndex(_ui->typeComboBox->findData(type));
|
||||
_ui->manualProxyRadioButton->setChecked(true);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
_ui->hostLineEdit->setText(cfgFile.proxyHostName());
|
||||
int port = cfgFile.proxyPort();
|
||||
if (port == 0)
|
||||
port = 8080;
|
||||
_ui->portSpinBox->setValue(port);
|
||||
if (!cfgFile.proxyUser().isEmpty())
|
||||
{
|
||||
_ui->authRequiredcheckBox->setChecked(true);
|
||||
_ui->userLineEdit->setText(cfgFile.proxyUser());
|
||||
_ui->passwordLineEdit->setText(cfgFile.proxyPassword());
|
||||
}
|
||||
}
|
||||
|
||||
void GeneralSettings::loadMiscSettings()
|
||||
{
|
||||
MirallConfigFile cfgFile;
|
||||
_ui->monoIconsCheckBox->setChecked(cfgFile.monoIcons());
|
||||
_ui->desktopNotificationsCheckBox->setChecked(cfgFile.optionalDesktopNotifications());
|
||||
}
|
||||
|
||||
void GeneralSettings::saveMiscSettings()
|
||||
|
@ -143,24 +83,4 @@ void GeneralSettings::slotToggleOptionalDesktopNotifications(bool enable)
|
|||
cfgFile.setOptionalDesktopNotifications(enable);
|
||||
}
|
||||
|
||||
void GeneralSettings::saveProxySettings()
|
||||
{
|
||||
MirallConfigFile cfgFile;
|
||||
|
||||
if (_ui->noProxyRadioButton->isChecked()){
|
||||
cfgFile.setProxyType(QNetworkProxy::NoProxy);
|
||||
} else if (_ui->systemProxyRadioButton->isChecked()){
|
||||
cfgFile.setProxyType(QNetworkProxy::DefaultProxy);
|
||||
} else if (_ui->manualProxyRadioButton->isChecked()) {
|
||||
int type = _ui->typeComboBox->itemData(_ui->typeComboBox->currentIndex()).toInt();
|
||||
bool needsAuth = _ui->authRequiredcheckBox->isChecked();
|
||||
QString user = _ui->userLineEdit->text();
|
||||
QString pass = _ui->passwordLineEdit->text();
|
||||
cfgFile.setProxyType(type, _ui->hostLineEdit->text(),
|
||||
_ui->portSpinBox->value(), needsAuth, user, pass);
|
||||
}
|
||||
|
||||
emit proxySettingsChanged();
|
||||
}
|
||||
|
||||
} // namespace Mirall
|
||||
|
|
|
@ -35,13 +35,11 @@ signals:
|
|||
void proxySettingsChanged();
|
||||
|
||||
private slots:
|
||||
void saveProxySettings();
|
||||
void saveMiscSettings();
|
||||
void slotToggleLaunchOnStartup(bool);
|
||||
void slotToggleOptionalDesktopNotifications(bool);
|
||||
|
||||
private:
|
||||
void loadProxySettings();
|
||||
void loadMiscSettings();
|
||||
|
||||
Ui::GeneralSettings *_ui;
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>468</width>
|
||||
<height>408</height>
|
||||
<height>169</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
|
@ -44,168 +44,6 @@
|
|||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="proxyGroupBox">
|
||||
<property name="enabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="title">
|
||||
<string>Proxy Settings</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<item row="0" column="0">
|
||||
<widget class="QRadioButton" name="noProxyRadioButton">
|
||||
<property name="text">
|
||||
<string>No Proxy</string>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<attribute name="buttonGroup">
|
||||
<string notr="true">proxyButtonGroup</string>
|
||||
</attribute>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QRadioButton" name="systemProxyRadioButton">
|
||||
<property name="text">
|
||||
<string>Use system proxy</string>
|
||||
</property>
|
||||
<attribute name="buttonGroup">
|
||||
<string notr="true">proxyButtonGroup</string>
|
||||
</attribute>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QRadioButton" name="manualProxyRadioButton">
|
||||
<property name="text">
|
||||
<string>Specify proxy manually as</string>
|
||||
</property>
|
||||
<attribute name="buttonGroup">
|
||||
<string notr="true">proxyButtonGroup</string>
|
||||
</attribute>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QComboBox" name="typeComboBox">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0" colspan="2">
|
||||
<widget class="QWidget" name="manualSettings" native="true">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<item>
|
||||
<widget class="QLabel" name="hostLabel">
|
||||
<property name="text">
|
||||
<string>Host</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLineEdit" name="hostLineEdit">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="text">
|
||||
<string>:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QSpinBox" name="portSpinBox">
|
||||
<property name="enabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Maximum" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>65535</number>
|
||||
</property>
|
||||
<property name="value">
|
||||
<number>8080</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="authRequiredcheckBox">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Proxy server requires authentication</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QWidget" name="authWidgets" native="true">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
||||
<property name="margin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QLineEdit" name="userLineEdit">
|
||||
<property name="enabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLineEdit" name="passwordLineEdit">
|
||||
<property name="enabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
<property name="echoMode">
|
||||
<enum>QLineEdit::Password</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="aboutGroupBox">
|
||||
<property name="title">
|
||||
|
|
|
@ -46,6 +46,11 @@ static const char proxyUserC[] = "Proxy/user";
|
|||
static const char proxyPassC[] = "Proxy/pass";
|
||||
static const char proxyNeedsAuthC[] = "Proxy/needsAuth";
|
||||
|
||||
static const char useUploadLimitC[] = "BWLimit/useUploadLimit";
|
||||
static const char useDownloadLimitC[] = "BWLimit/useDownloadLimit";
|
||||
static const char uploadLimitC[] = "BWLimit/uploadLimit";
|
||||
static const char downloadLimitC[] = "BWLimit/downloadLimit";
|
||||
|
||||
static const char seenVersionC[] = "Updater/seenVersion";
|
||||
static const char maxLogLinesC[] = "Logging/maxLogLines";
|
||||
|
||||
|
@ -556,14 +561,23 @@ void MirallConfigFile::setProxyType(int proxyType,
|
|||
settings.sync();
|
||||
}
|
||||
|
||||
QVariant MirallConfigFile::getValue(const QString& param, const QString& group) const
|
||||
QVariant MirallConfigFile::getValue(const QString& param, const QString& group,
|
||||
const QVariant& defaultValue) const
|
||||
{
|
||||
QSettings settings( configFile(), QSettings::IniFormat );
|
||||
settings.setIniCodec( "UTF-8" );
|
||||
if (!group.isEmpty())
|
||||
settings.beginGroup(group);
|
||||
|
||||
return settings.value(param);
|
||||
return settings.value(param, defaultValue);
|
||||
}
|
||||
|
||||
void MirallConfigFile::setValue(const QString& key, const QVariant &value)
|
||||
{
|
||||
QSettings settings( configFile(), QSettings::IniFormat );
|
||||
settings.setIniCodec( "UTF-8" );
|
||||
|
||||
settings.setValue(key, value);
|
||||
}
|
||||
|
||||
int MirallConfigFile::proxyType() const
|
||||
|
@ -597,6 +611,46 @@ QString MirallConfigFile::proxyPassword() const
|
|||
return QString::fromUtf8(QByteArray::fromBase64(pass));
|
||||
}
|
||||
|
||||
int MirallConfigFile::useUploadLimit() const
|
||||
{
|
||||
return getValue(useUploadLimitC, QString::null, -1).toInt();
|
||||
}
|
||||
|
||||
bool MirallConfigFile::useDownloadLimit() const
|
||||
{
|
||||
return getValue(useDownloadLimitC, QString::null, false).toBool();
|
||||
}
|
||||
|
||||
void MirallConfigFile::setUseUploadLimit(int val)
|
||||
{
|
||||
setValue(useUploadLimitC, val);
|
||||
}
|
||||
|
||||
void MirallConfigFile::setUseDownloadLimit(bool enable)
|
||||
{
|
||||
setValue(useDownloadLimitC, enable);
|
||||
}
|
||||
|
||||
int MirallConfigFile::uploadLimit() const
|
||||
{
|
||||
return getValue(uploadLimitC, QString::null, 10).toInt();
|
||||
}
|
||||
|
||||
int MirallConfigFile::downloadLimit() const
|
||||
{
|
||||
return getValue(downloadLimitC, QString::null, 80).toInt();
|
||||
}
|
||||
|
||||
void MirallConfigFile::setUploadLimit(int kbytes)
|
||||
{
|
||||
setValue(uploadLimitC, kbytes);
|
||||
}
|
||||
|
||||
void MirallConfigFile::setDownloadLimit(int kbytes)
|
||||
{
|
||||
setValue(downloadLimitC, kbytes);
|
||||
}
|
||||
|
||||
bool MirallConfigFile::monoIcons() const
|
||||
{
|
||||
QSettings settings( configFile(), QSettings::IniFormat );
|
||||
|
|
|
@ -16,8 +16,8 @@
|
|||
#define MIRALLCONFIGFILE_H
|
||||
|
||||
#include <QString>
|
||||
#include <QVariant>
|
||||
|
||||
class QVariant;
|
||||
class QWidget;
|
||||
|
||||
namespace Mirall {
|
||||
|
@ -95,6 +95,16 @@ public:
|
|||
QString proxyUser() const;
|
||||
QString proxyPassword() const;
|
||||
|
||||
/** 0: no limit, 1: manual, >0: automatic */
|
||||
int useUploadLimit() const;
|
||||
bool useDownloadLimit() const;
|
||||
void setUseUploadLimit(int);
|
||||
void setUseDownloadLimit(bool);
|
||||
int uploadLimit() const;
|
||||
int downloadLimit() const;
|
||||
void setUploadLimit(int kbytes);
|
||||
void setDownloadLimit(int kbytes);
|
||||
|
||||
static void setConfDir(const QString &value);
|
||||
|
||||
bool optionalDesktopNotifications() const;
|
||||
|
@ -114,15 +124,15 @@ protected:
|
|||
bool writePassword( const QString& passwd, const QString& connection = QString() );
|
||||
|
||||
private:
|
||||
QVariant getValue(const QString& param, const QString& group = QString::null) const;
|
||||
|
||||
QVariant getValue(const QString& param, const QString& group = QString::null,
|
||||
const QVariant& defaultValue = QVariant()) const;
|
||||
void setValue(const QString& key, const QVariant &value);
|
||||
|
||||
private:
|
||||
static bool _askedUser;
|
||||
static QString _oCVersion;
|
||||
static QString _confDir;
|
||||
QString _customHandle;
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
|
161
src/mirall/networksettings.cpp
Normal file
161
src/mirall/networksettings.cpp
Normal file
|
@ -0,0 +1,161 @@
|
|||
/*
|
||||
* Copyright (C) by Daniel Molkentin <danimo@owncloud.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; version 2 of the License.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "networksettings.h"
|
||||
#include "ui_networksettings.h"
|
||||
|
||||
#include "mirall/theme.h"
|
||||
#include "mirall/mirallconfigfile.h"
|
||||
#include "mirall/application.h"
|
||||
#include "mirall/utility.h"
|
||||
#include "mirall/mirallconfigfile.h"
|
||||
|
||||
#include <QNetworkProxy>
|
||||
|
||||
namespace Mirall {
|
||||
|
||||
NetworkSettings::NetworkSettings(QWidget *parent) :
|
||||
QWidget(parent),
|
||||
_ui(new Ui::NetworkSettings)
|
||||
{
|
||||
_ui->setupUi(this);
|
||||
|
||||
_ui->hostLineEdit->setPlaceholderText(tr("Hostname of proxy server"));
|
||||
_ui->userLineEdit->setPlaceholderText(tr("Username for proxy server"));
|
||||
_ui->passwordLineEdit->setPlaceholderText(tr("Password for proxy server"));
|
||||
|
||||
_ui->typeComboBox->addItem(tr("HTTP(S) proxy"), QNetworkProxy::HttpProxy);
|
||||
_ui->typeComboBox->addItem(tr("SOCKS5 proxy"), QNetworkProxy::Socks5Proxy);
|
||||
|
||||
_ui->authRequiredcheckBox->setEnabled(true);
|
||||
|
||||
connect(_ui->manualProxyRadioButton, SIGNAL(toggled(bool)),
|
||||
_ui->manualSettings, SLOT(setEnabled(bool)));
|
||||
connect(_ui->manualProxyRadioButton, SIGNAL(toggled(bool)),
|
||||
_ui->typeComboBox, SLOT(setEnabled(bool)));
|
||||
connect(_ui->authRequiredcheckBox, SIGNAL(toggled(bool)),
|
||||
_ui->authWidgets, SLOT(setEnabled(bool)));
|
||||
|
||||
loadProxySettings();
|
||||
loadBWLimitSettings();
|
||||
|
||||
// proxy
|
||||
connect(_ui->typeComboBox, SIGNAL(currentIndexChanged(int)), SLOT(saveProxySettings()));
|
||||
connect(_ui->proxyButtonGroup, SIGNAL(buttonClicked(int)), SLOT(saveProxySettings()));
|
||||
connect(_ui->hostLineEdit, SIGNAL(editingFinished()), SLOT(saveProxySettings()));
|
||||
connect(_ui->userLineEdit, SIGNAL(editingFinished()), SLOT(saveProxySettings()));
|
||||
connect(_ui->passwordLineEdit, SIGNAL(editingFinished()), SLOT(saveProxySettings()));
|
||||
connect(_ui->portSpinBox, SIGNAL(editingFinished()), SLOT(saveProxySettings()));
|
||||
|
||||
connect(_ui->uploadLimitRadioButton, SIGNAL(clicked()), SLOT(saveBWLimitSettings()));
|
||||
connect(_ui->noUploadLimitRadioButton, SIGNAL(clicked()), SLOT(saveBWLimitSettings()));
|
||||
connect(_ui->autoUploadLimitRadioButton, SIGNAL(clicked()), SLOT(saveBWLimitSettings()));
|
||||
connect(_ui->downloadLimitRadioButton, SIGNAL(clicked()), SLOT(saveBWLimitSettings()));
|
||||
connect(_ui->noDownloadLimitRadioButton, SIGNAL(clicked()), SLOT(saveBWLimitSettings()));
|
||||
connect(_ui->downloadSpinBox, SIGNAL(valueChanged(int)), SLOT(saveBWLimitSettings()));
|
||||
connect(_ui->uploadSpinBox, SIGNAL(valueChanged(int)), SLOT(saveBWLimitSettings()));
|
||||
}
|
||||
|
||||
NetworkSettings::~NetworkSettings()
|
||||
{
|
||||
delete _ui;
|
||||
}
|
||||
|
||||
void NetworkSettings::loadProxySettings()
|
||||
{
|
||||
// load current proxy settings
|
||||
Mirall::MirallConfigFile cfgFile;
|
||||
int type = cfgFile.proxyType();
|
||||
switch (type) {
|
||||
case QNetworkProxy::NoProxy:
|
||||
_ui->noProxyRadioButton->setChecked(true);
|
||||
break;
|
||||
case QNetworkProxy::DefaultProxy:
|
||||
_ui->systemProxyRadioButton->setChecked(true);
|
||||
break;
|
||||
case QNetworkProxy::Socks5Proxy:
|
||||
case QNetworkProxy::HttpProxy:
|
||||
_ui->typeComboBox->setCurrentIndex(_ui->typeComboBox->findData(type));
|
||||
_ui->manualProxyRadioButton->setChecked(true);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
_ui->hostLineEdit->setText(cfgFile.proxyHostName());
|
||||
int port = cfgFile.proxyPort();
|
||||
if (port == 0)
|
||||
port = 8080;
|
||||
_ui->portSpinBox->setValue(port);
|
||||
if (!cfgFile.proxyUser().isEmpty())
|
||||
{
|
||||
_ui->authRequiredcheckBox->setChecked(true);
|
||||
_ui->userLineEdit->setText(cfgFile.proxyUser());
|
||||
_ui->passwordLineEdit->setText(cfgFile.proxyPassword());
|
||||
}
|
||||
}
|
||||
|
||||
void NetworkSettings::loadBWLimitSettings()
|
||||
{
|
||||
MirallConfigFile cfgFile;
|
||||
_ui->downloadLimitRadioButton->setChecked(cfgFile.useDownloadLimit());
|
||||
int uploadLimit = cfgFile.useUploadLimit();
|
||||
if ( uploadLimit >= 1 ) {
|
||||
_ui->downloadLimitRadioButton->setChecked(true);
|
||||
} else if (uploadLimit == 0){
|
||||
_ui->noDownloadLimitRadioButton->setChecked(true);
|
||||
} else {
|
||||
_ui->autoUploadLimitRadioButton->setChecked(true);
|
||||
}
|
||||
_ui->downloadSpinBox->setValue(cfgFile.downloadLimit());
|
||||
_ui->uploadSpinBox->setValue(cfgFile.uploadLimit());
|
||||
}
|
||||
|
||||
void NetworkSettings::saveProxySettings()
|
||||
{
|
||||
MirallConfigFile cfgFile;
|
||||
|
||||
if (_ui->noProxyRadioButton->isChecked()){
|
||||
cfgFile.setProxyType(QNetworkProxy::NoProxy);
|
||||
} else if (_ui->systemProxyRadioButton->isChecked()){
|
||||
cfgFile.setProxyType(QNetworkProxy::DefaultProxy);
|
||||
} else if (_ui->manualProxyRadioButton->isChecked()) {
|
||||
int type = _ui->typeComboBox->itemData(_ui->typeComboBox->currentIndex()).toInt();
|
||||
bool needsAuth = _ui->authRequiredcheckBox->isChecked();
|
||||
QString user = _ui->userLineEdit->text();
|
||||
QString pass = _ui->passwordLineEdit->text();
|
||||
cfgFile.setProxyType(type, _ui->hostLineEdit->text(),
|
||||
_ui->portSpinBox->value(), needsAuth, user, pass);
|
||||
}
|
||||
|
||||
emit proxySettingsChanged();
|
||||
}
|
||||
|
||||
void NetworkSettings::saveBWLimitSettings()
|
||||
{
|
||||
MirallConfigFile cfgFile;
|
||||
cfgFile.setUseDownloadLimit(_ui->downloadLimitRadioButton->isChecked());
|
||||
|
||||
if (_ui->uploadLimitRadioButton->isChecked()) {
|
||||
cfgFile.setUseUploadLimit(1);
|
||||
} else if (_ui->noUploadLimitRadioButton->isChecked()) {
|
||||
cfgFile.setUseUploadLimit(0);
|
||||
} else if (_ui->autoUploadLimitRadioButton->isChecked()) {
|
||||
cfgFile.setUseUploadLimit(-1);
|
||||
}
|
||||
|
||||
cfgFile.setDownloadLimit(_ui->downloadSpinBox->value());
|
||||
cfgFile.setUploadLimit(_ui->uploadSpinBox->value());
|
||||
}
|
||||
|
||||
} // namespace Mirall
|
50
src/mirall/networksettings.h
Normal file
50
src/mirall/networksettings.h
Normal file
|
@ -0,0 +1,50 @@
|
|||
/*
|
||||
* Copyright (C) by Daniel Molkentin <danimo@owncloud.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; version 2 of the License.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef MIRALL_NETWORKSETTINGS_H
|
||||
#define MIRALL_NETWORKSETTINGS_H
|
||||
|
||||
#include <QWidget>
|
||||
|
||||
|
||||
namespace Mirall {
|
||||
|
||||
namespace Ui {
|
||||
class NetworkSettings;
|
||||
}
|
||||
|
||||
class NetworkSettings : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit NetworkSettings(QWidget *parent = 0);
|
||||
~NetworkSettings();
|
||||
|
||||
signals:
|
||||
void proxySettingsChanged();
|
||||
|
||||
private slots:
|
||||
void saveProxySettings();
|
||||
void saveBWLimitSettings();
|
||||
|
||||
private:
|
||||
void loadProxySettings();
|
||||
void loadBWLimitSettings();
|
||||
|
||||
Ui::NetworkSettings *_ui;
|
||||
};
|
||||
|
||||
|
||||
} // namespace Mirall
|
||||
#endif // MIRALL_NETWORKSETTINGS_H
|
399
src/mirall/networksettings.ui
Normal file
399
src/mirall/networksettings.ui
Normal file
|
@ -0,0 +1,399 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>Mirall::NetworkSettings</class>
|
||||
<widget class="QWidget" name="Mirall::NetworkSettings">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>558</width>
|
||||
<height>390</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Form</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_3">
|
||||
<item row="0" column="0" colspan="2">
|
||||
<widget class="QGroupBox" name="proxyGroupBox">
|
||||
<property name="enabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="title">
|
||||
<string>Proxy Settings</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<item row="0" column="0">
|
||||
<widget class="QRadioButton" name="noProxyRadioButton">
|
||||
<property name="text">
|
||||
<string>No Proxy</string>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<attribute name="buttonGroup">
|
||||
<string notr="true">proxyButtonGroup</string>
|
||||
</attribute>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QRadioButton" name="systemProxyRadioButton">
|
||||
<property name="text">
|
||||
<string>Use system proxy</string>
|
||||
</property>
|
||||
<attribute name="buttonGroup">
|
||||
<string notr="true">proxyButtonGroup</string>
|
||||
</attribute>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QRadioButton" name="manualProxyRadioButton">
|
||||
<property name="text">
|
||||
<string>Specify proxy manually as</string>
|
||||
</property>
|
||||
<attribute name="buttonGroup">
|
||||
<string notr="true">proxyButtonGroup</string>
|
||||
</attribute>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QComboBox" name="typeComboBox">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0" colspan="2">
|
||||
<widget class="QWidget" name="manualSettings" native="true">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<item>
|
||||
<widget class="QLabel" name="hostLabel">
|
||||
<property name="text">
|
||||
<string>Host</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLineEdit" name="hostLineEdit">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="text">
|
||||
<string>:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QSpinBox" name="portSpinBox">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Maximum" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>65535</number>
|
||||
</property>
|
||||
<property name="value">
|
||||
<number>8080</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="authRequiredcheckBox">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Proxy server requires authentication</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QWidget" name="authWidgets" native="true">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
||||
<property name="margin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QLineEdit" name="userLineEdit">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLineEdit" name="passwordLineEdit">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
<property name="echoMode">
|
||||
<enum>QLineEdit::Password</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QGroupBox" name="groupBox">
|
||||
<property name="title">
|
||||
<string>Download Bandwidth</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_2">
|
||||
<item row="2" column="0">
|
||||
<widget class="QRadioButton" name="downloadLimitRadioButton">
|
||||
<property name="text">
|
||||
<string>Limit to</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_3">
|
||||
<item>
|
||||
<widget class="QSpinBox" name="downloadSpinBox">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>9999</number>
|
||||
</property>
|
||||
<property name="value">
|
||||
<number>80</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="label_3">
|
||||
<property name="text">
|
||||
<string>KBytes/s</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="3" column="0" colspan="2">
|
||||
<spacer name="verticalSpacer_2">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>147</width>
|
||||
<height>25</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item row="0" column="0" colspan="2">
|
||||
<widget class="QRadioButton" name="noDownloadLimitRadioButton">
|
||||
<property name="text">
|
||||
<string>Do not Limit</string>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="2">
|
||||
<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>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QGroupBox" name="groupBox_2">
|
||||
<property name="title">
|
||||
<string>Upload Bandwidth</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_4">
|
||||
<item row="0" column="0" colspan="2">
|
||||
<widget class="QRadioButton" name="noUploadLimitRadioButton">
|
||||
<property name="text">
|
||||
<string>Do Not Limit</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0" colspan="2">
|
||||
<widget class="QRadioButton" name="autoUploadLimitRadioButton">
|
||||
<property name="text">
|
||||
<string>Automatically Limit</string>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QRadioButton" name="uploadLimitRadioButton">
|
||||
<property name="text">
|
||||
<string>Limit to</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_4">
|
||||
<item>
|
||||
<widget class="QSpinBox" name="uploadSpinBox">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>9999</number>
|
||||
</property>
|
||||
<property name="value">
|
||||
<number>10</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="label_4">
|
||||
<property name="text">
|
||||
<string>KBytes/s</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="2" column="2">
|
||||
<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 row="3" column="0" colspan="2">
|
||||
<spacer name="verticalSpacer_3">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>147</width>
|
||||
<height>6</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
<zorder>autoUploadLimitRadioButton</zorder>
|
||||
<zorder>uploadLimitRadioButton</zorder>
|
||||
<zorder>verticalSpacer_3</zorder>
|
||||
<zorder>horizontalSpacer_2</zorder>
|
||||
<zorder>noUploadLimitRadioButton</zorder>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<spacer name="verticalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections>
|
||||
<connection>
|
||||
<sender>downloadLimitRadioButton</sender>
|
||||
<signal>toggled(bool)</signal>
|
||||
<receiver>downloadSpinBox</receiver>
|
||||
<slot>setEnabled(bool)</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>73</x>
|
||||
<y>69</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>131</x>
|
||||
<y>78</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>uploadLimitRadioButton</sender>
|
||||
<signal>toggled(bool)</signal>
|
||||
<receiver>uploadSpinBox</receiver>
|
||||
<slot>setEnabled(bool)</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>322</x>
|
||||
<y>101</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>411</x>
|
||||
<y>106</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
</connections>
|
||||
<buttongroups>
|
||||
<buttongroup name="proxyButtonGroup"/>
|
||||
</buttongroups>
|
||||
</ui>
|
|
@ -17,6 +17,7 @@
|
|||
#include "mirall/folderman.h"
|
||||
#include "mirall/theme.h"
|
||||
#include "mirall/generalsettings.h"
|
||||
#include "mirall/networksettings.h"
|
||||
#include "mirall/accountsettings.h"
|
||||
#include "mirall/application.h"
|
||||
#include "mirall/mirallconfigfile.h"
|
||||
|
@ -52,10 +53,17 @@ SettingsDialog::SettingsDialog(Application *app, QWidget *parent) :
|
|||
general->setSizeHint(QSize(0, 32));
|
||||
_ui->labelWidget->addItem(general);
|
||||
GeneralSettings *generalSettings = new GeneralSettings;
|
||||
connect(generalSettings, SIGNAL(proxySettingsChanged()), app, SLOT(slotSetupProxy()));
|
||||
connect(generalSettings, SIGNAL(proxySettingsChanged()), FolderMan::instance(), SLOT(slotScheduleAllFolders()));
|
||||
_ui->stack->addWidget(generalSettings);
|
||||
|
||||
QIcon networkIcon(QLatin1String(":/mirall/resources/network.png"));
|
||||
QListWidgetItem *network = new QListWidgetItem(networkIcon, tr("Network"), _ui->labelWidget);
|
||||
network->setSizeHint(QSize(0, 32));
|
||||
_ui->labelWidget->addItem(network);
|
||||
NetworkSettings *networkSettings = new NetworkSettings;
|
||||
_ui->stack->addWidget(networkSettings);
|
||||
connect(networkSettings, SIGNAL(proxySettingsChanged()), app, SLOT(slotSetupProxy()));
|
||||
connect(networkSettings, SIGNAL(proxySettingsChanged()), FolderMan::instance(), SLOT(slotScheduleAllFolders()));
|
||||
|
||||
//connect(generalSettings, SIGNAL(resizeToSizeHint()), SLOT(resizeToSizeHint()));
|
||||
|
||||
_accountSettings = new AccountSettings(this);
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>704</width>
|
||||
<height>515</height>
|
||||
<height>299</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
|
|
Loading…
Reference in a new issue