added import of configs in .ovpn format

- on the "OpenVPN Settings" page, such a config will be displayed as raw text
This commit is contained in:
vladimir.kuznetsov 2022-11-01 23:12:42 +03:00
parent b62d0697be
commit 53d7a92a0d
15 changed files with 430 additions and 322 deletions

View file

@ -312,3 +312,10 @@ ServerCredentials Settings::serverCredentials(int index) const
return credentials; return credentials;
} }
bool Settings::isThirdPartyConfig(int serverIndex) const
{
if (serverIndex < 0) return false;
const QJsonObject &s = server(serverIndex);
return s.value("isThirdPartyConfig").toBool();
}

View file

@ -113,6 +113,8 @@ public:
QByteArray backupAppConfig() const { return m_settings.backupAppConfig(); } QByteArray backupAppConfig() const { return m_settings.backupAppConfig(); }
bool restoreAppConfig(const QByteArray &cfg) { return m_settings.restoreAppConfig(cfg); } bool restoreAppConfig(const QByteArray &cfg) { return m_settings.restoreAppConfig(cfg); }
bool isThirdPartyConfig(int serverIndex) const;
private: private:
SecureQSettings m_settings; SecureQSettings m_settings;

View file

@ -38,7 +38,8 @@ void ServerContainersLogic::onPushButtonProtoSettingsClicked(DockerContainer c,
uiLogic()->selectedDockerContainer = c; uiLogic()->selectedDockerContainer = c;
uiLogic()->protocolLogic(p)->updateProtocolPage(m_settings->protocolConfig(uiLogic()->selectedServerIndex, uiLogic()->selectedDockerContainer, p), uiLogic()->protocolLogic(p)->updateProtocolPage(m_settings->protocolConfig(uiLogic()->selectedServerIndex, uiLogic()->selectedDockerContainer, p),
uiLogic()->selectedDockerContainer, uiLogic()->selectedDockerContainer,
m_settings->haveAuthData(uiLogic()->selectedServerIndex)); m_settings->haveAuthData(uiLogic()->selectedServerIndex),
m_settings->isThirdPartyConfig(uiLogic()->selectedServerIndex));
emit uiLogic()->goToProtocolPage(p); emit uiLogic()->goToProtocolPage(p);
} }

View file

