added PageSettingsAbout, PageSettingsApplication, PageSettingsBackup, PageSettingsConnection, PageSettingsDns
- added SettingsController
This commit is contained in:
parent
be7386f0d7
commit
7b14ad9616
28 changed files with 1054 additions and 63 deletions
|
@ -98,6 +98,10 @@ void AmneziaApplication::init()
|
|||
new ExportController(m_serversModel, m_containersModel, m_settings, m_configurator));
|
||||
m_engine->rootContext()->setContextProperty("ExportController", m_exportController.get());
|
||||
|
||||
m_settingsController.reset(
|
||||
new SettingsController(m_serversModel, m_containersModel, m_settings));
|
||||
m_engine->rootContext()->setContextProperty("SettingsController", m_settingsController.get());
|
||||
|
||||
//
|
||||
|
||||
m_engine->load(url);
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
#include "ui/controllers/importController.h"
|
||||
#include "ui/controllers/installController.h"
|
||||
#include "ui/controllers/pageController.h"
|
||||
#include "ui/controllers/settingsController.h"
|
||||
#include "ui/models/containers_model.h"
|
||||
#include "ui/models/servers_model.h"
|
||||
|
||||
|
@ -73,6 +74,7 @@ private:
|
|||
QScopedPointer<InstallController> m_installController;
|
||||
QScopedPointer<ImportController> m_importController;
|
||||
QScopedPointer<ExportController> m_exportController;
|
||||
QScopedPointer<SettingsController> m_settingsController;
|
||||
};
|
||||
|
||||
#endif // AMNEZIA_APPLICATION_H
|
||||
|
|
5
client/images/controls/delete.svg
Normal file
5
client/images/controls/delete.svg
Normal file
|
@ -0,0 +1,5 @@
|
|||
<svg width="25" height="24" viewBox="0 0 25 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M20.332 5H9.33203L2.33203 12L9.33203 19H20.332C20.8625 19 21.3712 18.7893 21.7462 18.4142C22.1213 18.0391 22.332 17.5304 22.332 17V7C22.332 6.46957 22.1213 5.96086 21.7462 5.58579C21.3712 5.21071 20.8625 5 20.332 5V5Z" stroke="#D7D8DB" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<path d="M18.332 9L12.332 15" stroke="#D7D8DB" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<path d="M12.332 9L18.332 15" stroke="#D7D8DB" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
</svg>
|
After Width: | Height: | Size: 640 B |
4
client/images/controls/github.svg
Normal file
4
client/images/controls/github.svg
Normal file
|
@ -0,0 +1,4 @@
|
|||
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M15 22V18C15.1392 16.7473 14.78 15.4901 14 14.5C17 14.5 20 12.5 20 9C20.08 7.75 19.73 6.52 19 5.5C19.28 4.35 19.28 3.15 19 2C19 2 18 2 16 3.5C13.36 3 10.64 3 8.00004 3.5C6.00004 2 5.00004 2 5.00004 2C4.70004 3.15 4.70004 4.35 5.00004 5.5C4.27191 6.51588 3.91851 7.75279 4.00004 9C4.00004 12.5 7.00004 14.5 10 14.5C9.61004 14.99 9.32004 15.55 9.15004 16.15C8.98004 16.75 8.93004 17.38 9.00004 18V22" stroke="#CBCBCB" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<path d="M9 18C4.49 20 4 16 2 16" stroke="#CBCBCB" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
</svg>
|
After Width: | Height: | Size: 711 B |
4
client/images/controls/mail.svg
Normal file
4
client/images/controls/mail.svg
Normal file
|
@ -0,0 +1,4 @@
|
|||
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M20 4H4C2.89543 4 2 4.89543 2 6V18C2 19.1046 2.89543 20 4 20H20C21.1046 20 22 19.1046 22 18V6C22 4.89543 21.1046 4 20 4Z" stroke="#CBCBCB" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<path d="M22 7L13.03 12.7C12.7213 12.8934 12.3643 12.996 12 12.996C11.6357 12.996 11.2787 12.8934 10.97 12.7L2 7" stroke="#CBCBCB" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
</svg>
|
After Width: | Height: | Size: 514 B |
3
client/images/controls/telegram.svg
Normal file
3
client/images/controls/telegram.svg
Normal file
|
@ -0,0 +1,3 @@
|
|||
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M11.944 3.26667e-05C8.77112 0.0148396 5.73324 1.28566 3.4949 3.53449C1.25656 5.78332 -3.4549e-05 8.82711 7.12435e-10 12C7.12441e-10 15.1826 1.26428 18.2349 3.51472 20.4853C5.76515 22.7358 8.8174 24 12 24C15.1826 24 18.2348 22.7358 20.4853 20.4853C22.7357 18.2349 24 15.1826 24 12C24 8.81743 22.7357 5.76519 20.4853 3.51475C18.2348 1.26431 15.1826 3.26667e-05 12 3.26667e-05C11.9813 -1.08889e-05 11.9627 -1.08889e-05 11.944 3.26667e-05ZM16.906 7.22403C17.006 7.22203 17.227 7.24703 17.371 7.36403C17.4667 7.44713 17.5277 7.56311 17.542 7.68903C17.558 7.78203 17.578 7.99503 17.562 8.16103C17.382 10.059 16.6 14.663 16.202 16.788C16.034 17.688 15.703 17.989 15.382 18.018C14.686 18.083 14.157 17.558 13.482 17.116C12.426 16.423 11.829 15.992 10.804 15.316C9.619 14.536 10.387 14.106 11.062 13.406C11.239 13.222 14.309 10.429 14.369 10.176C14.376 10.144 14.383 10.026 14.313 9.96403C14.243 9.90203 14.139 9.92303 14.064 9.94003C13.958 9.96403 12.271 11.08 9.003 13.285C8.523 13.615 8.09 13.775 7.701 13.765C7.273 13.757 6.449 13.524 5.836 13.325C5.084 13.08 4.487 12.951 4.539 12.536C4.566 12.32 4.864 12.099 5.432 11.873C8.93 10.349 11.262 9.34403 12.43 8.85903C15.762 7.47303 16.455 7.23203 16.906 7.22403Z" fill="#D7D8DB"/>
|
||||
</svg>
|
After Width: | Height: | Size: 1.3 KiB |
|
@ -259,5 +259,14 @@
|
|||
<file>images/controls/radio-button-pressed.svg</file>
|
||||
<file>images/controls/radio-button-inner-circle-pressed.png</file>
|
||||
<file>ui/qml/Components/ShareConnectionDrawer.qml</file>
|
||||
<file>ui/qml/Pages2/PageSettingsConnection.qml</file>
|
||||
<file>ui/qml/Pages2/PageSettingsDns.qml</file>
|
||||
<file>ui/qml/Pages2/PageSettingsApplication.qml</file>
|
||||
<file>ui/qml/Pages2/PageSettingsBackup.qml</file>
|
||||
<file>images/controls/delete.svg</file>
|
||||
<file>ui/qml/Pages2/PageSettingsAbout.qml</file>
|
||||
<file>images/controls/github.svg</file>
|
||||
<file>images/controls/mail.svg</file>
|
||||
<file>images/controls/telegram.svg</file>
|
||||
</qresource>
|
||||
</RCC>
|
||||
|
|
|
@ -11,6 +11,8 @@
|
|||
|
||||
#include "qrcodegen.hpp"
|
||||
|
||||
#include "core/errorstrings.h"
|
||||
|
||||
ExportController::ExportController(const QSharedPointer<ServersModel> &serversModel,
|
||||
const QSharedPointer<ContainersModel> &containersModel,
|
||||
const std::shared_ptr<Settings> &settings,
|
||||
|
@ -35,6 +37,7 @@ void ExportController::generateFullAccessConfig()
|
|||
| QByteArray::OmitTrailingEquals)));
|
||||
|
||||
m_qrCodes = generateQrCodeImageSeries(compressedConfig);
|
||||
emit exportConfigChanged();
|
||||
}
|
||||
|
||||
void ExportController::generateConnectionConfig()
|
||||
|
@ -49,25 +52,25 @@ void ExportController::generateConnectionConfig()
|
|||
m_containersModel->data(containerModelIndex, ContainersModel::Roles::ConfigRole));
|
||||
containerConfig.insert(config_key::container, ContainerProps::containerToString(container));
|
||||
|
||||
ErrorCode e = ErrorCode::NoError;
|
||||
for (Proto p : ContainerProps::protocolsForContainer(container)) {
|
||||
QJsonObject protoConfig = m_settings->protocolConfig(serverIndex, container, p);
|
||||
ErrorCode errorCode = ErrorCode::NoError;
|
||||
for (Proto protocol : ContainerProps::protocolsForContainer(container)) {
|
||||
QJsonObject protocolConfig = m_settings->protocolConfig(serverIndex, container, protocol);
|
||||
|
||||
QString cfg = m_configurator->genVpnProtocolConfig(credentials,
|
||||
QString vpnConfig = m_configurator->genVpnProtocolConfig(credentials,
|
||||
container,
|
||||
containerConfig,
|
||||
p,
|
||||
&e);
|
||||
if (e) {
|
||||
cfg = "Error generating config";
|
||||
break;
|
||||
protocol,
|
||||
&errorCode);
|
||||
if (errorCode) {
|
||||
emit exportErrorOccurred(errorString(errorCode));
|
||||
return;
|
||||
}
|
||||
protoConfig.insert(config_key::last_config, cfg);
|
||||
containerConfig.insert(ProtocolProps::protoToString(p), protoConfig);
|
||||
protocolConfig.insert(config_key::last_config, vpnConfig);
|
||||
containerConfig.insert(ProtocolProps::protoToString(protocol), protocolConfig);
|
||||
}
|
||||
|
||||
QJsonObject config = m_settings->server(serverIndex);
|
||||
if (!e) {
|
||||
if (!errorCode) {
|
||||
config.remove(config_key::userName);
|
||||
config.remove(config_key::password);
|
||||
config.remove(config_key::port);
|
||||
|
@ -77,11 +80,8 @@ void ExportController::generateConnectionConfig()
|
|||
auto dns = m_configurator->getDnsForConfig(serverIndex);
|
||||
config.insert(config_key::dns1, dns.first);
|
||||
config.insert(config_key::dns2, dns.second);
|
||||
}
|
||||
|
||||
} /*else {
|
||||
set_textEditShareAmneziaCodeText(tr("Error while generating connection profile"));
|
||||
return;
|
||||
}*/
|
||||
QByteArray compressedConfig = QJsonDocument(config).toJson();
|
||||
compressedConfig = qCompress(compressedConfig, 8);
|
||||
m_amneziaCode = QString("vpn://%1")
|
||||
|
@ -89,6 +89,7 @@ void ExportController::generateConnectionConfig()
|
|||
| QByteArray::OmitTrailingEquals)));
|
||||
|
||||
m_qrCodes = generateQrCodeImageSeries(compressedConfig);
|
||||
emit exportConfigChanged();
|
||||
}
|
||||
|
||||
QString ExportController::getAmneziaCode()
|
||||
|
@ -154,3 +155,8 @@ QString ExportController::svgToBase64(const QString &image)
|
|||
{
|
||||
return "data:image/svg;base64," + QString::fromLatin1(image.toUtf8().toBase64().data());
|
||||
}
|
||||
|
||||
int ExportController::getQrCodesCount()
|
||||
{
|
||||
return m_qrCodes.size();
|
||||
}
|
||||
|
|
|
@ -17,9 +17,14 @@ public:
|
|||
const std::shared_ptr<VpnConfigurator> &configurator,
|
||||
QObject *parent = nullptr);
|
||||
|
||||
Q_PROPERTY(QList<QString> qrCodes READ getQrCodes NOTIFY exportConfigChanged)
|
||||
Q_PROPERTY(int qrCodesCount READ getQrCodesCount NOTIFY exportConfigChanged)
|
||||
Q_PROPERTY(QString amneziaCode READ getAmneziaCode NOTIFY exportConfigChanged)
|
||||
|
||||
public slots:
|
||||
void generateFullAccessConfig();
|
||||
void generateConnectionConfig();
|
||||
|
||||
QString getAmneziaCode();
|
||||
QList<QString> getQrCodes();
|
||||
|
||||
|
@ -27,11 +32,16 @@ public slots:
|
|||
|
||||
signals:
|
||||
void generateConfig(bool isFullAccess);
|
||||
void exportErrorOccurred(QString errorMessage);
|
||||
|
||||
void exportConfigChanged();
|
||||
|
||||
private:
|
||||
QList<QString> generateQrCodeImageSeries(const QByteArray &data);
|
||||
QString svgToBase64(const QString &image);
|
||||
|
||||
int getQrCodesCount();
|
||||
|
||||
QSharedPointer<ServersModel> m_serversModel;
|
||||
QSharedPointer<ContainersModel> m_containersModel;
|
||||
std::shared_ptr<Settings> m_settings;
|
||||
|
|
|
@ -22,6 +22,11 @@ namespace PageLoader
|
|||
PageSettingsServerProtocols,
|
||||
PageSettingsServerServices,
|
||||
PageSettingsServerProtocol,
|
||||
PageSettingsConnection,
|
||||
PageSettingsDns,
|
||||
PageSettingsApplication,
|
||||
PageSettingsBackup,
|
||||
PageSettingsAbout,
|
||||
|
||||
PageSetupWizardStart,
|
||||
PageSetupWizardCredentials,
|
||||
|
|
113
client/ui/controllers/settingsController.cpp
Normal file
113
client/ui/controllers/settingsController.cpp
Normal file
|
@ -0,0 +1,113 @@
|
|||
#include "settingsController.h"
|
||||
|
||||
#include <QStandardPaths>
|
||||
|
||||
#include "defines.h"
|
||||
#include "logger.h"
|
||||
#include "utilities.h"
|
||||
|
||||
SettingsController::SettingsController(const QSharedPointer<ServersModel> &serversModel,
|
||||
const QSharedPointer<ContainersModel> &containersModel,
|
||||
const std::shared_ptr<Settings> &settings,
|
||||
QObject *parent)
|
||||
: QObject(parent)
|
||||
, m_serversModel(serversModel)
|
||||
, m_containersModel(containersModel)
|
||||
, m_settings(settings)
|
||||
{
|
||||
m_appVersion = QString("%1: %2 (%3)")
|
||||
.arg(tr("Software version"), QString(APP_MAJOR_VERSION), __DATE__);
|
||||
}
|
||||
|
||||
void SettingsController::setAmneziaDns(bool enable)
|
||||
{
|
||||
m_settings->setUseAmneziaDns(enable);
|
||||
}
|
||||
|
||||
bool SettingsController::isAmneziaDnsEnabled()
|
||||
{
|
||||
return m_settings->useAmneziaDns();
|
||||
}
|
||||
|
||||
QString SettingsController::getPrimaryDns()
|
||||
{
|
||||
return m_settings->primaryDns();
|
||||
}
|
||||
|
||||
void SettingsController::setPrimaryDns(const QString &dns)
|
||||
{
|
||||
m_settings->setPrimaryDns(dns);
|
||||
emit primaryDnsChanged();
|
||||
}
|
||||
|
||||
QString SettingsController::getSecondaryDns()
|
||||
{
|
||||
return m_settings->secondaryDns();
|
||||
}
|
||||
|
||||
void SettingsController::setSecondaryDns(const QString &dns)
|
||||
{
|
||||
return m_settings->setSecondaryDns(dns);
|
||||
emit secondaryDnsChanged();
|
||||
}
|
||||
|
||||
bool SettingsController::isSaveLogsEnabled()
|
||||
{
|
||||
return m_settings->isSaveLogs();
|
||||
}
|
||||
|
||||
void SettingsController::setSaveLogs(bool enable)
|
||||
{
|
||||
m_settings->setSaveLogs(enable);
|
||||
}
|
||||
|
||||
void SettingsController::openLogsFolder()
|
||||
{
|
||||
Logger::openLogsFolder();
|
||||
}
|
||||
|
||||
void SettingsController::exportLogsFile()
|
||||
{
|
||||
Utils::saveFile(".log", tr("Save log"), "AmneziaVPN", Logger::getLogFile());
|
||||
}
|
||||
|
||||
void SettingsController::clearLogs()
|
||||
{
|
||||
Logger::clearLogs();
|
||||
Logger::clearServiceLogs();
|
||||
}
|
||||
|
||||
void SettingsController::backupAppConfig()
|
||||
{
|
||||
Utils::saveFile(".backup",
|
||||
tr("Backup application config"),
|
||||
"AmneziaVPN",
|
||||
m_settings->backupAppConfig());
|
||||
}
|
||||
|
||||
void SettingsController::restoreAppConfig()
|
||||
{
|
||||
QString fileName = Utils::getFileName(Q_NULLPTR,
|
||||
tr("Open backup"),
|
||||
QStandardPaths::writableLocation(
|
||||
QStandardPaths::DocumentsLocation),
|
||||
"*.backup");
|
||||
|
||||
//todo error processing
|
||||
if (fileName.isEmpty())
|
||||
return;
|
||||
|
||||
QFile file(fileName);
|
||||
file.open(QIODevice::ReadOnly);
|
||||
QByteArray data = file.readAll();
|
||||
|
||||
bool ok = m_settings->restoreAppConfig(data);
|
||||
if (ok) {
|
||||
// emit uiLogic()->showWarningMessage(tr("Can't import config, file is corrupted."));
|
||||
}
|
||||
}
|
||||
|
||||
QString SettingsController::getAppVersion()
|
||||
{
|
||||
return m_appVersion;
|
||||
}
|
56
client/ui/controllers/settingsController.h
Normal file
56
client/ui/controllers/settingsController.h
Normal file
|
@ -0,0 +1,56 @@
|
|||
#ifndef SETTINGSCONTROLLER_H
|
||||
#define SETTINGSCONTROLLER_H
|
||||
|
||||
#include <QObject>
|
||||
|
||||
#include "ui/models/containers_model.h"
|
||||
#include "ui/models/servers_model.h"
|
||||
|
||||
class SettingsController : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit SettingsController(const QSharedPointer<ServersModel> &serversModel,
|
||||
const QSharedPointer<ContainersModel> &containersModel,
|
||||
const std::shared_ptr<Settings> &settings,
|
||||
QObject *parent = nullptr);
|
||||
|
||||
Q_PROPERTY(QString primaryDns READ getPrimaryDns WRITE setPrimaryDns NOTIFY primaryDnsChanged)
|
||||
Q_PROPERTY(
|
||||
QString secondaryDns READ getSecondaryDns WRITE setSecondaryDns NOTIFY secondaryDnsChanged)
|
||||
|
||||
public slots:
|
||||
void setAmneziaDns(bool enable);
|
||||
bool isAmneziaDnsEnabled();
|
||||
|
||||
QString getPrimaryDns();
|
||||
void setPrimaryDns(const QString &dns);
|
||||
|
||||
QString getSecondaryDns();
|
||||
void setSecondaryDns(const QString &dns);
|
||||
|
||||
bool isSaveLogsEnabled();
|
||||
void setSaveLogs(bool enable);
|
||||
|
||||
void openLogsFolder();
|
||||
void exportLogsFile();
|
||||
void clearLogs();
|
||||
|
||||
void backupAppConfig();
|
||||
void restoreAppConfig();
|
||||
|
||||
QString getAppVersion();
|
||||
|
||||
signals:
|
||||
void primaryDnsChanged();
|
||||
void secondaryDnsChanged();
|
||||
|
||||
private:
|
||||
QSharedPointer<ServersModel> m_serversModel;
|
||||
QSharedPointer<ContainersModel> m_containersModel;
|
||||
std::shared_ptr<Settings> m_settings;
|
||||
|
||||
QString m_appVersion;
|
||||
};
|
||||
|
||||
#endif // SETTINGSCONTROLLER_H
|
|
@ -59,8 +59,6 @@ Item {
|
|||
Layout.fillWidth: true
|
||||
implicitHeight: 74
|
||||
|
||||
rootButtonBorderWidth: 0
|
||||
|
||||
descriptionText: qsTr("Hash")
|
||||
headerText: qsTr("Hash")
|
||||
|
||||
|
@ -97,8 +95,6 @@ Item {
|
|||
Layout.fillWidth: true
|
||||
implicitHeight: 74
|
||||
|
||||
rootButtonBorderWidth: 0
|
||||
|
||||
descriptionText: qsTr("Cipher")
|
||||
headerText: qsTr("Cipher")
|
||||
|
||||
|
|
|
@ -15,8 +15,6 @@ import "../Controls2/TextTypes"
|
|||
DrawerType {
|
||||
id: root
|
||||
|
||||
property var qrCodes: []
|
||||
property alias configText: configContent.text
|
||||
property alias headerText: header.headerText
|
||||
|
||||
width: parent.width
|
||||
|
@ -120,6 +118,8 @@ DrawerType {
|
|||
font.weight: Font.Medium
|
||||
font.family: "PT Root UI VF"
|
||||
|
||||
text: ExportController.amneziaCode
|
||||
|
||||
wrapMode: Text.Wrap
|
||||
|
||||
enabled: false
|
||||
|
@ -135,6 +135,8 @@ DrawerType {
|
|||
Layout.preferredHeight: width
|
||||
Layout.topMargin: 20
|
||||
|
||||
visible: ExportController.qrCodesCount > 0
|
||||
|
||||
color: "white"
|
||||
|
||||
Image {
|
||||
|
@ -144,22 +146,20 @@ DrawerType {
|
|||
Timer {
|
||||
property int idx: 0
|
||||
interval: 1000
|
||||
running: qrCodes.length > 0
|
||||
running: ExportController.qrCodesCount > 0
|
||||
repeat: true
|
||||
onTriggered: {
|
||||
idx++
|
||||
if (idx >= qrCodes.length) {
|
||||
if (idx >= ExportController.qrCodesCount) {
|
||||
idx = 0
|
||||
}
|
||||
parent.source = qrCodes[idx]
|
||||
parent.source = ExportController.qrCodes[idx]
|
||||
}
|
||||
}
|
||||
|
||||
Behavior on source {
|
||||
PropertyAnimation { duration: 200 }
|
||||
}
|
||||
|
||||
visible: qrCodes.length > 0
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -15,13 +15,15 @@ Item {
|
|||
property string headerText
|
||||
property string headerBackButtonImage
|
||||
|
||||
property var onRootButtonClicked
|
||||
property var rootButtonClickedFunction
|
||||
property string rootButtonImage: "qrc:/images/controls/chevron-down.svg"
|
||||
property string rootButtonImageColor: "#494B50"
|
||||
property string rootButtonDefaultColor: "#1C1D21"
|
||||
property string rootButtonImageColor: "#D7D8DB"
|
||||
property string rootButtonBackgroundColor: "#1C1D21"
|
||||
property int rootButtonMaximumWidth: 0
|
||||
|
||||
property string rootButtonBorderColor: "#494B50"
|
||||
property string rootButtonHoveredBorderColor: "#494B50"
|
||||
property string rootButtonDefaultBorderColor: "transparent"
|
||||
property string rootButtonPressedBorderColor: "#D7D8DB"
|
||||
property int rootButtonBorderWidth: 1
|
||||
|
||||
property real drawerHeight: 0.9
|
||||
|
@ -32,18 +34,31 @@ Item {
|
|||
implicitWidth: rootButtonContent.implicitWidth
|
||||
implicitHeight: rootButtonContent.implicitHeight
|
||||
|
||||
onMenuVisibleChanged: {
|
||||
if (menuVisible) {
|
||||
rootButtonBackground.border.color = rootButtonPressedBorderColor
|
||||
rootButtonBackground.border.width = rootButtonBorderWidth
|
||||
} else {
|
||||
rootButtonBackground.border.color = rootButtonDefaultBorderColor
|
||||
rootButtonBackground.border.width = 0
|
||||
}
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
id: rootButtonBackground
|
||||
anchors.fill: rootButtonContent
|
||||
|
||||
radius: 16
|
||||
color: rootButtonDefaultColor
|
||||
border.color: rootButtonBorderColor
|
||||
border.width: rootButtonBorderWidth
|
||||
color: rootButtonBackgroundColor
|
||||
border.color: rootButtonDefaultBorderColor
|
||||
border.width: 0
|
||||
|
||||
Behavior on border.width {
|
||||
PropertyAnimation { duration: 200 }
|
||||
}
|
||||
Behavior on border.color {
|
||||
PropertyAnimation { duration: 200 }
|
||||
}
|
||||
}
|
||||
|
||||
RowLayout {
|
||||
|
@ -83,7 +98,6 @@ Item {
|
|||
}
|
||||
}
|
||||
|
||||
//todo change to image type
|
||||
ImageButtonType {
|
||||
Layout.leftMargin: 4
|
||||
Layout.rightMargin: 16
|
||||
|
@ -100,16 +114,22 @@ Item {
|
|||
hoverEnabled: true
|
||||
|
||||
onEntered: {
|
||||
if (menu.visible === false) {
|
||||
rootButtonBackground.border.width = rootButtonBorderWidth
|
||||
rootButtonBackground.border.color = rootButtonHoveredBorderColor
|
||||
}
|
||||
}
|
||||
|
||||
onExited: {
|
||||
if (menu.visible === false) {
|
||||
rootButtonBackground.border.width = 0
|
||||
rootButtonBackground.border.color = rootButtonDefaultBorderColor
|
||||
}
|
||||
}
|
||||
|
||||
onClicked: {
|
||||
if (onRootButtonClicked && typeof onRootButtonClicked === "function") {
|
||||
onRootButtonClicked()
|
||||
if (rootButtonClickedFunction && typeof rootButtonClickedFunction === "function") {
|
||||
rootButtonClickedFunction()
|
||||
} else {
|
||||
menu.visible = true
|
||||
}
|
||||
|
|
|
@ -10,8 +10,10 @@ Button {
|
|||
property string hoveredColor: Qt.rgba(1, 1, 1, 0.08)
|
||||
property string defaultColor: "transparent"
|
||||
property string pressedColor: Qt.rgba(1, 1, 1, 0.12)
|
||||
property string disableColor: "#2C2D30"
|
||||
|
||||
property string imageColor: "#878B91"
|
||||
property string disableImageColor: "#2C2D30"
|
||||
|
||||
implicitWidth: 40
|
||||
implicitHeight: 40
|
||||
|
@ -19,7 +21,11 @@ Button {
|
|||
hoverEnabled: true
|
||||
|
||||
icon.source: image
|
||||
icon.color: imageColor
|
||||
icon.color: root.enabled ? imageColor : disableImageColor
|
||||
|
||||
Behavior on icon.color {
|
||||
PropertyAnimation { duration: 200 }
|
||||
}
|
||||
|
||||
background: Rectangle {
|
||||
id: background
|
||||
|
@ -33,6 +39,7 @@ Button {
|
|||
}
|
||||
return hovered ? hoveredColor : defaultColor
|
||||
}
|
||||
return defaultColor
|
||||
}
|
||||
Behavior on color {
|
||||
PropertyAnimation { duration: 200 }
|
||||
|
|
|
@ -2,9 +2,13 @@ import QtQuick
|
|||
import QtQuick.Controls
|
||||
import QtQuick.Layouts
|
||||
|
||||
import "TextTypes"
|
||||
|
||||
Switch {
|
||||
id: root
|
||||
|
||||
property alias descriptionText: description.text
|
||||
|
||||
property string checkedIndicatorColor: "#412102"
|
||||
property string defaultIndicatorColor: "transparent"
|
||||
property string checkedIndicatorBorderColor: "#412102"
|
||||
|
@ -16,10 +20,18 @@ Switch {
|
|||
property string hoveredIndicatorBackgroundColor: Qt.rgba(1, 1, 1, 0.08)
|
||||
property string defaultIndicatorBackgroundColor: "transparent"
|
||||
|
||||
implicitWidth: content.implicitWidth + switcher.implicitWidth
|
||||
implicitHeight: content.implicitHeight
|
||||
|
||||
indicator: Rectangle {
|
||||
id: switcher
|
||||
|
||||
anchors.left: content.right
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
|
||||
implicitWidth: 52
|
||||
implicitHeight: 32
|
||||
x: content.width - width
|
||||
|
||||
radius: 16
|
||||
color: root.checked ? checkedIndicatorColor : defaultIndicatorColor
|
||||
border.color: root.checked ? checkedIndicatorBorderColor : defaultIndicatorBorderColor
|
||||
|
@ -62,16 +74,23 @@ Switch {
|
|||
contentItem: ColumnLayout {
|
||||
id: content
|
||||
|
||||
Text {
|
||||
text: root.text
|
||||
color: "#D7D8DB"
|
||||
font.pixelSize: 18
|
||||
font.weight: 400
|
||||
font.family: "PT Root UI VF"
|
||||
anchors.fill: parent
|
||||
anchors.rightMargin: switcher.implicitWidth
|
||||
|
||||
height: 22
|
||||
ListItemTitleType {
|
||||
Layout.fillWidth: true
|
||||
Layout.bottomMargin: 16
|
||||
|
||||
text: root.text
|
||||
}
|
||||
|
||||
CaptionTextType {
|
||||
id: description
|
||||
|
||||
Layout.fillWidth: true
|
||||
|
||||
color: "#878B91"
|
||||
|
||||
visible: text !== ""
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -145,14 +145,14 @@ PageType {
|
|||
rootButtonBorderWidth: 0
|
||||
rootButtonImageColor: "#0E0E11"
|
||||
rootButtonMaximumWidth: 150 //todo make it dynamic
|
||||
rootButtonDefaultColor: "#D7D8DB"
|
||||
rootButtonBackgroundColor: "#D7D8DB"
|
||||
|
||||
text: root.currentContainerName
|
||||
textColor: "#0E0E11"
|
||||
headerText: qsTr("Протокол подключения")
|
||||
headerBackButtonImage: "qrc:/images/controls/arrow-left.svg"
|
||||
|
||||
onRootButtonClicked: function() {
|
||||
rootButtonClickedFunction: function() {
|
||||
ServersModel.setCurrentlyProcessedServerIndex(serversMenuContent.currentIndex)
|
||||
ContainersModel.setCurrentlyProcessedServerIndex(serversMenuContent.currentIndex)
|
||||
containersDropDown.menuVisible = true
|
||||
|
|
|
@ -58,6 +58,7 @@ PageType {
|
|||
iconImage: "qrc:/images/controls/radio.svg"
|
||||
|
||||
clickedFunction: function() {
|
||||
goToPage(PageEnum.PageSettingsConnection)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -71,6 +72,7 @@ PageType {
|
|||
iconImage: "qrc:/images/controls/app.svg"
|
||||
|
||||
clickedFunction: function() {
|
||||
goToPage(PageEnum.PageSettingsApplication)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -84,6 +86,7 @@ PageType {
|
|||
iconImage: "qrc:/images/controls/save.svg"
|
||||
|
||||
clickedFunction: function() {
|
||||
goToPage(PageEnum.PageSettingsBackup)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -97,6 +100,7 @@ PageType {
|
|||
iconImage: "qrc:/images/controls/amnezia.svg"
|
||||
|
||||
clickedFunction: function() {
|
||||
goToPage(PageEnum.PageSettingsAbout)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
207
client/ui/qml/Pages2/PageSettingsAbout.qml
Normal file
207
client/ui/qml/Pages2/PageSettingsAbout.qml
Normal file
|
@ -0,0 +1,207 @@
|
|||
import QtQuick
|
||||
import QtQuick.Controls
|
||||
import QtQuick.Layouts
|
||||
|
||||
import PageEnum 1.0
|
||||
|
||||
import "./"
|
||||
import "../Controls2"
|
||||
import "../Config"
|
||||
import "../Controls2/TextTypes"
|
||||
import "../Components"
|
||||
|
||||
PageType {
|
||||
id: root
|
||||
|
||||
BackButtonType {
|
||||
id: backButton
|
||||
|
||||
anchors.top: parent.top
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
anchors.rightMargin: 16
|
||||
anchors.leftMargin: 16
|
||||
anchors.topMargin: 20
|
||||
}
|
||||
|
||||
FlickableType {
|
||||
id: fl
|
||||
anchors.top: backButton.bottom
|
||||
anchors.bottom: root.bottom
|
||||
contentHeight: content.height
|
||||
|
||||
ColumnLayout {
|
||||
id: content
|
||||
|
||||
anchors.top: parent.top
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
|
||||
Image {
|
||||
id: image
|
||||
source: "qrc:/images/amneziaBigLogo.png"
|
||||
|
||||
Layout.alignment: Qt.AlignCenter
|
||||
Layout.topMargin: 16
|
||||
Layout.leftMargin: 16
|
||||
Layout.rightMargin: 16
|
||||
Layout.preferredWidth: 344
|
||||
Layout.preferredHeight: 279
|
||||
}
|
||||
|
||||
Header2TextType {
|
||||
Layout.fillWidth: true
|
||||
Layout.topMargin: 16
|
||||
Layout.leftMargin: 16
|
||||
Layout.rightMargin: 16
|
||||
|
||||
text: qsTr("Support the project with a donation")
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
}
|
||||
|
||||
ParagraphTextType {
|
||||
Layout.fillWidth: true
|
||||
Layout.topMargin: 16
|
||||
Layout.leftMargin: 16
|
||||
Layout.rightMargin: 16
|
||||
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
|
||||
height: 20
|
||||
font.pixelSize: 14
|
||||
|
||||
text: qsTr("This is a free and open source application. If you like it, support the developers with a donation.
|
||||
And if you don't like the app, all the more support it - the donation will be used to improve the app.")
|
||||
color: "#CCCAC8"
|
||||
}
|
||||
|
||||
BasicButtonType {
|
||||
Layout.fillWidth: true
|
||||
Layout.topMargin: 24
|
||||
Layout.leftMargin: 16
|
||||
Layout.rightMargin: 16
|
||||
|
||||
text: qsTr("Card on Patreon")
|
||||
|
||||
onClicked: {
|
||||
}
|
||||
}
|
||||
|
||||
BasicButtonType {
|
||||
Layout.fillWidth: true
|
||||
Layout.topMargin: 8
|
||||
Layout.leftMargin: 16
|
||||
Layout.rightMargin: 16
|
||||
|
||||
defaultColor: "transparent"
|
||||
hoveredColor: Qt.rgba(1, 1, 1, 0.08)
|
||||
pressedColor: Qt.rgba(1, 1, 1, 0.12)
|
||||
disabledColor: "#878B91"
|
||||
textColor: "#D7D8DB"
|
||||
borderWidth: 1
|
||||
|
||||
text: qsTr("Show other methods on Github")
|
||||
|
||||
onClicked: {
|
||||
}
|
||||
}
|
||||
|
||||
ParagraphTextType {
|
||||
Layout.fillWidth: true
|
||||
Layout.topMargin: 32
|
||||
Layout.leftMargin: 16
|
||||
Layout.rightMargin: 16
|
||||
|
||||
text: qsTr("Contacts")
|
||||
}
|
||||
|
||||
LabelWithButtonType {
|
||||
Layout.fillWidth: true
|
||||
Layout.topMargin: 16
|
||||
|
||||
text: qsTr("Telegram group")
|
||||
descriptionText: qsTr("To discuss features")
|
||||
buttonImage: "qrc:/images/controls/chevron-right.svg"
|
||||
iconImage: "qrc:/images/controls/telegram.svg"
|
||||
|
||||
clickedFunction: function() {
|
||||
goToPage(PageEnum.PageSettingsAbout)
|
||||
}
|
||||
}
|
||||
|
||||
DividerType {}
|
||||
|
||||
LabelWithButtonType {
|
||||
Layout.fillWidth: true
|
||||
|
||||
text: qsTr("Mail")
|
||||
descriptionText: qsTr("For reviews and bug reports")
|
||||
buttonImage: "qrc:/images/controls/chevron-right.svg"
|
||||
iconImage: "qrc:/images/controls/mail.svg"
|
||||
|
||||
clickedFunction: function() {
|
||||
goToPage(PageEnum.PageSettingsAbout)
|
||||
}
|
||||
}
|
||||
|
||||
DividerType {}
|
||||
|
||||
LabelWithButtonType {
|
||||
Layout.fillWidth: true
|
||||
|
||||
text: qsTr("Github")
|
||||
buttonImage: "qrc:/images/controls/chevron-right.svg"
|
||||
iconImage: "qrc:/images/controls/github.svg"
|
||||
|
||||
clickedFunction: function() {
|
||||
goToPage(PageEnum.PageSettingsAbout)
|
||||
}
|
||||
}
|
||||
|
||||
DividerType {}
|
||||
|
||||
LabelWithButtonType {
|
||||
Layout.fillWidth: true
|
||||
|
||||
text: qsTr("Website")
|
||||
buttonImage: "qrc:/images/controls/chevron-right.svg"
|
||||
iconImage: "qrc:/images/controls/amnezia.svg"
|
||||
|
||||
clickedFunction: function() {
|
||||
goToPage(PageEnum.PageSettingsAbout)
|
||||
}
|
||||
}
|
||||
|
||||
DividerType {}
|
||||
|
||||
CaptionTextType {
|
||||
Layout.fillWidth: true
|
||||
Layout.topMargin: 40
|
||||
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
|
||||
text: SettingsController.getAppVersion()
|
||||
color: "#878B91"
|
||||
}
|
||||
|
||||
BasicButtonType {
|
||||
Layout.alignment: Qt.AlignHCenter
|
||||
Layout.topMargin: 8
|
||||
Layout.bottomMargin: 16
|
||||
implicitHeight: 32
|
||||
|
||||
defaultColor: "transparent"
|
||||
hoveredColor: Qt.rgba(1, 1, 1, 0.08)
|
||||
pressedColor: Qt.rgba(1, 1, 1, 0.12)
|
||||
disabledColor: "#878B91"
|
||||
textColor: "#FBB26A"
|
||||
|
||||
text: qsTr("Check for updates")
|
||||
|
||||
onClicked: {
|
||||
Qt.openUrlExternally("https://github.com/amnezia-vpn/desktop-client/releases/latest")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
74
client/ui/qml/Pages2/PageSettingsApplication.qml
Normal file
74
client/ui/qml/Pages2/PageSettingsApplication.qml
Normal file
|
@ -0,0 +1,74 @@
|
|||
import QtQuick
|
||||
import QtQuick.Controls
|
||||
import QtQuick.Layouts
|
||||
|
||||
import PageEnum 1.0
|
||||
|
||||
import "./"
|
||||
import "../Controls2"
|
||||
import "../Config"
|
||||
import "../Controls2/TextTypes"
|
||||
|
||||
PageType {
|
||||
id: root
|
||||
|
||||
BackButtonType {
|
||||
id: backButton
|
||||
|
||||
anchors.top: parent.top
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
anchors.rightMargin: 16
|
||||
anchors.leftMargin: 16
|
||||
anchors.topMargin: 20
|
||||
}
|
||||
|
||||
FlickableType {
|
||||
id: fl
|
||||
anchors.top: backButton.bottom
|
||||
anchors.bottom: root.bottom
|
||||
contentHeight: content.height
|
||||
|
||||
ColumnLayout {
|
||||
id: content
|
||||
|
||||
anchors.top: parent.top
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
anchors.leftMargin: 16
|
||||
anchors.rightMargin: 16
|
||||
|
||||
spacing: 16
|
||||
|
||||
HeaderType {
|
||||
Layout.fillWidth: true
|
||||
|
||||
headerText: qsTr("Application")
|
||||
}
|
||||
|
||||
LabelWithButtonType {
|
||||
Layout.fillWidth: true
|
||||
|
||||
text: qsTr("Language")
|
||||
buttonImage: "qrc:/images/controls/chevron-right.svg"
|
||||
|
||||
clickedFunction: function() {
|
||||
}
|
||||
}
|
||||
|
||||
DividerType {}
|
||||
|
||||
LabelWithButtonType {
|
||||
Layout.fillWidth: true
|
||||
|
||||
text: qsTr("Reset settings and remove all data from the application")
|
||||
buttonImage: "qrc:/images/controls/chevron-right.svg"
|
||||
|
||||
clickedFunction: function() {
|
||||
}
|
||||
}
|
||||
|
||||
DividerType {}
|
||||
}
|
||||
}
|
||||
}
|
184
client/ui/qml/Pages2/PageSettingsBackup.qml
Normal file
184
client/ui/qml/Pages2/PageSettingsBackup.qml
Normal file
|
@ -0,0 +1,184 @@
|
|||
import QtQuick
|
||||
import QtQuick.Controls
|
||||
import QtQuick.Layouts
|
||||
|
||||
import PageEnum 1.0
|
||||
|
||||
import "./"
|
||||
import "../Controls2"
|
||||
import "../Config"
|
||||
import "../Controls2/TextTypes"
|
||||
|
||||
PageType {
|
||||
id: root
|
||||
|
||||
BackButtonType {
|
||||
id: backButton
|
||||
|
||||
anchors.top: parent.top
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
anchors.rightMargin: 16
|
||||
anchors.leftMargin: 16
|
||||
anchors.topMargin: 20
|
||||
}
|
||||
|
||||
FlickableType {
|
||||
id: fl
|
||||
anchors.top: backButton.bottom
|
||||
anchors.bottom: root.bottom
|
||||
contentHeight: content.height
|
||||
|
||||
ColumnLayout {
|
||||
id: content
|
||||
|
||||
anchors.top: parent.top
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
anchors.leftMargin: 16
|
||||
anchors.rightMargin: 16
|
||||
|
||||
spacing: 16
|
||||
|
||||
HeaderType {
|
||||
Layout.fillWidth: true
|
||||
|
||||
headerText: qsTr("Backup")
|
||||
}
|
||||
|
||||
SwitcherType {
|
||||
Layout.fillWidth: true
|
||||
Layout.topMargin: 16
|
||||
|
||||
text: qsTr("Save logs")
|
||||
|
||||
checked: SettingsController.isSaveLogsEnabled()
|
||||
onCheckedChanged: {
|
||||
if (checked !== SettingsController.isSaveLogsEnabled()) {
|
||||
SettingsController.setSaveLogs(checked)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
RowLayout {
|
||||
Layout.fillWidth: true
|
||||
|
||||
ColumnLayout {
|
||||
Layout.alignment: Qt.AlignBaseline
|
||||
Layout.preferredWidth: root.width / 3
|
||||
|
||||
ImageButtonType {
|
||||
Layout.alignment: Qt.AlignHCenter
|
||||
|
||||
implicitWidth: 56
|
||||
implicitHeight: 56
|
||||
|
||||
image: "qrc:/images/controls/folder-open.svg"
|
||||
|
||||
onClicked: SettingsController.openLogsFolder()
|
||||
}
|
||||
|
||||
CaptionTextType {
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
Layout.fillWidth: true
|
||||
|
||||
text: qsTr("Open folder with logs")
|
||||
color: "#D7D8DB"
|
||||
}
|
||||
}
|
||||
|
||||
ColumnLayout {
|
||||
Layout.alignment: Qt.AlignBaseline
|
||||
Layout.preferredWidth: root.width / 3
|
||||
|
||||
ImageButtonType {
|
||||
Layout.alignment: Qt.AlignHCenter
|
||||
|
||||
implicitWidth: 56
|
||||
implicitHeight: 56
|
||||
|
||||
image: "qrc:/images/controls/save.svg"
|
||||
|
||||
onClicked: SettingsController.exportLogsFile()
|
||||
}
|
||||
|
||||
CaptionTextType {
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
Layout.fillWidth: true
|
||||
|
||||
text: qsTr("Save logs to file")
|
||||
color: "#D7D8DB"
|
||||
}
|
||||
}
|
||||
|
||||
ColumnLayout {
|
||||
Layout.alignment: Qt.AlignBaseline
|
||||
Layout.preferredWidth: root.width / 3
|
||||
|
||||
ImageButtonType {
|
||||
Layout.alignment: Qt.AlignHCenter
|
||||
|
||||
implicitWidth: 56
|
||||
implicitHeight: 56
|
||||
|
||||
image: "qrc:/images/controls/delete.svg"
|
||||
|
||||
onClicked: SettingsController.clearLogs()
|
||||
}
|
||||
|
||||
CaptionTextType {
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
Layout.fillWidth: true
|
||||
|
||||
text: qsTr("Clear logs")
|
||||
color: "#D7D8DB"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ListItemTitleType {
|
||||
Layout.fillWidth: true
|
||||
Layout.topMargin: 10
|
||||
|
||||
text: qsTr("Configuration backup")
|
||||
}
|
||||
|
||||
CaptionTextType {
|
||||
Layout.fillWidth: true
|
||||
Layout.topMargin: -12
|
||||
|
||||
text: qsTr("It will help you instantly restore connection settings at the next installation")
|
||||
color: "#878B91"
|
||||
}
|
||||
|
||||
BasicButtonType {
|
||||
Layout.fillWidth: true
|
||||
Layout.topMargin: 14
|
||||
|
||||
text: qsTr("Make a backup")
|
||||
|
||||
onClicked: {
|
||||
SettingsController.backupAppConfig()
|
||||
}
|
||||
}
|
||||
|
||||
BasicButtonType {
|
||||
Layout.fillWidth: true
|
||||
Layout.topMargin: -8
|
||||
|
||||
defaultColor: "transparent"
|
||||
hoveredColor: Qt.rgba(1, 1, 1, 0.08)
|
||||
pressedColor: Qt.rgba(1, 1, 1, 0.12)
|
||||
disabledColor: "#878B91"
|
||||
textColor: "#D7D8DB"
|
||||
borderWidth: 1
|
||||
|
||||
text: qsTr("Restore from backup")
|
||||
|
||||
onClicked: {
|
||||
SettingsController.restoreAppConfig()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
107
client/ui/qml/Pages2/PageSettingsConnection.qml
Normal file
107
client/ui/qml/Pages2/PageSettingsConnection.qml
Normal file
|
@ -0,0 +1,107 @@
|
|||
import QtQuick
|
||||
import QtQuick.Controls
|
||||
import QtQuick.Layouts
|
||||
|
||||
import PageEnum 1.0
|
||||
|
||||
import "./"
|
||||
import "../Controls2"
|
||||
import "../Config"
|
||||
|
||||
PageType {
|
||||
id: root
|
||||
|
||||
BackButtonType {
|
||||
id: backButton
|
||||
|
||||
anchors.top: parent.top
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
anchors.rightMargin: 16
|
||||
anchors.leftMargin: 16
|
||||
anchors.topMargin: 20
|
||||
}
|
||||
|
||||
FlickableType {
|
||||
id: fl
|
||||
anchors.top: backButton.bottom
|
||||
anchors.bottom: root.bottom
|
||||
contentHeight: content.height
|
||||
|
||||
ColumnLayout {
|
||||
id: content
|
||||
|
||||
anchors.top: parent.top
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
|
||||
spacing: 16
|
||||
|
||||
HeaderType {
|
||||
Layout.fillWidth: true
|
||||
Layout.leftMargin: 16
|
||||
Layout.rightMargin: 16
|
||||
|
||||
headerText: qsTr("Connection")
|
||||
}
|
||||
|
||||
SwitcherType {
|
||||
Layout.fillWidth: true
|
||||
Layout.leftMargin: 16
|
||||
Layout.rightMargin: 16
|
||||
|
||||
text: qsTr("Use AmnesiaDNS if installed on the server")
|
||||
descriptionText: qsTr("Internal IP address 172.29.172.254")
|
||||
|
||||
checked: SettingsController.isAmneziaDnsEnabled()
|
||||
onCheckedChanged: {
|
||||
if (checked !== SettingsController.isAmneziaDnsEnabled()) {
|
||||
SettingsController.setAmneziaDns(checked)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
DividerType {}
|
||||
|
||||
LabelWithButtonType {
|
||||
Layout.fillWidth: true
|
||||
|
||||
text: qsTr("DNS servers")
|
||||
descriptionText: qsTr("If AmneziaDNS is not used or installed")
|
||||
buttonImage: "qrc:/images/controls/chevron-right.svg"
|
||||
|
||||
clickedFunction: function() {
|
||||
goToPage(PageEnum.PageSettingsDns)
|
||||
}
|
||||
}
|
||||
|
||||
DividerType {}
|
||||
|
||||
LabelWithButtonType {
|
||||
Layout.fillWidth: true
|
||||
|
||||
text: qsTr("Split site tunneling")
|
||||
descriptionText: qsTr("Allows you to connect to some sites through a secure connection, and to others bypassing it")
|
||||
buttonImage: "qrc:/images/controls/chevron-right.svg"
|
||||
|
||||
clickedFunction: function() {
|
||||
}
|
||||
}
|
||||
|
||||
DividerType {}
|
||||
|
||||
LabelWithButtonType {
|
||||
Layout.fillWidth: true
|
||||
|
||||
text: qsTr("Separate application tunneling")
|
||||
descriptionText: qsTr("Allows you to use the VPN only for certain applications")
|
||||
buttonImage: "qrc:/images/controls/chevron-right.svg"
|
||||
|
||||
clickedFunction: function() {
|
||||
}
|
||||
}
|
||||
|
||||
DividerType {}
|
||||
}
|
||||
}
|
||||
}
|
87
client/ui/qml/Pages2/PageSettingsDns.qml
Normal file
87
client/ui/qml/Pages2/PageSettingsDns.qml
Normal file
|
@ -0,0 +1,87 @@
|
|||
import QtQuick
|
||||
import QtQuick.Controls
|
||||
import QtQuick.Layouts
|
||||
|
||||
import PageEnum 1.0
|
||||
|
||||
import "./"
|
||||
import "../Controls2"
|
||||
import "../Config"
|
||||
import "../Controls2/TextTypes"
|
||||
|
||||
PageType {
|
||||
id: root
|
||||
|
||||
BackButtonType {
|
||||
id: backButton
|
||||
|
||||
anchors.top: parent.top
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
anchors.rightMargin: 16
|
||||
anchors.leftMargin: 16
|
||||
anchors.topMargin: 20
|
||||
}
|
||||
|
||||
FlickableType {
|
||||
id: fl
|
||||
anchors.top: backButton.bottom
|
||||
anchors.bottom: root.bottom
|
||||
contentHeight: content.height
|
||||
|
||||
ColumnLayout {
|
||||
id: content
|
||||
|
||||
anchors.top: parent.top
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
anchors.leftMargin: 16
|
||||
anchors.rightMargin: 16
|
||||
|
||||
spacing: 16
|
||||
|
||||
HeaderType {
|
||||
Layout.fillWidth: true
|
||||
|
||||
headerText: qsTr("DNS servers")
|
||||
}
|
||||
|
||||
ParagraphTextType {
|
||||
text: qsTr("If AmneziaDNS is not used or installed")
|
||||
}
|
||||
|
||||
TextFieldWithHeaderType {
|
||||
id: primaryDns
|
||||
|
||||
Layout.fillWidth: true
|
||||
headerText: "Primary DNS"
|
||||
|
||||
textFieldText: SettingsController.primaryDns
|
||||
}
|
||||
|
||||
TextFieldWithHeaderType {
|
||||
id: secondaryDns
|
||||
|
||||
Layout.fillWidth: true
|
||||
headerText: "Secondary DNS"
|
||||
|
||||
textFieldText: SettingsController.secondaryDns
|
||||
}
|
||||
|
||||
BasicButtonType {
|
||||
Layout.fillWidth: true
|
||||
|
||||
text: qsTr("Save")
|
||||
|
||||
onClicked: function() {
|
||||
if (primaryDns.textFieldText !== SettingsController.primaryDns) {
|
||||
SettingsController.primaryDns = primaryDns.textFieldText
|
||||
}
|
||||
if (secondaryDns.textFieldText !== SettingsController.secondaryDns) {
|
||||
SettingsController.secondaryDns = secondaryDns.textFieldText
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -25,9 +25,6 @@ PageType {
|
|||
} else {
|
||||
ExportController.generateConnectionConfig()
|
||||
}
|
||||
|
||||
shareConnectionDrawer.configText = ExportController.getAmneziaCode()
|
||||
shareConnectionDrawer.qrCodes = ExportController.getQrCodes()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -125,7 +122,8 @@ PageType {
|
|||
ParagraphTextType {
|
||||
Layout.fillWidth: true
|
||||
|
||||
text: qsTr("VPN access without the ability to manage the server")
|
||||
text: accessTypeSelector.currentIndex === 0 ? qsTr("VPN access without the ability to manage the server") :
|
||||
qsTr("Full access to server")
|
||||
color: "#878B91"
|
||||
}
|
||||
|
||||
|
@ -137,7 +135,6 @@ PageType {
|
|||
|
||||
implicitHeight: 74
|
||||
|
||||
rootButtonBorderWidth: 0
|
||||
drawerHeight: 0.4375
|
||||
|
||||
descriptionText: qsTr("Server and service")
|
||||
|
@ -234,6 +231,7 @@ PageType {
|
|||
clickedFunction: function () {
|
||||
serverSelector.text += ", " + selectedText
|
||||
shareConnectionDrawer.headerText = qsTr("Connection to ") + serverSelector.text
|
||||
ContainersModel.setCurrentlyProcessedContainerIndex(proxyContainersModel.mapToSource(currentIndex))
|
||||
|
||||
protocolSelector.visible = false
|
||||
serverSelector.menuVisible = false
|
||||
|
@ -244,6 +242,7 @@ PageType {
|
|||
Component.onCompleted: {
|
||||
serverSelector.text += ", " + selectedText
|
||||
shareConnectionDrawer.headerText = qsTr("Connection to ") + serverSelector.text
|
||||
ContainersModel.setCurrentlyProcessedContainerIndex(proxyContainersModel.mapToSource(currentIndex))
|
||||
|
||||
fillConnectionTypeModel()
|
||||
}
|
||||
|
@ -273,7 +272,6 @@ PageType {
|
|||
|
||||
implicitHeight: 74
|
||||
|
||||
rootButtonBorderWidth: 0
|
||||
drawerHeight: 0.4375
|
||||
|
||||
visible: accessTypeSelector.currentIndex === 0
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
#include <QCoreApplication>
|
||||
#include <QDebug>
|
||||
#include <QDesktopServices>
|
||||
#include <QDir>
|
||||
#include <QHostAddress>
|
||||
#include <QHostInfo>
|
||||
|
@ -7,6 +8,7 @@
|
|||
#include <QRandomGenerator>
|
||||
#include <QRegularExpression>
|
||||
#include <QStandardPaths>
|
||||
#include <QUrl>
|
||||
|
||||
#include "defines.h"
|
||||
#include "utilities.h"
|
||||
|
@ -247,6 +249,58 @@ QString Utils::certUtilPath()
|
|||
#endif
|
||||
}
|
||||
|
||||
void Utils::saveFile(const QString &fileExtension,
|
||||
const QString &caption,
|
||||
const QString &fileName,
|
||||
const QString &data)
|
||||
{
|
||||
QString docDir = QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation);
|
||||
QUrl fileUrl = QFileDialog::getSaveFileUrl(nullptr,
|
||||
caption,
|
||||
QUrl::fromLocalFile(docDir + "/" + fileName),
|
||||
"*" + fileExtension);
|
||||
if (fileUrl.isEmpty())
|
||||
return;
|
||||
if (!fileUrl.toString().endsWith(fileExtension)) {
|
||||
fileUrl = QUrl(fileUrl.toString() + fileExtension);
|
||||
}
|
||||
if (fileUrl.isEmpty())
|
||||
return;
|
||||
|
||||
QFile save(fileUrl.toLocalFile());
|
||||
|
||||
//todo check if save successful
|
||||
save.open(QIODevice::WriteOnly);
|
||||
save.write(data.toUtf8());
|
||||
save.close();
|
||||
|
||||
QFileInfo fi(fileUrl.toLocalFile());
|
||||
QDesktopServices::openUrl(fi.absoluteDir().absolutePath());
|
||||
}
|
||||
|
||||
QString Utils::getFileName(QWidget *parent,
|
||||
const QString &caption,
|
||||
const QString &dir,
|
||||
const QString &filter,
|
||||
QString *selectedFilter,
|
||||
QFileDialog::Options options)
|
||||
{
|
||||
QString fileName
|
||||
= QFileDialog::getOpenFileName(parent, caption, dir, filter, selectedFilter, options);
|
||||
|
||||
#ifdef Q_OS_ANDROID
|
||||
// patch for files containing spaces etc
|
||||
const QString sep{"raw%3A%2F"};
|
||||
if (fileName.startsWith("content://") && fileName.contains(sep)) {
|
||||
QString contentUrl = fileName.split(sep).at(0);
|
||||
QString rawUrl = fileName.split(sep).at(1);
|
||||
rawUrl.replace(" ", "%20");
|
||||
fileName = contentUrl + sep + rawUrl;
|
||||
}
|
||||
#endif
|
||||
return fileName;
|
||||
}
|
||||
|
||||
#ifdef Q_OS_WIN
|
||||
// Inspired from http://stackoverflow.com/a/15281070/1529139
|
||||
// and http://stackoverflow.com/q/40059902/1529139
|
||||
|
|
|
@ -1,9 +1,10 @@
|
|||
#ifndef UTILITIES_H
|
||||
#define UTILITIES_H
|
||||
|
||||
#include <QFileDialog>
|
||||
#include <QRegExp>
|
||||
#include <QString>
|
||||
#include <QRegularExpression>
|
||||
#include <QString>
|
||||
|
||||
#ifdef Q_OS_WIN
|
||||
#include "Windows.h"
|
||||
|
@ -50,6 +51,18 @@ public:
|
|||
static QString wireguardExecPath();
|
||||
static QString certUtilPath();
|
||||
|
||||
static void saveFile(const QString &fileExtension,
|
||||
const QString &caption,
|
||||
const QString &fileName,
|
||||
const QString &data);
|
||||
|
||||
static QString getFileName(QWidget *parent = nullptr,
|
||||
const QString &caption = QString(),
|
||||
const QString &dir = QString(),
|
||||
const QString &filter = QString(),
|
||||
QString *selectedFilter = nullptr,
|
||||
QFileDialog::Options options = QFileDialog::Options());
|
||||
|
||||
#ifdef Q_OS_WIN
|
||||
static bool signalCtrl(DWORD dwProcessId, DWORD dwCtrlEvent);
|
||||
#endif
|
||||
|
|
|
@ -6,7 +6,7 @@ project(${PROJECT})
|
|||
set(CMAKE_CXX_STANDARD 20)
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||
|
||||
find_package(Qt6 REQUIRED COMPONENTS Core Network RemoteObjects Core5Compat)
|
||||
find_package(Qt6 REQUIRED COMPONENTS Core Network RemoteObjects Core5Compat Widgets)
|
||||
qt_standard_project_setup()
|
||||
|
||||
set(HEADERS
|
||||
|
@ -89,14 +89,14 @@ include_directories(
|
|||
)
|
||||
|
||||
add_executable(${PROJECT} ${SOURCES} ${HEADERS})
|
||||
target_link_libraries(${PROJECT} PRIVATE Qt6::Core Qt6::Network Qt6::RemoteObjects Qt6::Core5Compat ${LIBS})
|
||||
target_link_libraries(${PROJECT} PRIVATE Qt6::Core Qt6::Network Qt6::RemoteObjects Qt6::Core5Compat Qt6::Widgets ${LIBS})
|
||||
|
||||
qt_add_repc_sources(${PROJECT} ${CMAKE_CURRENT_LIST_DIR}/../../ipc/ipc_interface.rep)
|
||||
if(NOT IOS)
|
||||
qt_add_repc_sources(${PROJECT} ${CMAKE_CURRENT_LIST_DIR}/../../ipc/ipc_process_interface.rep)
|
||||
endif()
|
||||
|
||||
# deploy artifacts required to run the application to the debug build folder
|
||||
# copy deploy artifacts required to run the application to the debug build folder
|
||||
if(WIN32)
|
||||
if("${CMAKE_SIZEOF_VOID_P}" STREQUAL "8")
|
||||
set(DEPLOY_ARTIFACT_PATH "windows/x64")
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue