added protocol settings pages and models for openvpn, cloak and shadowsocks

This commit is contained in:
vladimir.kuznetsov 2023-07-13 11:29:26 +09:00
parent a97417fd38
commit c13b9754eb
42 changed files with 2130 additions and 576 deletions

View file

@ -129,8 +129,8 @@ file(GLOB_RECURSE PAGE_LOGIC_CPP CONFIGURE_DEPENDS ${CMAKE_CURRENT_LIST_DIR}/ui/
file(GLOB CONFIGURATORS_H CONFIGURE_DEPENDS ${CMAKE_CURRENT_LIST_DIR}/configurators/*.h)
file(GLOB CONFIGURATORS_CPP CONFIGURE_DEPENDS ${CMAKE_CURRENT_LIST_DIR}/configurators/*.cpp)
file(GLOB UI_MODELS_H CONFIGURE_DEPENDS ${CMAKE_CURRENT_LIST_DIR}/ui/models/*.h)
file(GLOB UI_MODELS_CPP CONFIGURE_DEPENDS ${CMAKE_CURRENT_LIST_DIR}/ui/models/*.cpp)
file(GLOB UI_MODELS_H CONFIGURE_DEPENDS ${CMAKE_CURRENT_LIST_DIR}/ui/models/*.h ${CMAKE_CURRENT_LIST_DIR}/ui/models/protocols/*.h)
file(GLOB UI_MODELS_CPP CONFIGURE_DEPENDS ${CMAKE_CURRENT_LIST_DIR}/ui/models/*.cpp ${CMAKE_CURRENT_LIST_DIR}/ui/models/protocols/*.cpp)
file(GLOB UI_CONTROLLERS_H CONFIGURE_DEPENDS ${CMAKE_CURRENT_LIST_DIR}/ui/controllers/*.h)
file(GLOB UI_CONTROLLERS_CPP CONFIGURE_DEPENDS ${CMAKE_CURRENT_LIST_DIR}/ui/controllers/*.cpp)

View file

@ -79,38 +79,12 @@ void AmneziaApplication::init()
m_engine->rootContext()->setContextProperty("Debug", &Logger::Instance());
//
m_containersModel.reset(new ContainersModel(m_settings, this));
m_engine->rootContext()->setContextProperty("ContainersModel", m_containersModel.get());
m_serversModel.reset(new ServersModel(m_settings, this));
m_engine->rootContext()->setContextProperty("ServersModel", m_serversModel.get());
connect(m_serversModel.get(), &ServersModel::currentlyProcessedServerIndexChanged, m_containersModel.get(),
&ContainersModel::setCurrentlyProcessedServerIndex);
m_languageModel.reset(new LanguageModel(m_settings, this));
m_engine->rootContext()->setContextProperty("LanguageModel", m_languageModel.get());
connect(m_languageModel.get(), &LanguageModel::updateTranslations, this, &AmneziaApplication::updateTranslator);
m_configurator = std::shared_ptr<VpnConfigurator>(new VpnConfigurator(m_settings, this));
m_vpnConnection.reset(new VpnConnection(m_settings, m_configurator));
m_connectionController.reset(new ConnectionController(m_serversModel, m_containersModel, m_vpnConnection));
m_engine->rootContext()->setContextProperty("ConnectionController", m_connectionController.get());
m_pageController.reset(new PageController(m_serversModel));
m_engine->rootContext()->setContextProperty("PageController", m_pageController.get());
m_installController.reset(new InstallController(m_serversModel, m_containersModel, m_settings));
m_engine->rootContext()->setContextProperty("InstallController", m_installController.get());
m_importController.reset(new ImportController(m_serversModel, m_containersModel, m_settings));
m_engine->rootContext()->setContextProperty("ImportController", m_importController.get());
m_exportController.reset(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());
initModels();
initControllers();
//
@ -244,3 +218,59 @@ QQmlApplicationEngine *AmneziaApplication::qmlEngine() const
{
return m_engine;
}
void AmneziaApplication::initModels()
{
m_containersModel.reset(new ContainersModel(m_settings, this));
m_engine->rootContext()->setContextProperty("ContainersModel", m_containersModel.get());
m_serversModel.reset(new ServersModel(m_settings, this));
m_engine->rootContext()->setContextProperty("ServersModel", m_serversModel.get());
connect(m_serversModel.get(), &ServersModel::currentlyProcessedServerIndexChanged, m_containersModel.get(),
&ContainersModel::setCurrentlyProcessedServerIndex);
m_languageModel.reset(new LanguageModel(m_settings, this));
m_engine->rootContext()->setContextProperty("LanguageModel", m_languageModel.get());
connect(m_languageModel.get(), &LanguageModel::updateTranslations, this, &AmneziaApplication::updateTranslator);
m_protocolsModel.reset(new ProtocolsModel(m_settings, this));
m_engine->rootContext()->setContextProperty("ProtocolsModel", m_protocolsModel.get());
m_openVpnConfigModel.reset(new OpenVpnConfigModel(this));
m_engine->rootContext()->setContextProperty("OpenVpnConfigModel", m_openVpnConfigModel.get());
m_shadowSocksConfigModel.reset(new ShadowSocksConfigModel(this));
m_engine->rootContext()->setContextProperty("ShadowSocksConfigModel", m_shadowSocksConfigModel.get());
m_cloakConfigModel.reset(new CloakConfigModel(this));
m_engine->rootContext()->setContextProperty("CloakConfigModel", m_cloakConfigModel.get());
m_wireguardConfigModel.reset(new WireGuardConfigModel(this));
m_engine->rootContext()->setContextProperty("WireGuardConfigModel", m_wireguardConfigModel.get());
#ifdef Q_OS_WINDOWS
m_ikev2ConfigModel.reset(new Ikev2ConfigModel(this));
m_engine->rootContext()->setContextProperty("Ikev2ConfigModel", m_ikev2ConfigModel.get());
#endif
}
void AmneziaApplication::initControllers()
{
m_connectionController.reset(new ConnectionController(m_serversModel, m_containersModel, m_vpnConnection));
m_engine->rootContext()->setContextProperty("ConnectionController", m_connectionController.get());
m_pageController.reset(new PageController(m_serversModel));
m_engine->rootContext()->setContextProperty("PageController", m_pageController.get());
m_installController.reset(new InstallController(m_serversModel, m_containersModel, m_settings));
m_engine->rootContext()->setContextProperty("InstallController", m_installController.get());
m_importController.reset(new ImportController(m_serversModel, m_containersModel, m_settings));
m_engine->rootContext()->setContextProperty("ImportController", m_importController.get());
m_exportController.reset(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());
}

View file

@ -21,6 +21,14 @@
#include "ui/controllers/settingsController.h"
#include "ui/models/containers_model.h"
#include "ui/models/languageModel.h"
#include "ui/models/protocols/cloakConfigModel.h"
#ifdef Q_OS_WINDOWS
#include "ui/models/protocols/ikev2ConfigModel.h"
#endif
#include "ui/models/protocols/openvpnConfigModel.h"
#include "ui/models/protocols/shadowsocksConfigModel.h"
#include "ui/models/protocols/wireguardConfigModel.h"
#include "ui/models/protocols_model.h"
#include "ui/models/servers_model.h"
#define amnApp (static_cast<AmneziaApplication *>(QCoreApplication::instance()))
@ -56,6 +64,9 @@ public:
QQmlApplicationEngine *qmlEngine() const;
private:
void initModels();
void initControllers();
QQmlApplicationEngine *m_engine {};
std::shared_ptr<Settings> m_settings;
std::shared_ptr<VpnConfigurator> m_configurator;
@ -69,6 +80,15 @@ private:
QSharedPointer<ContainersModel> m_containersModel;
QSharedPointer<ServersModel> m_serversModel;
QScopedPointer<LanguageModel> m_languageModel;
QScopedPointer<ProtocolsModel> m_protocolsModel;
QScopedPointer<OpenVpnConfigModel> m_openVpnConfigModel;
QScopedPointer<ShadowSocksConfigModel> m_shadowSocksConfigModel;
QScopedPointer<CloakConfigModel> m_cloakConfigModel;
QScopedPointer<WireGuardConfigModel> m_wireguardConfigModel;
#ifdef Q_OS_WINDOWS
QScopedPointer<Ikev2ConfigModel> m_ikev2ConfigModel;
#endif
QSharedPointer<VpnConnection> m_vpnConnection;

View file

@ -1,229 +1,223 @@
#ifndef PROTOCOLS_DEFS_H
#define PROTOCOLS_DEFS_H
#include <QObject>
#include <QDebug>
#include <QObject>
#include <QQmlEngine>
namespace amnezia {
namespace config_key {
// Json config strings
constexpr char hostName[] = "hostName";
constexpr char userName[] = "userName";
constexpr char password[] = "password";
constexpr char port[] = "port";
constexpr char local_port[] = "local_port";
constexpr char dns1[] = "dns1";
constexpr char dns2[] = "dns2";
constexpr char description[] = "description";
constexpr char cert[] = "cert";
constexpr char config[] = "config";
constexpr char containers[] = "containers";
constexpr char container[] = "container";
constexpr char defaultContainer[] = "defaultContainer";
constexpr char vpnproto[] = "protocol";
constexpr char protocols[] = "protocols";
constexpr char remote[] = "remote";
constexpr char transport_proto[] = "transport_proto";
constexpr char cipher[] = "cipher";
constexpr char hash[] = "hash";
constexpr char ncp_disable[] = "ncp_disable";
constexpr char tls_auth[] = "tls_auth";
constexpr char client_priv_key[] = "client_priv_key";
constexpr char client_pub_key[] = "client_pub_key";
constexpr char server_priv_key[] = "server_priv_key";
constexpr char server_pub_key[] = "server_pub_key";
constexpr char psk_key[] = "psk_key";
constexpr char client_ip[] = "client_ip"; // internal ip address
constexpr char site[] = "site";
constexpr char block_outside_dns[] = "block_outside_dns";
constexpr char subnet_address[] = "subnet_address";
constexpr char subnet_mask[] = "subnet_mask";
constexpr char subnet_cidr[] = "subnet_cidr";
constexpr char additional_client_config[] = "additional_client_config";
constexpr char additional_server_config[] = "additional_server_config";
// proto config keys
constexpr char last_config[] = "last_config";
constexpr char isThirdPartyConfig[] = "isThirdPartyConfig";
constexpr char openvpn[] = "openvpn";
constexpr char wireguard[] = "wireguard";
}
namespace protocols {
namespace dns {
constexpr char amneziaDnsIp[] = "172.29.172.254";
}
namespace openvpn {
constexpr char defaultSubnetAddress[] = "10.8.0.0";
constexpr char defaultSubnetMask[] = "255.255.255.0";
constexpr char defaultSubnetCidr[] = "24";
constexpr char serverConfigPath[] = "/opt/amnezia/openvpn/server.conf";
constexpr char caCertPath[] = "/opt/amnezia/openvpn/pki/ca.crt";
constexpr char clientCertPath[] = "/opt/amnezia/openvpn/pki/issued";
constexpr char taKeyPath[] = "/opt/amnezia/openvpn/ta.key";
constexpr char clientsDirPath[] = "/opt/amnezia/openvpn/clients";
constexpr char defaultPort[] = "1194";
constexpr char defaultTransportProto[] = "udp";
constexpr char defaultCipher[] = "AES-256-GCM";
constexpr char defaultHash[] = "SHA512";
constexpr bool defaultBlockOutsideDns = true;
constexpr bool defaultNcpDisable = false;
constexpr bool defaultTlsAuth = true;
constexpr char ncpDisableString[] = "ncp-disable";
constexpr char tlsAuthString[] = "tls-auth /opt/amnezia/openvpn/ta.key 0";
constexpr char defaultAdditionalClientConfig[] = "";
constexpr char defaultAdditionalServerConfig[] = "";
}
namespace shadowsocks {
constexpr char ssKeyPath[] = "/opt/amnezia/shadowsocks/shadowsocks.key";
constexpr char defaultPort[] = "6789";
constexpr char defaultLocalProxyPort[] = "8585";
constexpr char defaultCipher[] = "chacha20-ietf-poly1305";
}
namespace cloak {
constexpr char ckPublicKeyPath[] = "/opt/amnezia/cloak/cloak_public.key";
constexpr char ckBypassUidKeyPath[] = "/opt/amnezia/cloak/cloak_bypass_uid.key";
constexpr char ckAdminKeyPath[] = "/opt/amnezia/cloak/cloak_admin_uid.key";
constexpr char defaultPort[] = "443";
constexpr char defaultRedirSite[] = "tile.openstreetmap.org";
constexpr char defaultCipher[] = "chacha20-poly1305";
}
namespace wireguard {
constexpr char defaultSubnetAddress[] = "10.8.1.0";
constexpr char defaultSubnetMask[] = "255.255.255.0";
constexpr char defaultSubnetCidr[] = "24";
constexpr char defaultPort[] = "51820";
constexpr char serverConfigPath[] = "/opt/amnezia/wireguard/wg0.conf";
constexpr char serverPublicKeyPath[] = "/opt/amnezia/wireguard/wireguard_server_public_key.key";
constexpr char serverPskKeyPath[] = "/opt/amnezia/wireguard/wireguard_psk.key";
}
namespace sftp {
constexpr char defaultUserName[] = "sftp_user";
} // namespace sftp
} // namespace protocols
namespace ProtocolEnumNS {
Q_NAMESPACE
enum TransportProto {
Udp,
Tcp
};
Q_ENUM_NS(TransportProto)
enum Proto {
Any = 0,
OpenVpn,
ShadowSocks,
Cloak,
WireGuard,
Ikev2,
L2tp,
// non-vpn
TorWebSite,
Dns,
FileShare,
Sftp
};
Q_ENUM_NS(Proto)
enum ServiceType {
None = 0,
Vpn,
Other
};
Q_ENUM_NS(ServiceType)
} // namespace ProtocolEnumNS
using namespace ProtocolEnumNS;
class ProtocolProps : public QObject
namespace amnezia
{
Q_OBJECT
namespace config_key
{
public:
Q_INVOKABLE static QList<Proto> allProtocols();
// Json config strings
constexpr char hostName[] = "hostName";
constexpr char userName[] = "userName";
constexpr char password[] = "password";
constexpr char port[] = "port";
constexpr char local_port[] = "local_port";
// spelling may differ for various protocols - TCP for OpenVPN, tcp for others
Q_INVOKABLE static TransportProto transportProtoFromString(QString p);
Q_INVOKABLE static QString transportProtoToString(TransportProto proto, Proto p = Proto::Any);
constexpr char dns1[] = "dns1";
constexpr char dns2[] = "dns2";
Q_INVOKABLE static Proto protoFromString(QString p);
Q_INVOKABLE static QString protoToString(Proto p);
constexpr char description[] = "description";
constexpr char cert[] = "cert";
constexpr char config[] = "config";
Q_INVOKABLE static QMap<Proto, QString> protocolHumanNames();
Q_INVOKABLE static QMap<Proto, QString> protocolDescriptions();
constexpr char containers[] = "containers";
constexpr char container[] = "container";
constexpr char defaultContainer[] = "defaultContainer";
Q_INVOKABLE static ServiceType protocolService(Proto p);
constexpr char vpnproto[] = "protocol";
constexpr char protocols[] = "protocols";
Q_INVOKABLE static int defaultPort(Proto p);
Q_INVOKABLE static bool defaultPortChangeable(Proto p);
constexpr char remote[] = "remote";
constexpr char transport_proto[] = "transport_proto";
constexpr char cipher[] = "cipher";
constexpr char hash[] = "hash";
constexpr char ncp_disable[] = "ncp_disable";
constexpr char tls_auth[] = "tls_auth";
Q_INVOKABLE static TransportProto defaultTransportProto(Proto p);
Q_INVOKABLE static bool defaultTransportProtoChangeable(Proto p);
constexpr char client_priv_key[] = "client_priv_key";
constexpr char client_pub_key[] = "client_pub_key";
constexpr char server_priv_key[] = "server_priv_key";
constexpr char server_pub_key[] = "server_pub_key";
constexpr char psk_key[] = "psk_key";
constexpr char client_ip[] = "client_ip"; // internal ip address
Q_INVOKABLE static QString key_proto_config_data(Proto p);
Q_INVOKABLE static QString key_proto_config_path(Proto p);
constexpr char site[] = "site";
constexpr char block_outside_dns[] = "block_outside_dns";
};
constexpr char subnet_address[] = "subnet_address";
constexpr char subnet_mask[] = "subnet_mask";
constexpr char subnet_cidr[] = "subnet_cidr";
static void declareQmlProtocolEnum() {
qmlRegisterUncreatableMetaObject(
ProtocolEnumNS::staticMetaObject,
"ProtocolEnum",
1, 0,
"ProtocolEnum",
"Error: only enums"
);
constexpr char additional_client_config[] = "additional_client_config";
constexpr char additional_server_config[] = "additional_server_config";
qmlRegisterUncreatableMetaObject(
ProtocolEnumNS::staticMetaObject,
"ProtocolEnum",
1, 0,
"TransportProto",
"Error: only enums"
);
// proto config keys
constexpr char last_config[] = "last_config";
qmlRegisterUncreatableMetaObject(
ProtocolEnumNS::staticMetaObject,
"ProtocolEnum",
1, 0,
"ServiceType",
"Error: only enums"
);
}
constexpr char isThirdPartyConfig[] = "isThirdPartyConfig";
constexpr char openvpn[] = "openvpn";
constexpr char wireguard[] = "wireguard";
constexpr char shadowsocks[] = "shadowsocks";
constexpr char cloak[] = "cloak";
}
namespace protocols
{
namespace dns
{
constexpr char amneziaDnsIp[] = "172.29.172.254";
}
namespace openvpn
{
constexpr char defaultSubnetAddress[] = "10.8.0.0";
constexpr char defaultSubnetMask[] = "255.255.255.0";
constexpr char defaultSubnetCidr[] = "24";
constexpr char serverConfigPath[] = "/opt/amnezia/openvpn/server.conf";
constexpr char caCertPath[] = "/opt/amnezia/openvpn/pki/ca.crt";
constexpr char clientCertPath[] = "/opt/amnezia/openvpn/pki/issued";
constexpr char taKeyPath[] = "/opt/amnezia/openvpn/ta.key";
constexpr char clientsDirPath[] = "/opt/amnezia/openvpn/clients";
constexpr char defaultPort[] = "1194";
constexpr char defaultTransportProto[] = "udp";
constexpr char defaultCipher[] = "AES-256-GCM";
constexpr char defaultHash[] = "SHA512";
constexpr bool defaultBlockOutsideDns = true;
constexpr bool defaultNcpDisable = false;
constexpr bool defaultTlsAuth = true;
constexpr char ncpDisableString[] = "ncp-disable";
constexpr char tlsAuthString[] = "tls-auth /opt/amnezia/openvpn/ta.key 0";
constexpr char defaultAdditionalClientConfig[] = "";
constexpr char defaultAdditionalServerConfig[] = "";
}
namespace shadowsocks
{
constexpr char ssKeyPath[] = "/opt/amnezia/shadowsocks/shadowsocks.key";
constexpr char defaultPort[] = "6789";
constexpr char defaultLocalProxyPort[] = "8585";
constexpr char defaultCipher[] = "chacha20-ietf-poly1305";
}
namespace cloak
{
constexpr char ckPublicKeyPath[] = "/opt/amnezia/cloak/cloak_public.key";
constexpr char ckBypassUidKeyPath[] = "/opt/amnezia/cloak/cloak_bypass_uid.key";
constexpr char ckAdminKeyPath[] = "/opt/amnezia/cloak/cloak_admin_uid.key";
constexpr char defaultPort[] = "443";
constexpr char defaultRedirSite[] = "tile.openstreetmap.org";
constexpr char defaultCipher[] = "chacha20-poly1305";
}
namespace wireguard
{
constexpr char defaultSubnetAddress[] = "10.8.1.0";
constexpr char defaultSubnetMask[] = "255.255.255.0";
constexpr char defaultSubnetCidr[] = "24";
constexpr char defaultPort[] = "51820";
constexpr char serverConfigPath[] = "/opt/amnezia/wireguard/wg0.conf";
constexpr char serverPublicKeyPath[] = "/opt/amnezia/wireguard/wireguard_server_public_key.key";
constexpr char serverPskKeyPath[] = "/opt/amnezia/wireguard/wireguard_psk.key";
}
namespace sftp
{
constexpr char defaultUserName[] = "sftp_user";
} // namespace sftp
} // namespace protocols
namespace ProtocolEnumNS
{
Q_NAMESPACE
enum TransportProto {
Udp,
Tcp
};
Q_ENUM_NS(TransportProto)
enum Proto {
Any = 0,
OpenVpn,
ShadowSocks,
Cloak,
WireGuard,
Ikev2,
L2tp,
// non-vpn
TorWebSite,
Dns,
FileShare,
Sftp
};
Q_ENUM_NS(Proto)
enum ServiceType {
None = 0,
Vpn,
Other
};
Q_ENUM_NS(ServiceType)
} // namespace ProtocolEnumNS
using namespace ProtocolEnumNS;
class ProtocolProps : public QObject
{
Q_OBJECT
public:
Q_INVOKABLE static QList<Proto> allProtocols();
// spelling may differ for various protocols - TCP for OpenVPN, tcp for others
Q_INVOKABLE static TransportProto transportProtoFromString(QString p);
Q_INVOKABLE static QString transportProtoToString(TransportProto proto, Proto p = Proto::Any);
Q_INVOKABLE static Proto protoFromString(QString p);
Q_INVOKABLE static QString protoToString(Proto p);
Q_INVOKABLE static QMap<Proto, QString> protocolHumanNames();
Q_INVOKABLE static QMap<Proto, QString> protocolDescriptions();
Q_INVOKABLE static ServiceType protocolService(Proto p);
Q_INVOKABLE static int defaultPort(Proto p);
Q_INVOKABLE static bool defaultPortChangeable(Proto p);
Q_INVOKABLE static TransportProto defaultTransportProto(Proto p);
Q_INVOKABLE static bool defaultTransportProtoChangeable(Proto p);
Q_INVOKABLE static QString key_proto_config_data(Proto p);
Q_INVOKABLE static QString key_proto_config_path(Proto p);
};
static void declareQmlProtocolEnum()
{
qmlRegisterUncreatableMetaObject(ProtocolEnumNS::staticMetaObject, "ProtocolEnum", 1, 0, "ProtocolEnum",
"Error: only enums");
qmlRegisterUncreatableMetaObject(ProtocolEnumNS::staticMetaObject, "ProtocolEnum", 1, 0, "TransportProto",
"Error: only enums");
qmlRegisterUncreatableMetaObject(ProtocolEnumNS::staticMetaObject, "ProtocolEnum", 1, 0, "ServiceType",
"Error: only enums");
}
} // namespace amnezia

View file

@ -250,7 +250,6 @@
<file>ui/qml/Pages2/PageDeinstalling.qml</file>
<file>ui/qml/Controls2/BackButtonType.qml</file>
<file>ui/qml/Pages2/PageSettingsServerProtocol.qml</file>
<file>ui/qml/Components/Protocols/OpenVpnSettings.qml</file>
<file>ui/qml/Components/TransportProtoSelector.qml</file>
<file>ui/qml/Controls2/ListViewType.qml</file>
<file>images/controls/radio-button.svg</file>
@ -271,5 +270,8 @@
<file>ui/qml/Filters/ContainersModelFilters.qml</file>
<file>ui/qml/Components/SelectLanguageDrawer.qml</file>
<file>ui/qml/Controls2/BusyIndicatorType.qml</file>
<file>ui/qml/Pages2/PageProtocolOpenVpnSettings.qml</file>
<file>ui/qml/Pages2/PageProtocolShadowSocksSettings.qml</file>
<file>ui/qml/Pages2/PageProtocolCloakSettings.qml</file>
</qresource>
</RCC>

View file

@ -69,7 +69,7 @@ void InstallController::installServer(DockerContainer container, QJsonObject &co
m_serversModel->addServer(server);
m_serversModel->setDefaultServerIndex(m_serversModel->getServersCount() - 1);
emit installServerFinished(isInstalledContainerFound);
emit installServerFinished(false); // todo incorrect notification about found containers
return;
}
@ -108,7 +108,7 @@ void InstallController::installContainer(DockerContainer container, QJsonObject
}
}
emit installContainerFinished(isInstalledContainerFound);
emit installContainerFinished(false); // todo incorrect notification about found containers
return;
}
@ -162,6 +162,29 @@ void InstallController::scanServerForInstalledContainers()
emit installationErrorOccurred(errorString(errorCode));
}
void InstallController::updateContainer(QJsonObject config)
{
int serverIndex = m_serversModel->getCurrentlyProcessedServerIndex();
ServerCredentials serverCredentials =
qvariant_cast<ServerCredentials>(m_serversModel->data(serverIndex, ServersModel::Roles::CredentialsRole));
const DockerContainer container = ContainerProps::containerFromString(config.value(config_key::container).toString());
auto modelIndex = m_containersModel->index(container);
QJsonObject oldContainerConfig =
qvariant_cast<QJsonObject>(m_containersModel->data(modelIndex, ContainersModel::Roles::ConfigRole));
ServerController serverController(m_settings);
auto errorCode = serverController.updateContainer(serverCredentials, container, oldContainerConfig, config);
if (errorCode == ErrorCode::NoError) {
m_containersModel->setData(modelIndex, config, ContainersModel::Roles::ConfigRole);
emit updateContainerFinished();
return;
}
emit installationErrorOccurred(errorString(errorCode));
}
QRegularExpression InstallController::ipAddressPortRegExp()
{
return Utils::ipAddressPortRegExp();

View file

@ -24,12 +24,16 @@ public slots:
void scanServerForInstalledContainers();
void updateContainer(QJsonObject config);
QRegularExpression ipAddressPortRegExp();
signals:
void installContainerFinished(bool isInstalledContainerFound);
void installServerFinished(bool isInstalledContainerFound);
void updateContainerFinished();
void scanServerFinished(bool isInstalledContainerFound);
void installationErrorOccurred(QString errorMessage);

View file

@ -36,7 +36,13 @@ namespace PageLoader
PageSetupWizardInstalling,
PageSetupWizardConfigSource,
PageSetupWizardTextKey,
PageSetupWizardViewConfig
PageSetupWizardViewConfig,
PageProtocolOpenVpnSettings,
PageProtocolShadowSocksSettings,
PageProtocolCloakSettings,
PageProtocolWireGuardSettings,
PageProtocolIKev2Settings
};
Q_ENUM_NS(PageEnum)

View file

@ -29,6 +29,11 @@ bool ContainersModel::setData(const QModelIndex &index, const QVariant &value, i
case ConfigRole: {
m_settings->setContainerConfig(m_currentlyProcessedServerIndex, container, value.toJsonObject());
m_containers = m_settings->containers(m_currentlyProcessedServerIndex);
if (m_defaultContainerIndex != DockerContainer::None) {
break;
} else if (ContainerProps::containerService(container) == ServiceType::Other) {
break;
}
}
case ServiceTypeRole:
// return ContainerProps::containerService(container);
@ -108,6 +113,11 @@ int ContainersModel::getCurrentlyProcessedContainerIndex()
return m_currentlyProcessedContainerIndex;
}
QString ContainersModel::getCurrentlyProcessedContainerName()
{
return ContainerProps::containerHumanNames().value(static_cast<DockerContainer>(m_currentlyProcessedContainerIndex));
}
void ContainersModel::removeAllContainers()
{
@ -116,14 +126,39 @@ void ContainersModel::removeAllContainers()
if (errorCode == ErrorCode::NoError) {
beginResetModel();
m_settings->setContainers(m_currentlyProcessedServerIndex, {});
m_settings->setDefaultContainer(m_currentlyProcessedServerIndex, DockerContainer::None);
m_containers = m_settings->containers(m_currentlyProcessedServerIndex);
setData(index(DockerContainer::None, 0), true, IsDefaultRole);
endResetModel();
}
// todo process errors
}
void ContainersModel::removeCurrentlyProcessedContainer()
{
ServerController serverController(m_settings);
auto credentials = m_settings->serverCredentials(m_currentlyProcessedServerIndex);
auto dockerContainer = static_cast<DockerContainer>(m_currentlyProcessedContainerIndex);
ErrorCode e = serverController.removeContainer(credentials, dockerContainer);
beginResetModel(); // todo change to begin remove rows?
m_settings->removeContainerConfig(m_currentlyProcessedServerIndex, dockerContainer);
m_containers = m_settings->containers(m_currentlyProcessedServerIndex);
if (m_defaultContainerIndex == m_currentlyProcessedContainerIndex) {
if (m_containers.isEmpty()) {
setData(index(DockerContainer::None, 0), true, IsDefaultRole);
} else {
setData(index(m_containers.begin().key(), 0), true, IsDefaultRole);
}
}
endResetModel();
}
void ContainersModel::clearCachedProfiles()
{
const auto &containers = m_settings->containers(m_currentlyProcessedServerIndex);
@ -150,6 +185,7 @@ QHash<int, QByteArray> ContainersModel::roleNames() const
roles[DescRole] = "description";
roles[ServiceTypeRole] = "serviceType";
roles[DockerContainerRole] = "dockerContainer";
roles[ConfigRole] = "config";
roles[IsEasySetupContainerRole] = "isEasySetupContainer";
roles[EasySetupHeaderRole] = "easySetupHeader";

View file

@ -45,10 +45,14 @@ public slots:
QString getDefaultContainerName();
void setCurrentlyProcessedServerIndex(const int index);
void setCurrentlyProcessedContainerIndex(int index);
int getCurrentlyProcessedContainerIndex();
QString getCurrentlyProcessedContainerName();
void removeAllContainers();
void removeCurrentlyProcessedContainer();
void clearCachedProfiles();
bool isAmneziaDnsContainerInstalled();

View file

@ -22,14 +22,8 @@ QVariant LanguageModel::data(const QModelIndex &index, int role) const
}
switch (role) {
case NameRole: {
return m_availableLanguages[index.row()].name;
break;
}
case IndexRole: {
return static_cast<int>(m_availableLanguages[index.row()].index);
break;
}
case NameRole: return m_availableLanguages[index.row()].name;
case IndexRole: return static_cast<int>(m_availableLanguages[index.row()].index);
}
return QVariant();
}

View file

@ -0,0 +1,81 @@
#include "cloakConfigModel.h"
#include "protocols/protocols_defs.h"
CloakConfigModel::CloakConfigModel(QObject *parent) : QAbstractListModel(parent)
{
}
int CloakConfigModel::rowCount(const QModelIndex &parent) const
{
Q_UNUSED(parent);
return 1;
}
bool CloakConfigModel::setData(const QModelIndex &index, const QVariant &value, int role)
{
if (!index.isValid() || index.row() < 0 || index.row() >= ContainerProps::allContainers().size()) {
return false;
}
switch (role) {
case Roles::PortRole: m_protocolConfig.insert(config_key::port, value.toString()); break;
case Roles::CipherRole: m_protocolConfig.insert(config_key::cipher, value.toString()); break;
case Roles::SiteRole: m_protocolConfig.insert(config_key::site, value.toString()); break;
}
emit dataChanged(index, index, QList { role });
return true;
}
QVariant CloakConfigModel::data(const QModelIndex &index, int role) const
{
if (!index.isValid() || index.row() < 0 || index.row() >= rowCount()) {
return false;
}
switch (role) {
case Roles::PortRole: return m_protocolConfig.value(config_key::port).toString(protocols::cloak::defaultPort);
case Roles::CipherRole: return m_protocolConfig.value(config_key::cipher).toString(protocols::cloak::defaultCipher);
case Roles::SiteRole: return m_protocolConfig.value(config_key::site).toString(protocols::cloak::defaultRedirSite);
}
return QVariant();
}
void CloakConfigModel::updateModel(const QJsonObject &config)
{
beginResetModel();
m_container = ContainerProps::containerFromString(config.value(config_key::container).toString());
m_fullConfig = config;
QJsonObject protocolConfig = config.value(config_key::cloak).toObject();
m_protocolConfig.insert(config_key::cipher,
protocolConfig.value(config_key::cipher).toString(protocols::cloak::defaultCipher));
m_protocolConfig.insert(config_key::port,
protocolConfig.value(config_key::port).toString(protocols::cloak::defaultPort));
m_protocolConfig.insert(config_key::site,
protocolConfig.value(config_key::site).toString(protocols::cloak::defaultRedirSite));
endResetModel();
}
QJsonObject CloakConfigModel::getConfig()
{
m_fullConfig.insert(config_key::cloak, m_protocolConfig);
return m_fullConfig;
}
QHash<int, QByteArray> CloakConfigModel::roleNames() const
{
QHash<int, QByteArray> roles;
roles[PortRole] = "port";
roles[CipherRole] = "cipher";
roles[SiteRole] = "site";
return roles;
}

View file

@ -0,0 +1,40 @@
#ifndef CLOAKCONFIGMODEL_H
#define CLOAKCONFIGMODEL_H
#include <QAbstractListModel>
#include <QJsonObject>
#include "containers/containers_defs.h"
class CloakConfigModel : public QAbstractListModel
{
Q_OBJECT
public:
enum Roles {
PortRole = Qt::UserRole + 1,
CipherRole,
SiteRole
};
explicit CloakConfigModel(QObject *parent = nullptr);
int rowCount(const QModelIndex &parent = QModelIndex()) const override;
bool setData(const QModelIndex &index, const QVariant &value, int role) override;
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
public slots:
void updateModel(const QJsonObject &config);
QJsonObject getConfig();
protected:
QHash<int, QByteArray> roleNames() const override;
private:
DockerContainer m_container;
QJsonObject m_protocolConfig;
QJsonObject m_fullConfig;
};
#endif // CLOAKCONFIGMODEL_H

View file

@ -0,0 +1,76 @@
#include "ikev2ConfigModel.h".h "
#include "protocols/protocols_defs.h"
Ikev2ConfigModel::Ikev2ConfigModel(QObject *parent) : QAbstractListModel(parent)
{
}
int Ikev2ConfigModel::rowCount(const QModelIndex &parent) const
{
Q_UNUSED(parent);
return 1;
}
bool Ikev2ConfigModel::setData(const QModelIndex &index, const QVariant &value, int role)
{
if (!index.isValid() || index.row() < 0 || index.row() >= ContainerProps::allContainers().size()) {
return false;
}
switch (role) {
case Roles::PortRole: m_protocolConfig.insert(config_key::port, value.toString()); break;
case Roles::CipherRole: m_protocolConfig.insert(config_key::cipher, value.toString()); break;
}
emit dataChanged(index, index, QList { role });
return true;
}
QVariant Ikev2ConfigModel::data(const QModelIndex &index, int role) const
{
if (!index.isValid() || index.row() < 0 || index.row() >= rowCount()) {
return false;
}
switch (role) {
case Roles::PortRole: return m_protocolConfig.value(config_key::port).toString(protocols::shadowsocks::defaultPort);
case Roles::CipherRole:
return m_protocolConfig.value(config_key::cipher).toString(protocols::shadowsocks::defaultCipher);
}
return QVariant();
}
void Ikev2ConfigModel::updateModel(const QJsonObject &config)
{
beginResetModel();
m_container = ContainerProps::containerFromString(config.value(config_key::container).toString());
m_fullConfig = config;
QJsonObject protocolConfig = config.value(config_key::shadowsocks).toObject();
m_protocolConfig.insert(config_key::cipher,
protocolConfig.value(config_key::cipher).toString(protocols::shadowsocks::defaultCipher));
m_protocolConfig.insert(config_key::port,
protocolConfig.value(config_key::port).toString(protocols::shadowsocks::defaultPort));
endResetModel();
}
QJsonObject Ikev2ConfigModel::getConfig()
{
m_fullConfig.insert(config_key::shadowsocks, m_protocolConfig);
return m_fullConfig;
}
QHash<int, QByteArray> Ikev2ConfigModel::roleNames() const
{
QHash<int, QByteArray> roles;
roles[PortRole] = "port";
roles[CipherRole] = "cipher";
return roles;
}

View file

@ -0,0 +1,39 @@
#ifndef IKEV2CONFIGMODEL_H
#define IKEV2CONFIGMODEL_H
#include <QAbstractListModel>
#include <QJsonObject>
#include "containers/containers_defs.h"
class Ikev2ConfigModel : public QAbstractListModel
{
Q_OBJECT
public:
enum Roles {
PortRole = Qt::UserRole + 1,
CipherRole
};
explicit Ikev2ConfigModel(QObject *parent = nullptr);
int rowCount(const QModelIndex &parent = QModelIndex()) const override;
bool setData(const QModelIndex &index, const QVariant &value, int role) override;
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
public slots:
void updateModel(const QJsonObject &config);
QJsonObject getConfig();
protected:
QHash<int, QByteArray> roleNames() const override;
private:
DockerContainer m_container;
QJsonObject m_protocolConfig;
QJsonObject m_fullConfig;
};
#endif // IKEV2CONFIGMODEL_H

View file

@ -0,0 +1,152 @@
#include "openvpnConfigModel.h"
#include "protocols/protocols_defs.h"
OpenVpnConfigModel::OpenVpnConfigModel(QObject *parent) : QAbstractListModel(parent)
{
}
int OpenVpnConfigModel::rowCount(const QModelIndex &parent) const
{
Q_UNUSED(parent);
return 1;
}
bool OpenVpnConfigModel::setData(const QModelIndex &index, const QVariant &value, int role)
{
if (!index.isValid() || index.row() < 0 || index.row() >= ContainerProps::allContainers().size()) {
return false;
}
switch (role) {
case Roles::SubnetAddressRole:
m_protocolConfig.insert(amnezia::config_key::subnet_address, value.toString());
break;
case Roles::TransportProtoRole: m_protocolConfig.insert(config_key::transport_proto, value.toString()); break;
case Roles::PortRole: m_protocolConfig.insert(config_key::port, value.toString()); break;
case Roles::AutoNegotiateEncryprionRole: m_protocolConfig.insert(config_key::ncp_disable, !value.toBool()); break;
case Roles::HashRole: m_protocolConfig.insert(config_key::hash, value.toString()); break;
case Roles::CipherRole: m_protocolConfig.insert(config_key::cipher, value.toString()); break;
case Roles::TlsAuthRole: m_protocolConfig.insert(config_key::tls_auth, value.toBool()); break;
case Roles::BlockDnsRole: m_protocolConfig.insert(config_key::block_outside_dns, value.toBool()); break;
case Roles::AdditionalClientCommandsRole:
m_protocolConfig.insert(config_key::additional_client_config, value.toString());
break;
case Roles::AdditionalServerCommandsRole:
m_protocolConfig.insert(config_key::additional_server_config, value.toString());
break;
}
emit dataChanged(index, index, QList { role });
return true;
}
QVariant OpenVpnConfigModel::data(const QModelIndex &index, int role) const
{
if (!index.isValid() || index.row() < 0 || index.row() >= rowCount()) {
return false;
}
switch (role) {
case Roles::SubnetAddressRole:
return m_protocolConfig.value(amnezia::config_key::subnet_address)
.toString(amnezia::protocols::openvpn::defaultSubnetAddress);
case Roles::TransportProtoRole:
return m_protocolConfig.value(config_key::transport_proto).toString(protocols::openvpn::defaultTransportProto);
case Roles::PortRole: return m_protocolConfig.value(config_key::port).toString(protocols::openvpn::defaultPort);
case Roles::AutoNegotiateEncryprionRole:
return !m_protocolConfig.value(config_key::ncp_disable).toBool(protocols::openvpn::defaultNcpDisable);
case Roles::HashRole: return m_protocolConfig.value(config_key::hash).toString(protocols::openvpn::defaultHash);
case Roles::CipherRole:
return m_protocolConfig.value(config_key::cipher).toString(protocols::openvpn::defaultCipher);
case Roles::TlsAuthRole:
return m_protocolConfig.value(config_key::tls_auth).toBool(protocols::openvpn::defaultTlsAuth);
case Roles::BlockDnsRole:
return m_protocolConfig.value(config_key::block_outside_dns).toBool(protocols::openvpn::defaultBlockOutsideDns);
case Roles::AdditionalClientCommandsRole:
return m_protocolConfig.value(config_key::additional_client_config)
.toString(protocols::openvpn::defaultAdditionalClientConfig);
case Roles::AdditionalServerCommandsRole:
return m_protocolConfig.value(config_key::additional_server_config)
.toString(protocols::openvpn::defaultAdditionalServerConfig);
case Roles::IsPortEditable: return m_container == DockerContainer::OpenVpn ? true : false;
case Roles::IsTransportProtoEditable: return m_container == DockerContainer::OpenVpn ? true : false;
case Roles::HasRemoveButton: return m_container == DockerContainer::OpenVpn ? true : false;
}
return QVariant();
}
void OpenVpnConfigModel::updateModel(const QJsonObject &config)
{
beginResetModel();
m_container =
ContainerProps::containerFromString(config.value(config_key::container).toString()); // todo maybe unused
m_fullConfig = config;
QJsonObject protocolConfig = config.value(config_key::openvpn).toObject();
m_protocolConfig.insert(config_key::subnet_address,
protocolConfig.value(amnezia::config_key::subnet_address)
.toString(amnezia::protocols::openvpn::defaultSubnetAddress));
QString transportProto;
if (m_container == DockerContainer::OpenVpn) {
transportProto =
protocolConfig.value(config_key::transport_proto).toString(protocols::openvpn::defaultTransportProto);
} else {
transportProto = "tcp";
}
m_protocolConfig.insert(config_key::transport_proto, transportProto);
m_protocolConfig.insert(config_key::ncp_disable,
protocolConfig.value(config_key::ncp_disable).toBool(protocols::openvpn::defaultNcpDisable));
m_protocolConfig.insert(config_key::cipher,
protocolConfig.value(config_key::cipher).toString(protocols::openvpn::defaultCipher));
m_protocolConfig.insert(config_key::hash,
protocolConfig.value(config_key::hash).toString(protocols::openvpn::defaultHash));
m_protocolConfig.insert(config_key::block_outside_dns,
protocolConfig.value(config_key::tls_auth).toBool(protocols::openvpn::defaultTlsAuth));
m_protocolConfig.insert(config_key::port,
protocolConfig.value(config_key::port).toString(protocols::openvpn::defaultPort));
m_protocolConfig.insert(
config_key::tls_auth,
protocolConfig.value(config_key::block_outside_dns).toBool(protocols::openvpn::defaultBlockOutsideDns));
m_protocolConfig.insert(config_key::additional_client_config,
protocolConfig.value(config_key::additional_client_config)
.toString(protocols::openvpn::defaultAdditionalClientConfig));
m_protocolConfig.insert(config_key::additional_server_config,
protocolConfig.value(config_key::additional_server_config)
.toString(protocols::openvpn::defaultAdditionalServerConfig));
endResetModel();
}
QJsonObject OpenVpnConfigModel::getConfig()
{
m_fullConfig.insert(config_key::openvpn, m_protocolConfig);
return m_fullConfig;
}
QHash<int, QByteArray> OpenVpnConfigModel::roleNames() const
{
QHash<int, QByteArray> roles;
roles[SubnetAddressRole] = "subnetAddress";
roles[TransportProtoRole] = "transportProto";
roles[PortRole] = "port";
roles[AutoNegotiateEncryprionRole] = "autoNegotiateEncryprion";
roles[HashRole] = "hash";
roles[CipherRole] = "cipher";
roles[TlsAuthRole] = "tlsAuth";
roles[BlockDnsRole] = "blockDns";
roles[AdditionalClientCommandsRole] = "additionalClientCommands";
roles[AdditionalServerCommandsRole] = "additionalServerCommands";
roles[IsPortEditable] = "isPortEditable";
roles[IsTransportProtoEditable] = "isTransportProtoEditable";
roles[HasRemoveButton] = "hasRemoveButton";
return roles;
}

View file

@ -0,0 +1,52 @@
#ifndef OPENVPNCONFIGMODEL_H
#define OPENVPNCONFIGMODEL_H
#include <QAbstractListModel>
#include <QJsonObject>
#include "containers/containers_defs.h"
class OpenVpnConfigModel : public QAbstractListModel
{
Q_OBJECT
public:
enum Roles {
SubnetAddressRole = Qt::UserRole + 1,
TransportProtoRole,
PortRole,
AutoNegotiateEncryprionRole,
HashRole,
CipherRole,
TlsAuthRole,
BlockDnsRole,
AdditionalClientCommandsRole,
AdditionalServerCommandsRole,
IsPortEditable,
IsTransportProtoEditable,
HasRemoveButton
};
explicit OpenVpnConfigModel(QObject *parent = nullptr);
int rowCount(const QModelIndex &parent = QModelIndex()) const override;
bool setData(const QModelIndex &index, const QVariant &value, int role) override;
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
public slots:
void updateModel(const QJsonObject &config);
QJsonObject getConfig();
protected:
QHash<int, QByteArray> roleNames() const override;
private:
DockerContainer m_container;
QJsonObject m_protocolConfig;
QJsonObject m_fullConfig;
};
#endif // OPENVPNCONFIGMODEL_H

View file

@ -0,0 +1,76 @@
#include "shadowsocksConfigModel.h"
#include "protocols/protocols_defs.h"
ShadowSocksConfigModel::ShadowSocksConfigModel(QObject *parent) : QAbstractListModel(parent)
{
}
int ShadowSocksConfigModel::rowCount(const QModelIndex &parent) const
{
Q_UNUSED(parent);
return 1;
}
bool ShadowSocksConfigModel::setData(const QModelIndex &index, const QVariant &value, int role)
{
if (!index.isValid() || index.row() < 0 || index.row() >= ContainerProps::allContainers().size()) {
return false;
}
switch (role) {
case Roles::PortRole: m_protocolConfig.insert(config_key::port, value.toString()); break;
case Roles::CipherRole: m_protocolConfig.insert(config_key::cipher, value.toString()); break;
}
emit dataChanged(index, index, QList { role });
return true;
}
QVariant ShadowSocksConfigModel::data(const QModelIndex &index, int role) const
{
if (!index.isValid() || index.row() < 0 || index.row() >= rowCount()) {
return false;
}
switch (role) {
case Roles::PortRole: return m_protocolConfig.value(config_key::port).toString(protocols::shadowsocks::defaultPort);
case Roles::CipherRole:
return m_protocolConfig.value(config_key::cipher).toString(protocols::shadowsocks::defaultCipher);
}
return QVariant();
}
void ShadowSocksConfigModel::updateModel(const QJsonObject &config)
{
beginResetModel();
m_container = ContainerProps::containerFromString(config.value(config_key::container).toString());
m_fullConfig = config;
QJsonObject protocolConfig = config.value(config_key::shadowsocks).toObject();
m_protocolConfig.insert(config_key::cipher,
protocolConfig.value(config_key::cipher).toString(protocols::shadowsocks::defaultCipher));
m_protocolConfig.insert(config_key::port,
protocolConfig.value(config_key::port).toString(protocols::shadowsocks::defaultPort));
endResetModel();
}
QJsonObject ShadowSocksConfigModel::getConfig()
{
m_fullConfig.insert(config_key::shadowsocks, m_protocolConfig);
return m_fullConfig;
}
QHash<int, QByteArray> ShadowSocksConfigModel::roleNames() const
{
QHash<int, QByteArray> roles;
roles[PortRole] = "port";
roles[CipherRole] = "cipher";
return roles;
}

View file

@ -0,0 +1,39 @@
#ifndef SHADOWSOCKSCONFIGMODEL_H
#define SHADOWSOCKSCONFIGMODEL_H
#include <QAbstractListModel>
#include <QJsonObject>
#include "containers/containers_defs.h"
class ShadowSocksConfigModel : public QAbstractListModel
{
Q_OBJECT
public:
enum Roles {
PortRole = Qt::UserRole + 1,
CipherRole
};
explicit ShadowSocksConfigModel(QObject *parent = nullptr);
int rowCount(const QModelIndex &parent = QModelIndex()) const override;
bool setData(const QModelIndex &index, const QVariant &value, int role) override;
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
public slots:
void updateModel(const QJsonObject &config);
QJsonObject getConfig();
protected:
QHash<int, QByteArray> roleNames() const override;
private:
DockerContainer m_container;
QJsonObject m_protocolConfig;
QJsonObject m_fullConfig;
};
#endif // SHADOWSOCKSCONFIGMODEL_H

View file

@ -0,0 +1,70 @@
#include "wireguardConfigModel.h"
#include "protocols/protocols_defs.h"
WireGuardConfigModel::WireGuardConfigModel(QObject *parent) : QAbstractListModel(parent)
{
}
int WireGuardConfigModel::rowCount(const QModelIndex &parent) const
{
Q_UNUSED(parent);
return 1;
}
bool WireGuardConfigModel::setData(const QModelIndex &index, const QVariant &value, int role)
{
if (!index.isValid() || index.row() < 0 || index.row() >= ContainerProps::allContainers().size()) {
return false;
}
switch (role) {
case Roles::PortRole: m_protocolConfig.insert(config_key::port, value.toString()); break;
case Roles::CipherRole: m_protocolConfig.insert(config_key::cipher, value.toString()); break;
}
emit dataChanged(index, index, QList { role });
return true;
}
QVariant WireGuardConfigModel::data(const QModelIndex &index, int role) const
{
if (!index.isValid() || index.row() < 0 || index.row() >= rowCount()) {
return false;
}
switch (role) {
case Roles::PortRole: return m_protocolConfig.value(config_key::port).toString(protocols::shadowsocks::defaultPort);
case Roles::CipherRole:
return m_protocolConfig.value(config_key::cipher).toString(protocols::shadowsocks::defaultCipher);
}
return QVariant();
}
void WireGuardConfigModel::updateModel(const QJsonObject &config)
{
beginResetModel();
m_container = ContainerProps::containerFromString(config.value(config_key::container).toString());
m_fullConfig = config;
QJsonObject protocolConfig = config.value(config_key::wireguard).toObject();
endResetModel();
}
QJsonObject WireGuardConfigModel::getConfig()
{
m_fullConfig.insert(config_key::wireguard, m_protocolConfig);
return m_fullConfig;
}
QHash<int, QByteArray> WireGuardConfigModel::roleNames() const
{
QHash<int, QByteArray> roles;
roles[PortRole] = "port";
roles[CipherRole] = "cipher";
return roles;
}

View file

@ -0,0 +1,39 @@
#ifndef WIREGUARDCONFIGMODEL_H
#define WIREGUARDCONFIGMODEL_H
#include <QAbstractListModel>
#include <QJsonObject>
#include "containers/containers_defs.h"
class WireGuardConfigModel : public QAbstractListModel
{
Q_OBJECT
public:
enum Roles {
PortRole = Qt::UserRole + 1,
CipherRole
};
explicit WireGuardConfigModel(QObject *parent = nullptr);
int rowCount(const QModelIndex &parent = QModelIndex()) const override;
bool setData(const QModelIndex &index, const QVariant &value, int role) override;
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
public slots:
void updateModel(const QJsonObject &config);
QJsonObject getConfig();
protected:
QHash<int, QByteArray> roleNames() const override;
private:
DockerContainer m_container;
QJsonObject m_protocolConfig;
QJsonObject m_fullConfig;
};
#endif // WIREGUARDCONFIGMODEL_H

View file

@ -1,62 +1,73 @@
#include "protocols_model.h"
ProtocolsModel::ProtocolsModel(std::shared_ptr<Settings> settings, QObject *parent) :
m_settings(settings),
QAbstractListModel(parent)
ProtocolsModel::ProtocolsModel(std::shared_ptr<Settings> settings, QObject *parent)
: m_settings(settings), QAbstractListModel(parent)
{
}
int ProtocolsModel::rowCount(const QModelIndex &parent) const
{
Q_UNUSED(parent);
return ProtocolProps::allProtocols().size();
return m_content.size();
}
QHash<int, QByteArray> ProtocolsModel::roleNames() const {
QHash<int, QByteArray> ProtocolsModel::roleNames() const
{
QHash<int, QByteArray> roles;
roles[NameRole] = "name_role";
roles[DescRole] = "desc_role";
roles[ServiceTypeRole] = "service_type_role";
roles[IsInstalledRole] = "is_installed_role";
roles[ProtocolNameRole] = "protocolName";
roles[ProtocolPageRole] = "protocolPage";
return roles;
}
QVariant ProtocolsModel::data(const QModelIndex &index, int role) const
{
if (!index.isValid() || index.row() < 0
|| index.row() >= ProtocolProps::allProtocols().size()) {
if (!index.isValid() || index.row() < 0 || index.row() >= m_content.size()) {
return QVariant();
}
Proto p = ProtocolProps::allProtocols().at(index.row());
if (role == NameRole) {
return ProtocolProps::protocolHumanNames().value(p);
switch (role) {
case ProtocolNameRole: {
amnezia::Proto proto = ProtocolProps::protoFromString(m_content.keys().at(index.row()));
return ProtocolProps::protocolHumanNames().value(proto);
}
if (role == DescRole) {
return ProtocolProps::protocolDescriptions().value(p);
}
if (role == ServiceTypeRole) {
return ProtocolProps::protocolService(p);
}
if (role == IsInstalledRole) {
return ContainerProps::protocolsForContainer(m_selectedDockerContainer).contains(p);
case ProtocolPageRole:
return static_cast<int>(protocolPage(ProtocolProps::protoFromString(m_content.keys().at(index.row()))));
}
return QVariant();
}
void ProtocolsModel::setSelectedServerIndex(int index)
void ProtocolsModel::updateModel(const QJsonObject &content)
{
beginResetModel();
m_selectedServerIndex = index;
endResetModel();
m_container = ContainerProps::containerFromString(content.value(config_key::container).toString());
m_content = content;
m_content.remove(config_key::container);
}
void ProtocolsModel::setSelectedDockerContainer(DockerContainer c)
QJsonObject ProtocolsModel::getConfig()
{
beginResetModel();
m_selectedDockerContainer = c;
endResetModel();
QJsonObject config = m_content;
config.insert(config_key::container, ContainerProps::containerToString(m_container));
return config;
}
PageLoader::PageEnum ProtocolsModel::protocolPage(Proto protocol) const
{
switch (protocol) {
case Proto::OpenVpn: return PageLoader::PageEnum::PageProtocolOpenVpnSettings;
case Proto::Cloak: return PageLoader::PageEnum::PageProtocolCloakSettings;
case Proto::ShadowSocks: return PageLoader::PageEnum::PageProtocolShadowSocksSettings;
case Proto::WireGuard: return PageLoader::PageEnum::PageProtocolWireGuardSettings;
case Proto::Ikev2: return PageLoader::PageEnum::PageProtocolIKev2Settings;
case Proto::L2tp: return PageLoader::PageEnum::PageProtocolOpenVpnSettings;
// non-vpn
case Proto::TorWebSite: return PageLoader::PageEnum::PageProtocolOpenVpnSettings;
case Proto::Dns: return PageLoader::PageEnum::PageProtocolOpenVpnSettings;
case Proto::FileShare: return PageLoader::PageEnum::PageProtocolOpenVpnSettings;
case Proto::Sftp: return PageLoader::PageEnum::PageProtocolOpenVpnSettings;
default: return PageLoader::PageEnum::PageProtocolOpenVpnSettings;
}
}

View file

@ -3,38 +3,40 @@
#include <QAbstractListModel>
#include <QJsonObject>
#include <vector>
#include <utility>
#include "../controllers/pageController.h"
#include "settings.h"
#include "containers/containers_defs.h"
class ProtocolsModel : public QAbstractListModel
{
Q_OBJECT
public:
ProtocolsModel(std::shared_ptr<Settings> settings, QObject *parent = nullptr);
public:
enum SiteRoles {
NameRole = Qt::UserRole + 1,
DescRole,
ServiceTypeRole,
IsInstalledRole
enum Roles {
ProtocolNameRole = Qt::UserRole + 1,
ProtocolPageRole
};
ProtocolsModel(std::shared_ptr<Settings> settings, QObject *parent = nullptr);
int rowCount(const QModelIndex &parent = QModelIndex()) const override;
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
Q_INVOKABLE void setSelectedServerIndex(int index);
Q_INVOKABLE void setSelectedDockerContainer(DockerContainer c);
public slots:
void updateModel(const QJsonObject &content);
QJsonObject getConfig();
protected:
QHash<int, QByteArray> roleNames() const override;
private:
int m_selectedServerIndex;
DockerContainer m_selectedDockerContainer;
PageLoader::PageEnum protocolPage(Proto protocol) const;
std::shared_ptr<Settings> m_settings;
DockerContainer m_container;
QJsonObject m_content;
};
#endif // PROTOCOLS_MODEL_H

View file

@ -123,6 +123,7 @@ bool ServersModel::isDefaultServerHasWriteAccess()
void ServersModel::addServer(const QJsonObject &server)
{
// todo beginInsertRows()?
beginResetModel();
m_settings->addServer(server);
m_servers = m_settings->serversArray();

View file

@ -1,13 +1,11 @@
#include "GeneralSettingsLogic.h"
#include "ShareConnectionLogic.h"
#include "../uilogic.h"
#include "../models/protocols_model.h"
#include "../uilogic.h"
GeneralSettingsLogic::GeneralSettingsLogic(UiLogic *logic, QObject *parent):
PageLogicBase(logic, parent)
GeneralSettingsLogic::GeneralSettingsLogic(UiLogic *logic, QObject *parent) : PageLogicBase(logic, parent)
{
}
void GeneralSettingsLogic::onUpdatePage()
@ -32,9 +30,11 @@ void GeneralSettingsLogic::onPushButtonGeneralSettingsShareConnectionClicked()
uiLogic()->m_selectedServerIndex = m_settings->defaultServerIndex();
uiLogic()->m_selectedDockerContainer = m_settings->defaultContainer(uiLogic()->m_selectedServerIndex);
qobject_cast<ProtocolsModel *>(uiLogic()->protocolsModel())->setSelectedServerIndex(uiLogic()->m_selectedServerIndex);
qobject_cast<ProtocolsModel *>(uiLogic()->protocolsModel())->setSelectedDockerContainer(uiLogic()->m_selectedDockerContainer);
// qobject_cast<ProtocolsModel
// *>(uiLogic()->protocolsModel())->setSelectedServerIndex(uiLogic()->m_selectedServerIndex); qobject_cast<ProtocolsModel
// *>(uiLogic()->protocolsModel())->setSelectedDockerContainer(uiLogic()->m_selectedDockerContainer);
uiLogic()->pageLogic<ShareConnectionLogic>()->updateSharingPage(uiLogic()->m_selectedServerIndex, uiLogic()->m_selectedDockerContainer);
uiLogic()->pageLogic<ShareConnectionLogic>()->updateSharingPage(uiLogic()->m_selectedServerIndex,
uiLogic()->m_selectedDockerContainer);
emit uiLogic()->goToPage(Page::ShareConnection);
}

View file

@ -1,6 +1,6 @@
#include "ServerContainersLogic.h"
#include "ShareConnectionLogic.h"
#include "ServerConfiguringProgressLogic.h"
#include "ShareConnectionLogic.h"
#include <QApplication>
@ -9,24 +9,22 @@
#include "core/servercontroller.h"
#include <functional>
#include "../uilogic.h"
#include "../pages_logic/VpnLogic.h"
#include "vpnconnection.h"
#include "../uilogic.h"
#include "core/errorstrings.h"
#include "vpnconnection.h"
ServerContainersLogic::ServerContainersLogic(UiLogic *logic, QObject *parent):
PageLogicBase(logic, parent)
ServerContainersLogic::ServerContainersLogic(UiLogic *logic, QObject *parent) : PageLogicBase(logic, parent)
{
}
void ServerContainersLogic::onUpdatePage()
{
// ContainersModel *c_model = qobject_cast<ContainersModel *>(uiLogic()->containersModel());
// c_model->setSelectedServerIndex(uiLogic()->m_selectedServerIndex);
// ContainersModel *c_model = qobject_cast<ContainersModel *>(uiLogic()->containersModel());
// c_model->setSelectedServerIndex(uiLogic()->m_selectedServerIndex);
ProtocolsModel *p_model = qobject_cast<ProtocolsModel *>(uiLogic()->protocolsModel());
p_model->setSelectedServerIndex(uiLogic()->m_selectedServerIndex);
// p_model->setSelectedServerIndex(uiLogic()->m_selectedServerIndex);
set_isManagedServer(m_settings->haveAuthData(uiLogic()->m_selectedServerIndex));
uiLogic()->m_installCredentials = m_settings->serverCredentials(uiLogic()->m_selectedServerIndex);
@ -35,25 +33,29 @@ void ServerContainersLogic::onUpdatePage()
void ServerContainersLogic::onPushButtonProtoSettingsClicked(DockerContainer c, Proto p)
{
qDebug()<< "ServerContainersLogic::onPushButtonProtoSettingsClicked" << c << p;
qDebug() << "ServerContainersLogic::onPushButtonProtoSettingsClicked" << c << p;
uiLogic()->m_selectedDockerContainer = c;
uiLogic()->protocolLogic(p)->updateProtocolPage(m_settings->protocolConfig(uiLogic()->m_selectedServerIndex, uiLogic()->m_selectedDockerContainer, p),
uiLogic()->m_selectedDockerContainer,
m_settings->haveAuthData(uiLogic()->m_selectedServerIndex));
uiLogic()->protocolLogic(p)->updateProtocolPage(
m_settings->protocolConfig(uiLogic()->m_selectedServerIndex, uiLogic()->m_selectedDockerContainer, p),
uiLogic()->m_selectedDockerContainer, m_settings->haveAuthData(uiLogic()->m_selectedServerIndex));
emit uiLogic()->goToProtocolPage(p);
}
void ServerContainersLogic::onPushButtonDefaultClicked(DockerContainer c)
{
if (m_settings->defaultContainer(uiLogic()->m_selectedServerIndex) == c) return;
if (m_settings->defaultContainer(uiLogic()->m_selectedServerIndex) == c)
return;
m_settings->setDefaultContainer(uiLogic()->m_selectedServerIndex, c);
uiLogic()->onUpdateAllPages();
if (uiLogic()->m_selectedServerIndex != m_settings->defaultServerIndex()) return;
if (!uiLogic()->m_vpnConnection) return;
if (!uiLogic()->m_vpnConnection->isConnected()) return;
if (uiLogic()->m_selectedServerIndex != m_settings->defaultServerIndex())
return;
if (!uiLogic()->m_vpnConnection)
return;
if (!uiLogic()->m_vpnConnection->isConnected())
return;
uiLogic()->pageLogic<VpnLogic>()->onDisconnect();
uiLogic()->pageLogic<VpnLogic>()->onConnect();
@ -67,16 +69,19 @@ void ServerContainersLogic::onPushButtonShareClicked(DockerContainer c)
void ServerContainersLogic::onPushButtonRemoveClicked(DockerContainer container)
{
//buttonSetEnabledFunc(false);
// buttonSetEnabledFunc(false);
ServerController serverController(m_settings);
ErrorCode e = serverController.removeContainer(m_settings->serverCredentials(uiLogic()->m_selectedServerIndex), container);
ErrorCode e =
serverController.removeContainer(m_settings->serverCredentials(uiLogic()->m_selectedServerIndex), container);
m_settings->removeContainerConfig(uiLogic()->m_selectedServerIndex, container);
//buttonSetEnabledFunc(true);
// buttonSetEnabledFunc(true);
if (m_settings->defaultContainer(uiLogic()->m_selectedServerIndex) == container) {
const auto &c = m_settings->containers(uiLogic()->m_selectedServerIndex);
if (c.isEmpty()) m_settings->setDefaultContainer(uiLogic()->m_selectedServerIndex, DockerContainer::None);
else m_settings->setDefaultContainer(uiLogic()->m_selectedServerIndex, c.keys().first());
if (c.isEmpty())
m_settings->setDefaultContainer(uiLogic()->m_selectedServerIndex, DockerContainer::None);
else
m_settings->setDefaultContainer(uiLogic()->m_selectedServerIndex, c.keys().first());
}
uiLogic()->onUpdateAllPages();
}
@ -96,7 +101,8 @@ void ServerContainersLogic::onPushButtonContinueClicked(DockerContainer c, int p
if (!uiLogic()->isContainerAlreadyAddedToGui(c)) {
auto installAction = [this, c, &config]() {
ServerController serverController(m_settings);
return serverController.setupContainer(m_settings->serverCredentials(uiLogic()->m_selectedServerIndex), c, config);
return serverController.setupContainer(m_settings->serverCredentials(uiLogic()->m_selectedServerIndex),
c, config);
};
errorCode = uiLogic()->pageLogic<ServerConfiguringProgressLogic>()->doInstallAction(installAction);
@ -107,16 +113,16 @@ void ServerContainersLogic::onPushButtonContinueClicked(DockerContainer c, int p
}
}
} else {
emit uiLogic()->showWarningMessage("Attention! The container you are trying to install is already installed on the server. "
"All installed containers have been added to the application ");
emit uiLogic()->showWarningMessage(
"Attention! The container you are trying to install is already installed on the server. "
"All installed containers have been added to the application ");
}
uiLogic()->onUpdateAllPages();
}
if (errorCode != ErrorCode::NoError) {
emit uiLogic()->showWarningMessage(tr("Error occurred while configuring server.") + "\n" +
tr("Error message: ") + errorString(errorCode) + "\n" +
tr("See logs for details."));
emit uiLogic()->showWarningMessage(tr("Error occurred while configuring server.") + "\n" + tr("Error message: ")
+ errorString(errorCode) + "\n" + tr("See logs for details."));
}
emit uiLogic()->closePage();
}

View file

@ -1,147 +0,0 @@
import QtQuick 2.15
import QtQuick.Controls
import QtQuick.Layouts
import "../../Controls2"
import "../../Controls2/TextTypes"
import "../../Components"
Item {
id: root
implicitHeight: col.implicitHeight
implicitWidth: col.implicitWidth
ColumnLayout {
id: col
anchors.fill: parent
anchors.leftMargin: 16
anchors.rightMargin: 16
spacing: 16
Header2TextType {
Layout.fillWidth: true
text: "OpenVpn"
}
TextFieldWithHeaderType {
Layout.fillWidth: true
headerText: qsTr("VPN Addresses Subnet")
}
ParagraphTextType {
Layout.fillWidth: true
text: qsTr("Network protocol")
}
TransportProtoSelector {
Layout.fillWidth: true
}
TextFieldWithHeaderType {
Layout.fillWidth: true
headerText: qsTr("Port")
}
SwitcherType {
Layout.fillWidth: true
text: qsTr("Auto-negotiate encryption")
}
DropDownType {
id: hash
Layout.fillWidth: true
implicitHeight: 74
descriptionText: qsTr("Hash")
headerText: qsTr("Hash")
listView: ListViewType {
rootWidth: root.width
model: ListModel {
ListElement { name : qsTr("SHA512") }
ListElement { name : qsTr("SHA384") }
ListElement { name : qsTr("SHA256") }
ListElement { name : qsTr("SHA3-512") }
ListElement { name : qsTr("SHA3-384") }
ListElement { name : qsTr("SHA3-256") }
ListElement { name : qsTr("whirlpool") }
ListElement { name : qsTr("BLAKE2b512") }
ListElement { name : qsTr("BLAKE2s256") }
ListElement { name : qsTr("SHA1") }
}
currentIndex: 0
clickedFunction: {
hash.text = selectedText
hash.menuVisible = false
}
Component.onCompleted: {
hash.text = selectedText
}
}
}
DropDownType {
id: cipher
Layout.fillWidth: true
implicitHeight: 74
descriptionText: qsTr("Cipher")
headerText: qsTr("Cipher")
listView: ListViewType {
rootWidth: root.width
model: ListModel {
ListElement { name : qsTr("AES-256-GCM") }
ListElement { name : qsTr("AES-192-GCM") }
ListElement { name : qsTr("AES-128-GCM") }
ListElement { name : qsTr("AES-256-CBC") }
ListElement { name : qsTr("AES-192-CBC") }
ListElement { name : qsTr("AES-128-CBC") }
ListElement { name : qsTr("ChaCha20-Poly1305") }
ListElement { name : qsTr("ARIA-256-CBC") }
ListElement { name : qsTr("CAMELLIA-256-CBC") }
ListElement { name : qsTr("none") }
}
currentIndex: 0
clickedFunction: {
cipher.text = selectedText
cipher.menuVisible = false
}
Component.onCompleted: {
cipher.text = selectedText
}
}
}
CheckBoxType {
Layout.fillWidth: true
text: qsTr("TLS auth")
}
CheckBoxType {
Layout.fillWidth: true
text: qsTr("Block DNS requests outside of VPN")
}
SwitcherType {
Layout.fillWidth: true
text: qsTr("Additional configuration commands")
}
}
}

View file

@ -6,6 +6,7 @@ import SortFilterProxyModel 0.2
import PageEnum 1.0
import ProtocolEnum 1.0
import ContainerEnum 1.0
import "../Controls2"
import "../Controls2/TextTypes"
@ -88,8 +89,32 @@ ListView {
onClicked: {
if (isInstalled) {
ContainersModel.setCurrentlyProcessedContainerIndex(root.model.mapToSource(index))
goToPage(PageEnum.PageSettingsServerProtocol)
var containerIndex = root.model.mapToSource(index)
ContainersModel.setCurrentlyProcessedContainerIndex(containerIndex)
switch (containerIndex) {
case ContainerEnum.OpenVpn: {
OpenVpnConfigModel.updateModel(ProtocolsModel.getConfig())
goToPage(PageEnum.PageProtocolOpenVpnSettings)
break
}
case ContainerEnum.WireGuard: {
WireGuardConfigModel.updateModel(ProtocolsModel.getConfig())
goToPage(PageEnum.PageProtocolWireGuardSettings)
break
}
case ContainerEnum.Ipsec: {
Ikev2ConfigModel.updateModel(ProtocolsModel.getConfig())
goToPage(PageEnum.PageProtocolIKev2Settings)
break
}
default: {
if (serviceType !== ProtocolEnum.Other) { //todo disable settings for dns container
ProtocolsModel.updateModel(config)
goToPage(PageEnum.PageSettingsServerProtocol)
}
}
}
} else {
ContainersModel.setCurrentlyProcessedContainerIndex(root.model.mapToSource(index))
InstallController.setShouldCreateServer(false)

View file

@ -75,9 +75,9 @@ DrawerType {
text: qsTr("Copy")
onClicked: {
configContent.selectAll()
configContent.copy()
configContent.select(0, 0)
configText.selectAll()
configText.copy()
configText.select(0, 0)
}
}
@ -138,6 +138,8 @@ DrawerType {
}
TextArea {
id: configText
Layout.fillWidth: true
Layout.topMargin: 16
Layout.bottomMargin: 16

View file

@ -25,6 +25,8 @@ Rectangle {
HorizontalRadioButton {
checked: root.currentIndex === 0
hoverEnabled: root.enabled
implicitWidth: (rootWidth - 32) / 2
text: "UDP"
@ -36,6 +38,8 @@ Rectangle {
HorizontalRadioButton {
checked: root.currentIndex === 1
hoverEnabled: root.enabled
implicitWidth: (rootWidth - 32) / 2
text: "TCP"

View file

@ -3,6 +3,8 @@ import QtQuick.Controls
import QtQuick.Layouts
import Qt5Compat.GraphicalEffects
import "TextTypes"
CheckBox {
id: root
@ -26,6 +28,8 @@ CheckBox {
indicator: Rectangle {
id: checkBoxBackground
anchors.verticalCenter: parent.verticalCenter
implicitWidth: 56
implicitHeight: 56
radius: 16
@ -57,43 +61,41 @@ CheckBox {
anchors.centerIn: parent
source: root.pressed ? imageSource : root.checked ? imageSource : ""
ColorOverlay {
id: imageColor
anchors.fill: indicator
source: indicator
color: root.pressed ? pressedImageColor : root.checked ? checkedImageColor : defaultImageColor
layer {
enabled: true
effect: ColorOverlay {
color: root.pressed ? pressedImageColor : root.checked ? checkedImageColor : defaultImageColor
}
}
}
}
}
contentItem: ColumnLayout {
anchors.fill: parent
anchors.left: parent.left
anchors.right: parent.right
anchors.leftMargin: 8 + checkBoxBackground.width
Text {
text: root.text
color: "#D7D8DB"
font.pixelSize: 18
font.weight: 400
font.family: "PT Root UI VF"
spacing: 4
height: 22
ListItemTitleType {
Layout.fillWidth: true
// Layout.topMargin: 16
// Layout.bottomMargin: description.visible ? 0 : 16
text: root.text
}
Text {
CaptionTextType {
id: description
Layout.fillWidth: true
Layout.bottomMargin: 16
text: root.descriptionText
color: "#878b91"
font.pixelSize: 13
font.weight: 400
font.family: "PT Root UI VF"
font.letterSpacing: 0.02
height: 16
Layout.fillWidth: true
visible: root.descriptionText !== ""
}
}

View file

@ -9,8 +9,11 @@ Item {
property string text
property string textColor: "#d7d8db"
property string textDisabledColor: "#878B91"
property string descriptionText
property string descriptionTextColor: "#878B91"
property string descriptionTextDisabledColor: "#494B50"
property string headerText
property string headerBackButtonImage
@ -23,7 +26,6 @@ Item {
property string rootButtonHoveredBorderColor: "#494B50"
property string rootButtonDefaultBorderColor: "transparent"
property string rootButtonPressedBorderColor: "#D7D8DB"
property int rootButtonBorderWidth: 1
property real drawerHeight: 0.9
property Component listView
@ -36,10 +38,18 @@ Item {
onMenuVisibleChanged: {
if (menuVisible) {
rootButtonBackground.border.color = rootButtonPressedBorderColor
rootButtonBackground.border.width = rootButtonBorderWidth
} else {
rootButtonBackground.border.color = rootButtonDefaultBorderColor
rootButtonBackground.border.width = 0
}
}
onEnabledChanged: {
if (enabled) {
rootButtonBackground.color = rootButtonBackgroundColor
rootButtonBackground.border.color = rootButtonDefaultBorderColor
} else {
rootButtonBackground.color = "transparent"
rootButtonBackground.border.color = rootButtonHoveredBorderColor
}
}
@ -48,13 +58,10 @@ Item {
anchors.fill: rootButtonContent
radius: 16
color: rootButtonBackgroundColor
border.color: rootButtonDefaultBorderColor
border.width: 0
color: root.enabled ? rootButtonBackgroundColor : "transparent"
border.color: root.enabled ? rootButtonDefaultBorderColor : rootButtonHoveredBorderColor
border.width: 1
Behavior on border.width {
PropertyAnimation { duration: 200 }
}
Behavior on border.color {
PropertyAnimation { duration: 200 }
}
@ -77,7 +84,7 @@ Item {
visible: root.descriptionText !== ""
color: "#878B91"
color: root.enabled ? root.descriptionTextColor : root.descriptionTextDisabledColor
text: root.descriptionText
}
@ -87,7 +94,7 @@ Item {
horizontalAlignment: Text.AlignLeft
verticalAlignment: Text.AlignVCenter
color: root.textColor
color: root.enabled ? root.textColor : root.textDisabledColor
text: root.text
wrapMode: Text.NoWrap
@ -108,18 +115,16 @@ Item {
MouseArea {
anchors.fill: rootButtonContent
cursorShape: Qt.PointingHandCursor
hoverEnabled: true
hoverEnabled: root.enabled ? true : false
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
}
}

View file

@ -22,45 +22,44 @@ RadioButton {
implicitWidth: content.implicitWidth
implicitHeight: content.implicitHeight
hoverEnabled: true
indicator: Rectangle {
anchors.fill: parent
radius: 16
color: {
if (root.enabled) {
// if (root.enabled) {
if (root.hovered) {
return hoveredColor
} else if (root.checked) {
return selectedColor
}
return defaultColor
} else {
return disabledColor
}
// } else {
// return disabledColor
// }
}
border.color: {
if (root.enabled) {
// if (root.enabled) {
if (root.pressed) {
return pressedBorderColor
} else if (root.checked) {
return selectedBorderColor
}
}
return defaultBodredColor
return defaultBodredColor
// }
// return defaultBodredColor
}
border.width: {
if (root.enabled) {
// if (root.enabled) {
if(root.checked) {
return 1
}
return root.pressed ? 1 : 0
} else {
return 0
}
// } else {
// return 0
// }
}
Behavior on color {

View file

@ -8,6 +8,9 @@ Item {
id: root
property string headerText
property string headerTextDisabledColor: "#494B50"
property string headerTextColor: "#878b91"
property alias errorText: errorField.text
property string buttonText
@ -15,9 +18,18 @@ Item {
property alias textField: textField
property alias textFieldText: textField.text
property string textFieldTextColor: "#d7d8db"
property string textFieldTextDisabledColor: "#878B91"
property string textFieldPlaceholderText
property bool textFieldEditable: true
property string borderColor: "#2C2D30"
property string borderFocusedColor: "#d7d8db"
property string backgroundColor: "#1c1d21"
property string backgroundDisabledColor: "transparent"
implicitWidth: content.implicitWidth
implicitHeight: content.implicitHeight
@ -29,9 +41,9 @@ Item {
id: backgroud
Layout.fillWidth: true
Layout.preferredHeight: 74
color: "#1c1d21"
color: root.enabled ? root.backgroundColor : root.backgroundDisabledColor
radius: 16
border.color: textField.focus ? "#d7d8db" : "#2C2D30"
border.color: textField.focus ? root.borderFocusedColor : root.borderColor
border.width: 1
Behavior on border.color {
@ -43,7 +55,7 @@ Item {
ColumnLayout {
LabelTextType {
text: root.headerText
color: "#878b91"
color: root.enabled ? root.headerTextColor : root.headerTextDisabledColor
Layout.fillWidth: true
Layout.rightMargin: 16
@ -55,9 +67,9 @@ Item {
id: textField
enabled: root.textFieldEditable
color: "#d7d8db"
color: root.enabled ? root.textFieldTextColor : root.textFieldTextDisabledColor
placeholderText: textFieldPlaceholderText
placeholderText: root.textFieldPlaceholderText
placeholderTextColor: "#494B50"
selectionColor: "#412102"
@ -79,7 +91,7 @@ Item {
background: Rectangle {
anchors.fill: parent
color: "#1c1d21"
color: root.enabled ? root.backgroundColor : root.backgroundDisabledColor
}
onTextChanged: {
@ -98,13 +110,13 @@ Item {
textColor: "#D7D8DB"
borderWidth: 0
text: buttonText
text: root.buttonText
Layout.rightMargin: 24
onClicked: {
if (clickedFunc && typeof clickedFunc === "function") {
clickedFunc()
if (root.clickedFunc && typeof root.clickedFunc === "function") {
root.clickedFunc()
}
}
}

View file

@ -158,7 +158,6 @@ PageType {
implicitHeight: 40
rootButtonBorderWidth: 0
rootButtonImageColor: "#0E0E11"
rootButtonBackgroundColor: "#D7D8DB"

View file

@ -0,0 +1,176 @@
import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
import SortFilterProxyModel 0.2
import "./"
import "../Controls2"
import "../Controls2/TextTypes"
import "../Config"
import "../Components"
PageType {
id: root
//todo move to main?
Connections {
target: InstallController
function onInstallationErrorOccurred(errorMessage) {
PageController.showErrorMessage(errorMessage)
}
function onUpdateContainerFinished() {
//todo change to notification
PageController.showErrorMessage(qsTr("Settings updated successfully"))
}
}
ColumnLayout {
id: backButton
anchors.top: parent.top
anchors.left: parent.left
anchors.right: parent.right
anchors.topMargin: 20
BackButtonType {
}
}
FlickableType {
id: fl
anchors.top: backButton.bottom
anchors.bottom: parent.bottom
contentHeight: content.implicitHeight
Column {
id: content
anchors.top: parent.top
anchors.left: parent.left
anchors.right: parent.right
ListView {
id: listview
width: parent.width
height: listview.contentItem.height
clip: true
interactive: false
model: CloakConfigModel
delegate: Item {
implicitWidth: listview.width
implicitHeight: col.implicitHeight
ColumnLayout {
id: col
anchors.top: parent.top
anchors.left: parent.left
anchors.right: parent.right
anchors.leftMargin: 16
anchors.rightMargin: 16
spacing: 0
HeaderType {
Layout.fillWidth: true
headerText: qsTr("Cloak settings")
}
TextFieldWithHeaderType {
Layout.fillWidth: true
Layout.topMargin: 32
headerText: qsTr("Masquerading as traffic from")
textFieldText: site
textField.onEditingFinished: {
if (textFieldText !== site) {
site = textFieldText
}
}
}
TextFieldWithHeaderType {
Layout.fillWidth: true
Layout.topMargin: 16
headerText: qsTr("Port")
textFieldText: port
textField.onEditingFinished: {
if (textFieldText !== port) {
port = textFieldText
}
}
}
DropDownType {
id: cipherDropDown
Layout.fillWidth: true
Layout.topMargin: 16
implicitHeight: 74
descriptionText: qsTr("Cipher")
headerText: qsTr("Cipher")
listView: ListViewType {
id: cipherListView
rootWidth: root.width
model: ListModel {
ListElement { name : "chacha20-ietf-poly1305" }
ListElement { name : "xchacha20-ietf-poly1305" }
ListElement { name : "aes-256-gcm" }
ListElement { name : "aes-192-gcm" }
ListElement { name : "aes-128-gcm" }
}
clickedFunction: function() {
cipherDropDown.text = selectedText
cipher = cipherDropDown.text
cipherDropDown.menuVisible = false
}
Component.onCompleted: {
cipherDropDown.text = cipher
for (var i = 0; i < cipherListView.model.count; i++) {
if (cipherListView.model.get(i).name === cipherDropDown.text) {
currentIndex = i
}
}
}
}
}
BasicButtonType {
Layout.fillWidth: true
Layout.topMargin: 24
Layout.bottomMargin: 24
text: qsTr("Save and Restart Amnesia")
onClicked: {
forceActiveFocus()
PageController.showBusyIndicator(true)
InstallController.updateContainer(CloakConfigModel.getConfig())
PageController.showBusyIndicator(false)
}
}
}
}
}
}
}
}

View file

@ -0,0 +1,465 @@
import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
import SortFilterProxyModel 0.2
import PageEnum 1.0
import "./"
import "../Controls2"
import "../Controls2/TextTypes"
import "../Config"
import "../Components"
PageType {
id: root
Connections {
target: InstallController
function onInstallationErrorOccurred(errorMessage) {
PageController.showErrorMessage(errorMessage)
}
function onUpdateContainerFinished() {
//todo change to notification
PageController.showErrorMessage(qsTr("Settings updated successfully"))
}
}
ColumnLayout {
id: backButton
anchors.top: parent.top
anchors.left: parent.left
anchors.right: parent.right
anchors.topMargin: 20
BackButtonType {
}
}
FlickableType {
id: fl
anchors.top: backButton.bottom
anchors.bottom: parent.bottom
contentHeight: content.implicitHeight
Column {
id: content
anchors.top: parent.top
anchors.left: parent.left
anchors.right: parent.right
ListView {
id: listview
width: parent.width
height: listview.contentItem.height
clip: true
interactive: false
model: OpenVpnConfigModel
delegate: Item {
implicitWidth: listview.width
implicitHeight: col.implicitHeight
ColumnLayout {
id: col
anchors.top: parent.top
anchors.left: parent.left
anchors.right: parent.right
anchors.leftMargin: 16
anchors.rightMargin: 16
spacing: 0
HeaderType {
Layout.fillWidth: true
headerText: qsTr("OpenVPN settings")
}
TextFieldWithHeaderType {
Layout.fillWidth: true
Layout.topMargin: 32
headerText: qsTr("VPN Addresses Subnet")
textFieldText: subnetAddress
textField.onEditingFinished: {
if (textFieldText !== subnetAddress) {
subnetAddress = textFieldText
}
}
}
ParagraphTextType {
Layout.fillWidth: true
Layout.topMargin: 32
text: qsTr("Network protocol")
}
TransportProtoSelector {
Layout.fillWidth: true
Layout.topMargin: 16
rootWidth: root.width
enabled: isTransportProtoEditable
currentIndex: {
return transportProto === "tcp" ? 1 : 0
}
onCurrentIndexChanged: {
if (transportProto === "tcp" && currentIndex === 0) {
transportProto = "udp"
} else if (transportProto === "udp" && currentIndex === 1) {
transportProto = "tcp"
}
}
}
TextFieldWithHeaderType {
Layout.fillWidth: true
Layout.topMargin: 40
enabled: isPortEditable
headerText: qsTr("Port")
textFieldText: port
textField.onEditingFinished: {
if (textFieldText !== port) {
port = textFieldText
}
}
}
SwitcherType {
id: autoNegotiateEncryprionSwitcher
Layout.fillWidth: true
Layout.topMargin: 24
text: qsTr("Auto-negotiate encryption")
checked: autoNegotiateEncryprion
onCheckedChanged: {
if (checked !== autoNegotiateEncryprion) {
autoNegotiateEncryprion = checked
}
}
}
DropDownType {
id: hashDropDown
Layout.fillWidth: true
Layout.topMargin: 20
implicitHeight: 74
enabled: !autoNegotiateEncryprionSwitcher.checked
descriptionText: qsTr("Hash")
headerText: qsTr("Hash")
listView: ListViewType {
id: hashListView
rootWidth: root.width
model: ListModel {
ListElement { name : qsTr("SHA512") }
ListElement { name : qsTr("SHA384") }
ListElement { name : qsTr("SHA256") }
ListElement { name : qsTr("SHA3-512") }
ListElement { name : qsTr("SHA3-384") }
ListElement { name : qsTr("SHA3-256") }
ListElement { name : qsTr("whirlpool") }
ListElement { name : qsTr("BLAKE2b512") }
ListElement { name : qsTr("BLAKE2s256") }
ListElement { name : qsTr("SHA1") }
}
clickedFunction: function() {
hashDropDown.text = selectedText
hash = hashDropDown.text
hashDropDown.menuVisible = false
}
Component.onCompleted: {
hashDropDown.text = hash
for (var i = 0; i < hashListView.model.count; i++) {
if (hashListView.model.get(i).name === hashDropDown.text) {
currentIndex = i
}
}
}
}
}
DropDownType {
id: cipherDropDown
Layout.fillWidth: true
Layout.topMargin: 16
implicitHeight: 74
enabled: !autoNegotiateEncryprionSwitcher.checked
descriptionText: qsTr("Cipher")
headerText: qsTr("Cipher")
listView: ListViewType {
id: cipherListView
rootWidth: root.width
model: ListModel {
ListElement { name : qsTr("AES-256-GCM") }
ListElement { name : qsTr("AES-192-GCM") }
ListElement { name : qsTr("AES-128-GCM") }
ListElement { name : qsTr("AES-256-CBC") }
ListElement { name : qsTr("AES-192-CBC") }
ListElement { name : qsTr("AES-128-CBC") }
ListElement { name : qsTr("ChaCha20-Poly1305") }
ListElement { name : qsTr("ARIA-256-CBC") }
ListElement { name : qsTr("CAMELLIA-256-CBC") }
ListElement { name : qsTr("none") }
}
clickedFunction: function() {
cipherDropDown.text = selectedText
cipher = cipherDropDown.text
cipherDropDown.menuVisible = false
}
Component.onCompleted: {
cipherDropDown.text = cipher
for (var i = 0; i < cipherListView.model.count; i++) {
if (cipherListView.model.get(i).name === cipherDropDown.text) {
currentIndex = i
}
}
}
}
}
Rectangle {
Layout.fillWidth: true
Layout.topMargin: 32
Layout.preferredHeight: checkboxLayout.implicitHeight
color: "#1C1D21"
radius: 16
ColumnLayout {
id: checkboxLayout
CheckBoxType {
Layout.fillWidth: true
text: qsTr("TLS auth")
checked: tlsAuth
onCheckedChanged: {
if (checked !== tlsAuth) {
tlsAuth = checked
}
}
}
DividerType {}
CheckBoxType {
Layout.fillWidth: true
text: qsTr("Block DNS requests outside of VPN")
checked: blockDns
onCheckedChanged: {
if (checked !== blockDns) {
blockDns = checked
}
}
}
}
}
SwitcherType {
id: additionalClientCommandsSwitcher
Layout.fillWidth: true
Layout.topMargin: 32
checked: additionalClientCommands !== ""
text: qsTr("Additional client configuration commands")
}
Rectangle {
Layout.fillWidth: true
Layout.topMargin: 16
height: 148
color: "#1C1D21"
border.width: 1
border.color: "#2C2D30"
radius: 16
visible: additionalClientCommandsSwitcher.checked
FlickableType {
anchors.top: parent.top
anchors.bottom: parent.bottom
contentHeight: additionalClientCommandsTextArea.implicitHeight
TextArea {
id: additionalClientCommandsTextArea
width: parent.width
anchors.topMargin: 16
anchors.bottomMargin: 16
topPadding: 16
leftPadding: 16
color: "#D7D8DB"
selectionColor: "#412102"
selectedTextColor: "#D7D8DB"
placeholderTextColor: "#878B91"
font.pixelSize: 16
font.weight: Font.Medium
font.family: "PT Root UI VF"
placeholderText: qsTr("Commands:")
text: additionalClientCommands
wrapMode: Text.Wrap
onEditingFinished: {
if (additionalClientCommands !== text) {
additionalClientCommands = text
}
}
}
}
}
SwitcherType {
id: additionalServerCommandsSwitcher
Layout.fillWidth: true
Layout.topMargin: 16
checked: additionalServerCommands !== ""
text: qsTr("Additional server configuration commands")
}
Rectangle {
Layout.fillWidth: true
Layout.topMargin: 16
height: 148
color: "#1C1D21"
border.width: 1
border.color: "#2C2D30"
radius: 16
visible: additionalServerCommandsSwitcher.checked
FlickableType {
anchors.top: parent.top
anchors.bottom: parent.bottom
contentHeight: additionalServerCommandsTextArea.implicitHeight
TextArea {
id: additionalServerCommandsTextArea
width: parent.width
anchors.topMargin: 16
anchors.bottomMargin: 16
topPadding: 16
leftPadding: 16
color: "#D7D8DB"
selectionColor: "#412102"
selectedTextColor: "#D7D8DB"
placeholderTextColor: "#878B91"
font.pixelSize: 16
font.weight: Font.Medium
font.family: "PT Root UI VF"
placeholderText: qsTr("Commands:")
text: additionalServerCommands
wrapMode: Text.Wrap
onEditingFinished: {
if (additionalServerCommands !== text) {
additionalServerCommands = text
}
}
}
}
}
BasicButtonType {
Layout.topMargin: 24
defaultColor: "transparent"
hoveredColor: Qt.rgba(1, 1, 1, 0.08)
pressedColor: Qt.rgba(1, 1, 1, 0.12)
textColor: "#EB5757"
text: qsTr("Remove OpenVPN")
onClicked: {
questionDrawer.headerText = qsTr("Remove OpenVpn from server?")
// questionDrawer.descriptionText = qsTr("")
questionDrawer.yesButtonText = qsTr("Continue")
questionDrawer.noButtonText = qsTr("Cancel")
questionDrawer.yesButtonFunction = function() {
questionDrawer.visible = false
goToPage(PageEnum.PageDeinstalling)
ContainersModel.removeCurrentlyProcessedContainer()
closePage()
closePage() //todo auto close to deinstall page?
}
questionDrawer.noButtonFunction = function() {
questionDrawer.visible = false
}
questionDrawer.visible = true
}
}
BasicButtonType {
Layout.fillWidth: true
Layout.topMargin: 24
Layout.bottomMargin: 24
text: qsTr("Save and Restart Amnesia")
onClicked: {
forceActiveFocus()
PageController.showBusyIndicator(true)
InstallController.updateContainer(OpenVpnConfigModel.getConfig())
PageController.showBusyIndicator(false)
}
}
}
}
}
}
QuestionDrawer {
id: questionDrawer
}
}
}

View file

@ -0,0 +1,162 @@
import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
import SortFilterProxyModel 0.2
import "./"
import "../Controls2"
import "../Controls2/TextTypes"
import "../Config"
import "../Components"
PageType {
id: root
//todo move to main?
Connections {
target: InstallController
function onInstallationErrorOccurred(errorMessage) {
PageController.showErrorMessage(errorMessage)
}
function onUpdateContainerFinished() {
//todo change to notification
PageController.showErrorMessage(qsTr("Settings updated successfully"))
}
}
ColumnLayout {
id: backButton
anchors.top: parent.top
anchors.left: parent.left
anchors.right: parent.right
anchors.topMargin: 20
BackButtonType {
}
}
FlickableType {
id: fl
anchors.top: backButton.bottom
anchors.bottom: parent.bottom
contentHeight: content.implicitHeight
Column {
id: content
anchors.top: parent.top
anchors.left: parent.left
anchors.right: parent.right
ListView {
id: listview
width: parent.width
height: listview.contentItem.height
clip: true
interactive: false
model: ShadowSocksConfigModel
delegate: Item {
implicitWidth: listview.width
implicitHeight: col.implicitHeight
ColumnLayout {
id: col
anchors.top: parent.top
anchors.left: parent.left
anchors.right: parent.right
anchors.leftMargin: 16
anchors.rightMargin: 16
spacing: 0
HeaderType {
Layout.fillWidth: true
headerText: qsTr("ShadowSocks settings")
}
TextFieldWithHeaderType {
Layout.fillWidth: true
Layout.topMargin: 40
headerText: qsTr("Port")
textFieldText: port
textField.onEditingFinished: {
if (textFieldText !== port) {
port = textFieldText
}
}
}
DropDownType {
id: cipherDropDown
Layout.fillWidth: true
Layout.topMargin: 20
implicitHeight: 74
descriptionText: qsTr("Cipher")
headerText: qsTr("Cipher")
listView: ListViewType {
id: cipherListView
rootWidth: root.width
model: ListModel {
ListElement { name : "chacha20-ietf-poly1305" }
ListElement { name : "xchacha20-ietf-poly1305" }
ListElement { name : "aes-256-gcm" }
ListElement { name : "aes-192-gcm" }
ListElement { name : "aes-128-gcm" }
}
clickedFunction: function() {
cipherDropDown.text = selectedText
cipher = cipherDropDown.text
cipherDropDown.menuVisible = false
}
Component.onCompleted: {
cipherDropDown.text = cipher
for (var i = 0; i < cipherListView.model.count; i++) {
if (cipherListView.model.get(i).name === cipherDropDown.text) {
currentIndex = i
}
}
}
}
}
BasicButtonType {
Layout.fillWidth: true
Layout.topMargin: 24
Layout.bottomMargin: 24
text: qsTr("Save and Restart Amnesia")
onClicked: {
forceActiveFocus()
PageController.showBusyIndicator(true)
InstallController.updateContainer(ShadowSocksConfigModel.getConfig())
PageController.showBusyIndicator(false)
}
}
}
}
}
}
}
}

View file

@ -6,6 +6,7 @@ import SortFilterProxyModel 0.2
import PageEnum 1.0
import ProtocolEnum 1.0
import ContainerEnum 1.0
import ContainerProps 1.0
import "./"
@ -13,15 +14,37 @@ import "../Controls2"
import "../Controls2/TextTypes"
import "../Config"
import "../Components"
import "../Components/Protocols"
PageType {
id: root
ColumnLayout {
id: header
anchors.top: parent.top
anchors.left: parent.left
anchors.right: parent.right
anchors.topMargin: 20
BackButtonType {
}
HeaderType {
Layout.fillWidth: true
Layout.leftMargin: 16
Layout.rightMargin: 16
headerText: ContainersModel.getCurrentlyProcessedContainerName() + qsTr(" settings")
}
}
FlickableType {
id: fl
anchors.fill: parent
contentHeight: content.height + openVpnSettings.implicitHeight
anchors.top: header.bottom
anchors.left: parent.left
anchors.right: parent.right
contentHeight: content.height
Column {
id: content
@ -29,8 +52,7 @@ PageType {
anchors.top: parent.top
anchors.left: parent.left
anchors.right: parent.right
spacing: 16
anchors.topMargin: 32
ListView {
// todo change id naming
@ -39,16 +61,7 @@ PageType {
height: container.contentItem.height
clip: true
interactive: false
model: SortFilterProxyModel {
id: proxyContainersModel
sourceModel: ContainersModel
filters: [
ValueFilter {
roleName: "isCurrentlyProcessed"
value: true
}
]
}
model: ProtocolsModel
delegate: Item {
implicitWidth: container.width
@ -58,24 +71,60 @@ PageType {
id: delegateContent
anchors.fill: parent
anchors.rightMargin: 16
anchors.leftMargin: 16
HeaderType {
LabelWithButtonType {
id: button
Layout.fillWidth: true
Layout.topMargin: 20
headerText: name
text: protocolName
rightImageSource: "qrc:/images/controls/chevron-right.svg"
clickedFunction: function() {
var containerIndex = ContainersModel.getCurrentlyProcessedContainerIndex()
switch (containerIndex) {
case ContainerEnum.OpenVpn: OpenVpnConfigModel.updateModel(ProtocolsModel.getConfig()); break;
case ContainerEnum.ShadowSocks: ShadowSocksConfigModel.updateModel(ProtocolsModel.getConfig()); break;
case ContainerEnum.Cloak: CloakConfigModel.updateModel(ProtocolsModel.getConfig()); break;
case ContainerEnum.WireGuard: WireGuardConfigModel.updateModel(ProtocolsModel.getConfig()); break;
case ContainerEnum.Ipsec: Ikev2ConfigModel.updateModel(ProtocolsModel.getConfig()); break;
}
goToPage(protocolPage);
}
MouseArea {
anchors.fill: button
cursorShape: Qt.PointingHandCursor
enabled: false
}
}
DividerType {}
}
}
}
OpenVpnSettings {
id: openVpnSettings
LabelWithButtonType {
id: removeButton
width: parent.width
text: qsTr("Remove ") + ContainersModel.getCurrentlyProcessedContainerName()
textColor: "#EB5757"
clickedFunction: function() {
ContainersModel.removeCurrentlyProcessedContainer()
closePage()
}
MouseArea {
anchors.fill: removeButton
cursorShape: Qt.PointingHandCursor
enabled: false
}
}
DividerType {}
}
}
}

View file

@ -14,8 +14,6 @@ import "../Config"
PageType {
id: root
property real progressBarValue: 0
Connections {
target: InstallController
@ -128,8 +126,6 @@ PageType {
Layout.fillWidth: true
Layout.topMargin: 32
// value: progressBarValue
Timer {
id: timer

View file

@ -44,7 +44,7 @@ PageType {
FlickableType {
id: fl
anchors.top: backButton.top
anchors.top: backButton.bottom
anchors.bottom: parent.bottom
contentHeight: content.implicitHeight + content.anchors.topMargin + content.anchors.bottomMargin

View file

@ -31,8 +31,6 @@ PageType {
shareConnectionDrawer.contentVisible = false
PageController.showBusyIndicator(true)
console.log(type)
switch (type) {
case PageShare.ConfigType.AmneziaConnection: ExportController.generateConnectionConfig(); break;
case PageShare.ConfigType.AmenziaFullAccess: ExportController.generateFullAccessConfig(); break;
@ -51,6 +49,7 @@ PageType {
}
property bool showContent: false
property bool shareButtonEnabled: false
property list<QtObject> connectionTypesModel: [
amneziaConnectionFormat
]
@ -180,6 +179,7 @@ PageType {
serverSelector.text = selectedText
ServersModel.currentlyProcessedIndex = currentIndex
protocolSelector.visible = true
root.shareButtonEnabled = false
}
Component.onCompleted: {
@ -253,18 +253,24 @@ PageType {
currentIndex: 0
clickedFunction: function () {
serverSelector.text += ", " + selectedText
shareConnectionDrawer.headerText = qsTr("Connection to ") + serverSelector.text
shareConnectionDrawer.configContentHeaderText = qsTr("File with connection settings to ") + serverSelector.text
ContainersModel.setCurrentlyProcessedContainerIndex(proxyContainersModel.mapToSource(currentIndex))
handler()
protocolSelector.visible = false
serverSelector.menuVisible = false
fillConnectionTypeModel()
}
Component.onCompleted: {
handler()
}
function handler() {
if (!proxyContainersModel.count) {
root.shareButtonEnabled = false
return
} else {
root.shareButtonEnabled = true
}
serverSelector.text += ", " + selectedText
shareConnectionDrawer.headerText = qsTr("Connection to ") + serverSelector.text
shareConnectionDrawer.configContentHeaderText = qsTr("File with connection settings to ") + serverSelector.text
@ -336,6 +342,8 @@ PageType {
Layout.fillWidth: true
Layout.topMargin: 32
enabled: shareButtonEnabled
text: qsTr("Share")
onClicked: {