@ -15,6 +15,25 @@
#include "platforms/android/android_controller.h" #include "platforms/android/android_controller.h"
#endif #endif
namespace {
QString checkConfigFormat(const QString &config)
{
const QString openVpnConfigPatternCli = "client";
const QString openVpnConfigPatternProto1 = "proto tcp";
const QString openVpnConfigPatternProto2 = "proto udp";
const QString openVpnConfigPatternDriver1 = "dev tun";
const QString openVpnConfigPatternDriver2 = "dev tap";
if (config.contains(openVpnConfigPatternCli) &&
(config.contains(openVpnConfigPatternProto1) || config.contains(openVpnConfigPatternProto2)) &&
(config.contains(openVpnConfigPatternDriver1) || config.contains(openVpnConfigPatternDriver2))) {
return "OpenVpn";
}
return "Amnezia";
}
}
StartPageLogic::StartPageLogic(UiLogic *logic, QObject *parent): StartPageLogic::StartPageLogic(UiLogic *logic, QObject *parent):
PageLogicBase(logic, parent), PageLogicBase(logic, parent),
m_pushButtonConnectEnabled{true}, m_pushButtonConnectEnabled{true},
@ -136,7 +155,7 @@ void StartPageLogic::onPushButtonImport()
void StartPageLogic::onPushButtonImportOpenFile() void StartPageLogic::onPushButtonImportOpenFile()
{ {
QString fileName = QFileDialog::getOpenFileName(nullptr, tr("Open profile"), QString fileName = QFileDialog::getOpenFileName(nullptr, tr("Open profile"),
QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation), "*.vpn"); QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation), "*.vpn *.ovpn");
if (fileName.isEmpty()) return; if (fileName.isEmpty()) return;
@ -144,7 +163,12 @@ void StartPageLogic::onPushButtonImportOpenFile()
file.open(QIODevice::ReadOnly); file.open(QIODevice::ReadOnly);
QByteArray data = file.readAll(); QByteArray data = file.readAll();
importConnectionFromCode(QString(data)); auto configFormat = checkConfigFormat(QString(data));
if (configFormat == "OpenVpn") {
importConnectionFromOpenVpnConfig(QString(data));
} else {
importConnectionFromCode(QString(data));
}
} }
bool StartPageLogic::importConnection(const QJsonObject &profile) bool StartPageLogic::importConnection(const QJsonObject &profile)
@ -214,3 +238,44 @@ bool StartPageLogic::importConnectionFromQr(const QByteArray &data)
return false; return false;
} }
bool StartPageLogic::importConnectionFromOpenVpnConfig(const QString &config)
{
QJsonObject openVpnConfig;
openVpnConfig[config_key::config] = config;
QJsonObject lastConfig;
lastConfig[config_key::last_config] = QString(QJsonDocument(openVpnConfig).toJson());
QJsonObject containers;
containers.insert(config_key::container, QJsonValue("amnezia-openvpn"));
containers.insert("openvpn", QJsonValue(lastConfig));
QJsonArray arr;
arr.push_back(containers);
QJsonObject o;
o[config_key::containers] = arr;
o[config_key::defaultContainer] = "amnezia-openvpn";
o[config_key::description] = "OpenVpn server";
const static QRegularExpression dnsRegExp("dhcp-option DNS \\b\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\b");
QRegularExpressionMatchIterator dnsMatch = dnsRegExp.globalMatch(config);
if (dnsMatch.hasNext()) {
o[config_key::dns1] = dnsMatch.next().captured(0).split(" ").at(2);
}
if (dnsMatch.hasNext()) {
o[config_key::dns2] = dnsMatch.next().captured(0).split(" ").at(2);
}
const static QRegularExpression hostNameRegExp("remote \\b\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\b");
QRegularExpressionMatch hostNameMatch = hostNameRegExp.match(config);
if (hostNameMatch.hasMatch()) {
o[config_key::hostName] = hostNameMatch.captured(0).split(" ").at(1);
}
o["isThirdPartyConfig"] = true;
return importConnection(o);
}

View file

@ -32,6 +32,7 @@ public:
bool importConnection(const QJsonObject &profile); bool importConnection(const QJsonObject &profile);
bool importConnectionFromCode(QString code); bool importConnectionFromCode(QString code);
bool importConnectionFromQr(const QByteArray &data); bool importConnectionFromQr(const QByteArray &data);
bool importConnectionFromOpenVpnConfig(const QString &config);
public: public:
explicit StartPageLogic(UiLogic *uiLogic, QObject *parent = nullptr); explicit StartPageLogic(UiLogic *uiLogic, QObject *parent = nullptr);

View file

@ -23,7 +23,7 @@ CloakLogic::CloakLogic(UiLogic *logic, QObject *parent):
} }
void CloakLogic::updateProtocolPage(const QJsonObject &ckConfig, DockerContainer container, bool haveAuthData) void CloakLogic::updateProtocolPage(const QJsonObject &ckConfig, DockerContainer container, bool haveAuthData, bool isThirdPartyConfig)
{ {
set_pageEnabled(haveAuthData); set_pageEnabled(haveAuthData);
set_pushButtonSaveVisible(haveAuthData); set_pushButtonSaveVisible(haveAuthData);

View file

@ -28,7 +28,7 @@ public:
explicit CloakLogic(UiLogic *uiLogic, QObject *parent = nullptr); explicit CloakLogic(UiLogic *uiLogic, QObject *parent = nullptr);
~CloakLogic() = default; ~CloakLogic() = default;
void updateProtocolPage (const QJsonObject &ckConfig, DockerContainer container, bool haveAuthData) override; void updateProtocolPage(const QJsonObject &ckConfig, DockerContainer container, bool haveAuthData, bool isThirdPartyConfig) override;
QJsonObject getProtocolConfigFromPage(QJsonObject oldConfig) override; QJsonObject getProtocolConfigFromPage(QJsonObject oldConfig) override;
private: private:

View file

@ -35,7 +35,7 @@ OpenVpnLogic::OpenVpnLogic(UiLogic *logic, QObject *parent):
} }
void OpenVpnLogic::updateProtocolPage(const QJsonObject &openvpnConfig, DockerContainer container, bool haveAuthData) void OpenVpnLogic::updateProtocolPage(const QJsonObject &openvpnConfig, DockerContainer container, bool haveAuthData, bool isThirdPartyConfig)
{ {
qDebug() << "OpenVpnLogic::updateProtocolPage"; qDebug() << "OpenVpnLogic::updateProtocolPage";
set_pageEnabled(haveAuthData); set_pageEnabled(haveAuthData);
@ -87,6 +87,16 @@ void OpenVpnLogic::updateProtocolPage(const QJsonObject &openvpnConfig, DockerCo
toString(protocols::openvpn::defaultPort)); toString(protocols::openvpn::defaultPort));
set_lineEditPortEnabled(container == DockerContainer::OpenVpn); set_lineEditPortEnabled(container == DockerContainer::OpenVpn);
auto lastConfig = openvpnConfig.value(config_key::last_config).toString();
auto lastConfigJson = QJsonDocument::fromJson(lastConfig.toUtf8()).object();
QStringList lines = lastConfigJson.value(config_key::config).toString().replace("\r", "").split("\n");
for (const QString &l: lines) {
m_openVpnLastConfigText.append(l + "\n");
}
emit openVpnLastConfigTextChanged(m_openVpnLastConfigText);
set_isThirdPartyConfig(isThirdPartyConfig);
} }
void OpenVpnLogic::onPushButtonProtoOpenVpnSaveClicked() void OpenVpnLogic::onPushButtonProtoOpenVpnSaveClicked()

View file

@ -35,6 +35,9 @@ class OpenVpnLogic : public PageProtocolLogicBase
AUTO_PROPERTY(int, progressBarResetValue) AUTO_PROPERTY(int, progressBarResetValue)
AUTO_PROPERTY(int, progressBarResetMaximium) AUTO_PROPERTY(int, progressBarResetMaximium)
AUTO_PROPERTY(QString, openVpnLastConfigText)
AUTO_PROPERTY(bool, isThirdPartyConfig)
public: public:
Q_INVOKABLE void onPushButtonProtoOpenVpnSaveClicked(); Q_INVOKABLE void onPushButtonProtoOpenVpnSaveClicked();
@ -42,7 +45,7 @@ public:
explicit OpenVpnLogic(UiLogic *uiLogic, QObject *parent = nullptr); explicit OpenVpnLogic(UiLogic *uiLogic, QObject *parent = nullptr);
~OpenVpnLogic() = default; ~OpenVpnLogic() = default;
void updateProtocolPage(const QJsonObject &openvpnConfig, DockerContainer container, bool haveAuthData) override; void updateProtocolPage(const QJsonObject &openvpnConfig, DockerContainer container, bool haveAuthData, bool isThirdPartyConfig) override;
QJsonObject getProtocolConfigFromPage(QJsonObject oldConfig) override; QJsonObject getProtocolConfigFromPage(QJsonObject oldConfig) override;
private: private:

View file

@ -36,7 +36,7 @@ OtherProtocolsLogic::~OtherProtocolsLogic()
#endif #endif
} }
void OtherProtocolsLogic::updateProtocolPage(const QJsonObject &config, DockerContainer container, bool haveAuthData) void OtherProtocolsLogic::updateProtocolPage(const QJsonObject &config, DockerContainer container, bool haveAuthData, bool isThirdPartyConfig)
{ {
set_labelTftpUserNameText(config.value(config_key::userName).toString()); set_labelTftpUserNameText(config.value(config_key::userName).toString());
set_labelTftpPasswordText(config.value(config_key::password).toString(protocols::sftp::defaultUserName)); set_labelTftpPasswordText(config.value(config_key::password).toString(protocols::sftp::defaultUserName));

View file

@ -27,7 +27,7 @@ public:
explicit OtherProtocolsLogic(UiLogic *uiLogic, QObject *parent = nullptr); explicit OtherProtocolsLogic(UiLogic *uiLogic, QObject *parent = nullptr);
~OtherProtocolsLogic(); ~OtherProtocolsLogic();
void updateProtocolPage(const QJsonObject &config, DockerContainer container, bool haveAuthData) override; void updateProtocolPage(const QJsonObject &config, DockerContainer container, bool haveAuthData, bool isThirdPartyConfig) override;
//QJsonObject getProtocolConfigFromPage(QJsonObject oldConfig) override; //QJsonObject getProtocolConfigFromPage(QJsonObject oldConfig) override;
private: private:

View file

@ -17,7 +17,7 @@ public:
explicit PageProtocolLogicBase(UiLogic *uiLogic, QObject *parent = nullptr); explicit PageProtocolLogicBase(UiLogic *uiLogic, QObject *parent = nullptr);
~PageProtocolLogicBase() = default; ~PageProtocolLogicBase() = default;
virtual void updateProtocolPage(const QJsonObject &config, DockerContainer container, bool haveAuthData) {} virtual void updateProtocolPage(const QJsonObject &config, DockerContainer container, bool haveAuthData, bool isThirdPartyConfig) {}
virtual QJsonObject getProtocolConfigFromPage(QJsonObject oldConfig) { return QJsonObject(); } virtual QJsonObject getProtocolConfigFromPage(QJsonObject oldConfig) { return QJsonObject(); }
}; };

View file

@ -21,7 +21,7 @@ ShadowSocksLogic::ShadowSocksLogic(UiLogic *logic, QObject *parent):
} }
void ShadowSocksLogic::updateProtocolPage(const QJsonObject &ssConfig, DockerContainer container, bool haveAuthData) void ShadowSocksLogic::updateProtocolPage(const QJsonObject &ssConfig, DockerContainer container, bool haveAuthData, bool isThirdPartyConfig)
{ {
set_pageEnabled(haveAuthData); set_pageEnabled(haveAuthData);
set_pushButtonSaveVisible(haveAuthData); set_pushButtonSaveVisible(haveAuthData);

View file

@ -26,7 +26,7 @@ public:
explicit ShadowSocksLogic(UiLogic *uiLogic, QObject *parent = nullptr); explicit ShadowSocksLogic(UiLogic *uiLogic, QObject *parent = nullptr);
~ShadowSocksLogic() = default; ~ShadowSocksLogic() = default;
void updateProtocolPage(const QJsonObject &ssConfig, DockerContainer container, bool haveAuthData) override; void updateProtocolPage(const QJsonObject &ssConfig, DockerContainer container, bool haveAuthData, bool isThirdPartyConfig) override;
QJsonObject getProtocolConfigFromPage(QJsonObject oldConfig) override; QJsonObject getProtocolConfigFromPage(QJsonObject oldConfig) override;
private: private:

View file

@ -36,370 +36,389 @@ PageProtocolBase {
ColumnLayout { ColumnLayout {
id: content id: content
enabled: logic.pageEnabled
anchors.top: parent.top anchors.top: parent.top
anchors.left: parent.left anchors.left: parent.left
anchors.right: parent.right anchors.right: parent.right
ColumnLayout {
LabelType { visible: !logic.isThirdPartyConfig
id: lb_subnet enabled: logic.pageEnabled
height: 21
text: qsTr("VPN Addresses Subnet")
}
TextFieldType {
id: tf_subnet
implicitWidth: parent.width
height: 31
text: logic.lineEditSubnetText
onEditingFinished: {
logic.lineEditSubnetText = text
}
}
//
LabelType {
id: lb_proto
Layout.topMargin: 20
height: 21
text: qsTr("Network protocol")
}
Rectangle {
id: rect_proto
implicitWidth: root.width - 60
height: 71
border.width: 1
border.color: "lightgray"
radius: 2
RadioButtonType {
x: 10
y: 40
width: 171
height: 19
text: qsTr("TCP")
enabled: logic.radioButtonTcpEnabled
checked: logic.radioButtonTcpChecked
onCheckedChanged: {
UiLogic.radioButtonTcpChecked = checked
}
}
RadioButtonType {
x: 10
y: 10
width: 171
height: 19
text: qsTr("UDP")
checked: logic.radioButtonUdpChecked
onCheckedChanged: {
logic.radioButtonUdpChecked = checked
}
enabled: logic.radioButtonUdpEnabled
}
}
//
RowLayout {
Layout.topMargin: 10
Layout.fillWidth: true
LabelType { LabelType {
id: lb_port id: lb_subnet
height: 31 height: 21
text: qsTr("Port") text: qsTr("VPN Addresses Subnet")
Layout.preferredWidth: root.width / 2 - 10
} }
TextFieldType { TextFieldType {
id: tf_port id: tf_subnet
implicitWidth: parent.width
height: 31
text: logic.lineEditSubnetText
onEditingFinished: {
logic.lineEditSubnetText = text
}
}
//
LabelType {
id: lb_proto
Layout.topMargin: 20
height: 21
text: qsTr("Network protocol")
}
Rectangle {
id: rect_proto
implicitWidth: root.width - 60
height: 71
border.width: 1
border.color: "lightgray"
radius: 2
RadioButtonType {
x: 10
y: 40
width: 171
height: 19
text: qsTr("TCP")
enabled: logic.radioButtonTcpEnabled
checked: logic.radioButtonTcpChecked
onCheckedChanged: {
UiLogic.radioButtonTcpChecked = checked
}
}
RadioButtonType {
x: 10
y: 10
width: 171
height: 19
text: qsTr("UDP")
checked: logic.radioButtonUdpChecked
onCheckedChanged: {
logic.radioButtonUdpChecked = checked
}
enabled: logic.radioButtonUdpEnabled
}
}
//
RowLayout {
Layout.topMargin: 10
Layout.fillWidth: true Layout.fillWidth: true
LabelType {
id: lb_port
height: 31
text: qsTr("Port")
Layout.preferredWidth: root.width / 2 - 10
}
TextFieldType {
id: tf_port
Layout.fillWidth: true
height: 31
text: logic.lineEditPortText
onEditingFinished: {
logic.lineEditPortText = text
}
enabled: logic.lineEditPortEnabled
}
}
//
CheckBoxType {
id: check_auto_enc
implicitWidth: parent.width
height: 21
text: qsTr("Auto-negotiate encryption")
checked: logic.checkBoxAutoEncryptionChecked
onCheckedChanged: {
logic.checkBoxAutoEncryptionChecked = checked
}
onClicked: {
logic.checkBoxAutoEncryptionClicked()
}
}
//
LabelType {
id: lb_cipher
height: 21
text: qsTr("Cipher")
}
ComboBoxType {
id: cb_cipher
implicitWidth: parent.width
height: 31 height: 31
text: logic.lineEditPortText model: [
onEditingFinished: { qsTr("AES-256-GCM"),
logic.lineEditPortText = text qsTr("AES-192-GCM"),
} qsTr("AES-128-GCM"),
enabled: logic.lineEditPortEnabled qsTr("AES-256-CBC"),
} qsTr("AES-192-CBC"),
} qsTr("AES-128-CBC"),
qsTr("ChaCha20-Poly1305"),
qsTr("ARIA-256-CBC"),
qsTr("CAMELLIA-256-CBC"),
// qsTr("none")
CheckBoxType { ]
id: check_auto_enc currentIndex: {
for (let i = 0; i < model.length; ++i) {
implicitWidth: parent.width if (logic.comboBoxVpnCipherText === model[i]) {
height: 21 return i
text: qsTr("Auto-negotiate encryption") }
checked: logic.checkBoxAutoEncryptionChecked
onCheckedChanged: {
logic.checkBoxAutoEncryptionChecked = checked
}
onClicked: {
logic.checkBoxAutoEncryptionClicked()
}
}
//
LabelType {
id: lb_cipher
height: 21
text: qsTr("Cipher")
}
ComboBoxType {
id: cb_cipher
implicitWidth: parent.width
height: 31
model: [
qsTr("AES-256-GCM"),
qsTr("AES-192-GCM"),
qsTr("AES-128-GCM"),
qsTr("AES-256-CBC"),
qsTr("AES-192-CBC"),
qsTr("AES-128-CBC"),
qsTr("ChaCha20-Poly1305"),
qsTr("ARIA-256-CBC"),
qsTr("CAMELLIA-256-CBC"),
qsTr("none")
]
currentIndex: {
for (let i = 0; i < model.length; ++i) {
if (logic.comboBoxVpnCipherText === model[i]) {
return i
} }
return -1
} }
return -1 onCurrentTextChanged: {
logic.comboBoxVpnCipherText = currentText
}
enabled: !check_auto_enc.checked
} }
onCurrentTextChanged: {
logic.comboBoxVpnCipherText = currentText
}
enabled: !check_auto_enc.checked
}
// //
LabelType { LabelType {
id: lb_hash id: lb_hash
height: 21 height: 21
Layout.topMargin: 20 Layout.topMargin: 20
text: qsTr("Hash") text: qsTr("Hash")
} }
ComboBoxType { ComboBoxType {
id: cb_hash id: cb_hash
height: 31 height: 31
implicitWidth: parent.width implicitWidth: parent.width
model: [ model: [
qsTr("SHA512"), qsTr("SHA512"),
qsTr("SHA384"), qsTr("SHA384"),
qsTr("SHA256"), qsTr("SHA256"),
qsTr("SHA3-512"), qsTr("SHA3-512"),
qsTr("SHA3-384"), qsTr("SHA3-384"),
qsTr("SHA3-256"), qsTr("SHA3-256"),
qsTr("whirlpool"), qsTr("whirlpool"),
qsTr("BLAKE2b512"), qsTr("BLAKE2b512"),
qsTr("BLAKE2s256"), qsTr("BLAKE2s256"),
qsTr("SHA1") qsTr("SHA1")
] ]
currentIndex: { currentIndex: {
for (let i = 0; i < model.length; ++i) { for (let i = 0; i < model.length; ++i) {
if (logic.comboBoxVpnHashText === model[i]) { if (logic.comboBoxVpnHashText === model[i]) {
return i return i
}
} }
return -1
} }
return -1 onCurrentTextChanged: {
} logic.comboBoxVpnHashText = currentText
onCurrentTextChanged: { }
logic.comboBoxVpnHashText = currentText enabled: !check_auto_enc.checked
}
enabled: !check_auto_enc.checked
}
CheckBoxType {
id: check_tls
implicitWidth: parent.width
Layout.topMargin: 20
height: 21
text: qsTr("Enable TLS auth")
checked: logic.checkBoxTlsAuthChecked
onCheckedChanged: {
logic.checkBoxTlsAuthChecked = checked
} }
} CheckBoxType {
id: check_tls
implicitWidth: parent.width
Layout.topMargin: 20
height: 21
text: qsTr("Enable TLS auth")
checked: logic.checkBoxTlsAuthChecked
onCheckedChanged: {
logic.checkBoxTlsAuthChecked = checked
}
CheckBoxType {
id: check_block_dns
implicitWidth: parent.width
height: 21
text: qsTr("Block DNS requests outside of VPN")
checked: logic.checkBoxBlockDnsChecked
onCheckedChanged: {
logic.checkBoxBlockDnsChecked = checked
}
}
BasicButtonType {
id: pb_client_config
implicitWidth: parent.width
height: 21
text: qsTr("Additional client config commands →")
background: Item {
anchors.fill: parent
} }
contentItem: Text { CheckBoxType {
anchors.fill: parent id: check_block_dns
font.family: "Lato" implicitWidth: parent.width
font.styleName: "normal" height: 21
font.pixelSize: 16 text: qsTr("Block DNS requests outside of VPN")
color: "#15CDCB"; checked: logic.checkBoxBlockDnsChecked
text: pb_client_config.text onCheckedChanged: {
horizontalAlignment: Text.AlignLeft logic.checkBoxBlockDnsChecked = checked
verticalAlignment: Text.AlignVCenter }
} }
antialiasing: true
checkable: true
checked: StartPageLogic.pushButtonConnectKeyChecked
}
Rectangle {
id: rect_client_conf
implicitWidth: root.width - 60
height: 101
border.width: 1
border.color: "lightgray"
radius: 2
visible: pb_client_config.checked
ScrollView { BasicButtonType {
anchors.fill: parent id: pb_client_config
TextArea {
id: te_client_config implicitWidth: parent.width
height: 21
text: qsTr("Additional client config commands →")
background: Item {
anchors.fill: parent
}
contentItem: Text {
anchors.fill: parent
font.family: "Lato" font.family: "Lato"
font.styleName: "normal" font.styleName: "normal"
font.pixelSize: 16 font.pixelSize: 16
color: "#181922" color: "#15CDCB";
text: logic.textAreaAdditionalClientConfig text: pb_client_config.text
onEditingFinished: { horizontalAlignment: Text.AlignLeft
logic.textAreaAdditionalClientConfig = text verticalAlignment: Text.AlignVCenter
}
antialiasing: true
checkable: true
checked: StartPageLogic.pushButtonConnectKeyChecked
}
Rectangle {
id: rect_client_conf
implicitWidth: root.width - 60
height: 101
border.width: 1
border.color: "lightgray"
radius: 2
visible: pb_client_config.checked
ScrollView {
anchors.fill: parent
TextArea {
id: te_client_config
font.family: "Lato"
font.styleName: "normal"
font.pixelSize: 16
color: "#181922"
text: logic.textAreaAdditionalClientConfig
onEditingFinished: {
logic.textAreaAdditionalClientConfig = text
}
} }
} }
} }
} BasicButtonType {
id: pb_server_config
implicitWidth: parent.width
height: 21
text: qsTr("Additional server config commands →")
background: Item {
anchors.fill: parent
}
BasicButtonType { contentItem: Text {
id: pb_server_config anchors.fill: parent
implicitWidth: parent.width
height: 21
text: qsTr("Additional server config commands →")
background: Item {
anchors.fill: parent
}
contentItem: Text {
anchors.fill: parent
font.family: "Lato"
font.styleName: "normal"
font.pixelSize: 16
color: "#15CDCB";
text: pb_server_config.text
horizontalAlignment: Text.AlignLeft
verticalAlignment: Text.AlignVCenter
}
antialiasing: true
checkable: true
checked: StartPageLogic.pushButtonConnectKeyChecked
}
Rectangle {
id: rect_server_conf
implicitWidth: root.width - 60
height: 101
border.width: 1
border.color: "lightgray"
radius: 2
visible: pb_server_config.checked
ScrollView {
anchors.fill: parent
TextArea {
id: te_server_config
font.family: "Lato" font.family: "Lato"
font.styleName: "normal" font.styleName: "normal"
font.pixelSize: 16 font.pixelSize: 16
color: "#181922" color: "#15CDCB";
text: logic.textAreaAdditionalServerConfig text: pb_server_config.text
onEditingFinished: { horizontalAlignment: Text.AlignLeft
logic.textAreaAdditionalServerConfig = text verticalAlignment: Text.AlignVCenter
}
} }
antialiasing: true
checkable: true
checked: StartPageLogic.pushButtonConnectKeyChecked
} }
Rectangle {
id: rect_server_conf
implicitWidth: root.width - 60
height: 101
border.width: 1
border.color: "lightgray"
radius: 2
visible: pb_server_config.checked
} ScrollView {
anchors.fill: parent
TextArea {
id: te_server_config
font.family: "Lato"
font.styleName: "normal"
font.pixelSize: 16
color: "#181922"
text: logic.textAreaAdditionalServerConfig
onEditingFinished: {
logic.textAreaAdditionalServerConfig = text
}
}
}
LabelType {
id: label_proto_openvpn_info
height: 41 }
visible: logic.labelProtoOpenVpnInfoVisible
text: logic.labelProtoOpenVpnInfoText
}
Rectangle { LabelType {
id: it_save id: label_proto_openvpn_info
implicitWidth: parent.width
Layout.topMargin: 20
height: 40
BlueButtonType { height: 41
id: pb_save visible: logic.labelProtoOpenVpnInfoVisible
z: 1 text: logic.labelProtoOpenVpnInfoText
}
Rectangle {
id: it_save
implicitWidth: parent.width
Layout.topMargin: 20
height: 40 height: 40
text: qsTr("Save and restart VPN")
width: parent.width
visible: logic.pushButtonSaveVisible
onClicked: {
logic.onPushButtonProtoOpenVpnSaveClicked()
}
}
ProgressBar { BlueButtonType {
id: progress_save id: pb_save
anchors.fill: pb_save z: 1
from: 0 height: 40
to: logic.progressBarResetMaximium text: qsTr("Save and restart VPN")
value: logic.progressBarResetValue width: parent.width
visible: logic.progressBarResetVisible visible: logic.pushButtonSaveVisible
background: Rectangle { onClicked: {
implicitWidth: parent.width logic.onPushButtonProtoOpenVpnSaveClicked()
implicitHeight: parent.height
color: "#100A44"
radius: 4
}
contentItem: Item {
implicitWidth: parent.width
implicitHeight: parent.height
Rectangle {
width: progress_save.visualPosition * parent.width
height: parent.height
radius: 4
color: Qt.rgba(255, 255, 255, 0.15);
} }
} }
ProgressBar {
id: progress_save
anchors.fill: pb_save
from: 0
to: logic.progressBarResetMaximium
value: logic.progressBarResetValue
visible: logic.progressBarResetVisible
background: Rectangle {
implicitWidth: parent.width
implicitHeight: parent.height
color: "#100A44"
radius: 4
}
contentItem: Item {
implicitWidth: parent.width
implicitHeight: parent.height
Rectangle {
width: progress_save.visualPosition * parent.width
height: parent.height
radius: 4
color: Qt.rgba(255, 255, 255, 0.15);
}
}
}
} }
} }
} ColumnLayout {
visible: logic.isThirdPartyConfig
TextAreaType {
id: ta_config
Layout.topMargin: 5
Layout.bottomMargin: 20
Layout.fillWidth: true
Layout.leftMargin: 1
Layout.rightMargin: 1
Layout.preferredHeight: fl.height - 70
flickableDirection: Flickable.AutoFlickIfNeeded
textArea.readOnly: true
textArea.text: logic.openVpnLastConfigText
}
}
}
} }
} }