added separation for read/write and readonly servers for pageSettingsServerProtocols, PageSettingsServerServices, PageSettingsServerData
- added fields validations for pageSetupWizardCredentials
This commit is contained in:
parent
249be451f7
commit
2ef53c6df9
22 changed files with 466 additions and 325 deletions
|
@ -1,29 +1,28 @@
|
|||
#include "amnezia_application.h"
|
||||
|
||||
#include <QFontDatabase>
|
||||
#include <QQuickStyle>
|
||||
#include <QStandardPaths>
|
||||
#include <QTimer>
|
||||
#include <QTranslator>
|
||||
#include <QQuickStyle>
|
||||
|
||||
#include "logger.h"
|
||||
#include "defines.h"
|
||||
#include "logger.h"
|
||||
|
||||
#include "platforms/ios/QRCodeReaderBase.h"
|
||||
|
||||
#include "ui/pages.h"
|
||||
|
||||
#if defined(Q_OS_IOS)
|
||||
#include "platforms/ios/QtAppDelegate-C-Interface.h"
|
||||
#include "platforms/ios/QtAppDelegate-C-Interface.h"
|
||||
#endif
|
||||
|
||||
#if defined(Q_OS_ANDROID) || defined(Q_OS_IOS)
|
||||
AmneziaApplication::AmneziaApplication(int &argc, char *argv[]):
|
||||
AMNEZIA_BASE_CLASS(argc, argv)
|
||||
AmneziaApplication::AmneziaApplication(int &argc, char *argv[]) : AMNEZIA_BASE_CLASS(argc, argv)
|
||||
#else
|
||||
AmneziaApplication::AmneziaApplication(int &argc, char *argv[], bool allowSecondary,
|
||||
SingleApplication::Options options, int timeout, const QString &userData):
|
||||
SingleApplication(argc, argv, allowSecondary, options, timeout, userData)
|
||||
AmneziaApplication::AmneziaApplication(int &argc, char *argv[], bool allowSecondary, SingleApplication::Options options,
|
||||
int timeout, const QString &userData)
|
||||
: SingleApplication(argc, argv, allowSecondary, options, timeout, userData)
|
||||
#endif
|
||||
{
|
||||
setQuitOnLastWindowClosed(false);
|
||||
|
@ -51,12 +50,14 @@
|
|||
AmneziaApplication::~AmneziaApplication()
|
||||
{
|
||||
if (m_engine) {
|
||||
QObject::disconnect(m_engine, 0,0,0);
|
||||
QObject::disconnect(m_engine, 0, 0, 0);
|
||||
delete m_engine;
|
||||
}
|
||||
|
||||
if (m_protocolProps) delete m_protocolProps;
|
||||
if (m_containerProps) delete m_containerProps;
|
||||
if (m_protocolProps)
|
||||
delete m_protocolProps;
|
||||
if (m_containerProps)
|
||||
delete m_containerProps;
|
||||
}
|
||||
|
||||
void AmneziaApplication::init()
|
||||
|
@ -64,11 +65,13 @@ void AmneziaApplication::init()
|
|||
m_engine = new QQmlApplicationEngine;
|
||||
|
||||
const QUrl url(QStringLiteral("qrc:/ui/qml/main2.qml"));
|
||||
QObject::connect(m_engine, &QQmlApplicationEngine::objectCreated,
|
||||
this, [url](QObject *obj, const QUrl &objUrl) {
|
||||
if (!obj && url == objUrl)
|
||||
QCoreApplication::exit(-1);
|
||||
}, Qt::QueuedConnection);
|
||||
QObject::connect(
|
||||
m_engine, &QQmlApplicationEngine::objectCreated, this,
|
||||
[url](QObject *obj, const QUrl &objUrl) {
|
||||
if (!obj && url == objUrl)
|
||||
QCoreApplication::exit(-1);
|
||||
},
|
||||
Qt::QueuedConnection);
|
||||
|
||||
m_engine->rootContext()->setContextProperty("Debug", &Logger::Instance());
|
||||
|
||||
|
@ -78,6 +81,8 @@ void AmneziaApplication::init()
|
|||
|
||||
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_configurator = std::shared_ptr<VpnConfigurator>(new VpnConfigurator(m_settings, this));
|
||||
m_vpnConnection.reset(new VpnConnection(m_settings, m_configurator));
|
||||
|
@ -94,21 +99,19 @@ void AmneziaApplication::init()
|
|||
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_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_settingsController.reset(new SettingsController(m_serversModel, m_containersModel, m_settings));
|
||||
m_engine->rootContext()->setContextProperty("SettingsController", m_settingsController.get());
|
||||
|
||||
//
|
||||
|
||||
m_engine->load(url);
|
||||
|
||||
// if (m_engine->rootObjects().size() > 0) {
|
||||
// m_uiLogic->setQmlRoot(m_engine->rootObjects().at(0));
|
||||
// }
|
||||
// if (m_engine->rootObjects().size() > 0) {
|
||||
// m_uiLogic->setQmlRoot(m_engine->rootObjects().at(0));
|
||||
// }
|
||||
|
||||
if (m_settings->isSaveLogs()) {
|
||||
if (!Logger::init()) {
|
||||
|
@ -116,24 +119,23 @@ void AmneziaApplication::init()
|
|||
}
|
||||
}
|
||||
|
||||
//#ifdef Q_OS_WIN
|
||||
// if (m_parser.isSet("a")) m_uiLogic->showOnStartup();
|
||||
// else emit m_uiLogic->show();
|
||||
//#else
|
||||
// m_uiLogic->showOnStartup();
|
||||
//#endif
|
||||
|
||||
// // TODO - fix
|
||||
//#if !defined(Q_OS_ANDROID) && !defined(Q_OS_IOS)
|
||||
// if (isPrimary()) {
|
||||
// QObject::connect(this, &SingleApplication::instanceStarted, m_uiLogic, [this](){
|
||||
// qDebug() << "Secondary instance started, showing this window instead";
|
||||
// emit m_uiLogic->show();
|
||||
// emit m_uiLogic->raise();
|
||||
// });
|
||||
// }
|
||||
//#endif
|
||||
// #ifdef Q_OS_WIN
|
||||
// if (m_parser.isSet("a")) m_uiLogic->showOnStartup();
|
||||
// else emit m_uiLogic->show();
|
||||
// #else
|
||||
// m_uiLogic->showOnStartup();
|
||||
// #endif
|
||||
|
||||
// // TODO - fix
|
||||
// #if !defined(Q_OS_ANDROID) && !defined(Q_OS_IOS)
|
||||
// if (isPrimary()) {
|
||||
// QObject::connect(this, &SingleApplication::instanceStarted, m_uiLogic, [this](){
|
||||
// qDebug() << "Secondary instance started, showing this window instead";
|
||||
// emit m_uiLogic->show();
|
||||
// emit m_uiLogic->raise();
|
||||
// });
|
||||
// }
|
||||
// #endif
|
||||
}
|
||||
|
||||
void AmneziaApplication::registerTypes()
|
||||
|
@ -156,6 +158,9 @@ void AmneziaApplication::registerTypes()
|
|||
m_protocolProps = new ProtocolProps;
|
||||
qmlRegisterSingletonInstance("ProtocolProps", 1, 0, "ProtocolProps", m_protocolProps);
|
||||
|
||||
qmlRegisterSingletonType(QUrl("qrc:/ui/qml/Filters/ContainersModelFilters.qml"), "ContainersModelFilters", 1, 0,
|
||||
"ContainersModelFilters");
|
||||
|
||||
//
|
||||
Vpn::declareQmlVpnConnectionStateEnum();
|
||||
PageLoader::declareQmlPageEnum();
|
||||
|
@ -182,19 +187,17 @@ bool AmneziaApplication::parseCommands()
|
|||
m_parser.addHelpOption();
|
||||
m_parser.addVersionOption();
|
||||
|
||||
QCommandLineOption c_autostart {{"a", "autostart"}, "System autostart"};
|
||||
QCommandLineOption c_autostart { { "a", "autostart" }, "System autostart" };
|
||||
m_parser.addOption(c_autostart);
|
||||
|
||||
QCommandLineOption c_cleanup {{"c", "cleanup"}, "Cleanup logs"};
|
||||
QCommandLineOption c_cleanup { { "c", "cleanup" }, "Cleanup logs" };
|
||||
m_parser.addOption(c_cleanup);
|
||||
|
||||
m_parser.process(*this);
|
||||
|
||||
if (m_parser.isSet(c_cleanup)) {
|
||||
Logger::cleanUp();
|
||||
QTimer::singleShot(100, this, [this]{
|
||||
quit();
|
||||
});
|
||||
QTimer::singleShot(100, this, [this] { quit(); });
|
||||
exec();
|
||||
return false;
|
||||
}
|
||||
|
@ -205,4 +208,3 @@ QQmlApplicationEngine *AmneziaApplication::qmlEngine() const
|
|||
{
|
||||
return m_engine;
|
||||
}
|
||||
|
||||
|
|
|
@ -269,5 +269,6 @@
|
|||
<file>images/controls/mail.svg</file>
|
||||
<file>images/controls/telegram.svg</file>
|
||||
<file>ui/qml/Controls2/TextTypes/SmallTextType.qml</file>
|
||||
<file>ui/qml/Filters/ContainersModelFilters.qml</file>
|
||||
</qresource>
|
||||
</RCC>
|
||||
|
|
|
@ -16,14 +16,14 @@
|
|||
ExportController::ExportController(const QSharedPointer<ServersModel> &serversModel,
|
||||
const QSharedPointer<ContainersModel> &containersModel,
|
||||
const std::shared_ptr<Settings> &settings,
|
||||
const std::shared_ptr<VpnConfigurator> &configurator,
|
||||
QObject *parent)
|
||||
: QObject(parent)
|
||||
, m_serversModel(serversModel)
|
||||
, m_containersModel(containersModel)
|
||||
, m_settings(settings)
|
||||
, m_configurator(configurator)
|
||||
{}
|
||||
const std::shared_ptr<VpnConfigurator> &configurator, QObject *parent)
|
||||
: QObject(parent),
|
||||
m_serversModel(serversModel),
|
||||
m_containersModel(containersModel),
|
||||
m_settings(settings),
|
||||
m_configurator(configurator)
|
||||
{
|
||||
}
|
||||
|
||||
void ExportController::generateFullAccessConfig()
|
||||
{
|
||||
|
@ -33,8 +33,8 @@ void ExportController::generateFullAccessConfig()
|
|||
QByteArray compressedConfig = QJsonDocument(config).toJson();
|
||||
compressedConfig = qCompress(compressedConfig, 8);
|
||||
m_amneziaCode = QString("vpn://%1")
|
||||
.arg(QString(compressedConfig.toBase64(QByteArray::Base64UrlEncoding
|
||||
| QByteArray::OmitTrailingEquals)));
|
||||
.arg(QString(compressedConfig.toBase64(QByteArray::Base64UrlEncoding
|
||||
| QByteArray::OmitTrailingEquals)));
|
||||
|
||||
m_qrCodes = generateQrCodeImageSeries(compressedConfig);
|
||||
emit exportConfigChanged();
|
||||
|
@ -43,25 +43,21 @@ void ExportController::generateFullAccessConfig()
|
|||
void ExportController::generateConnectionConfig()
|
||||
{
|
||||
int serverIndex = m_serversModel->getCurrentlyProcessedServerIndex();
|
||||
ServerCredentials credentials = qvariant_cast<ServerCredentials>(
|
||||
m_serversModel->data(serverIndex, ServersModel::Roles::CredentialsRole));
|
||||
ServerCredentials credentials =
|
||||
qvariant_cast<ServerCredentials>(m_serversModel->data(serverIndex, ServersModel::Roles::CredentialsRole));
|
||||
|
||||
DockerContainer container = static_cast<DockerContainer>(
|
||||
m_containersModel->getCurrentlyProcessedContainerIndex());
|
||||
DockerContainer container = static_cast<DockerContainer>(m_containersModel->getCurrentlyProcessedContainerIndex());
|
||||
QModelIndex containerModelIndex = m_containersModel->index(container);
|
||||
QJsonObject containerConfig = qvariant_cast<QJsonObject>(
|
||||
m_containersModel->data(containerModelIndex, ContainersModel::Roles::ConfigRole));
|
||||
QJsonObject containerConfig =
|
||||
qvariant_cast<QJsonObject>(m_containersModel->data(containerModelIndex, ContainersModel::Roles::ConfigRole));
|
||||
containerConfig.insert(config_key::container, ContainerProps::containerToString(container));
|
||||
|
||||
ErrorCode errorCode = ErrorCode::NoError;
|
||||
for (Proto protocol : ContainerProps::protocolsForContainer(container)) {
|
||||
QJsonObject protocolConfig = m_settings->protocolConfig(serverIndex, container, protocol);
|
||||
|
||||
QString vpnConfig = m_configurator->genVpnProtocolConfig(credentials,
|
||||
container,
|
||||
containerConfig,
|
||||
protocol,
|
||||
&errorCode);
|
||||
QString vpnConfig =
|
||||
m_configurator->genVpnProtocolConfig(credentials, container, containerConfig, protocol, &errorCode);
|
||||
if (errorCode) {
|
||||
emit exportErrorOccurred(errorString(errorCode));
|
||||
return;
|
||||
|
@ -75,7 +71,7 @@ void ExportController::generateConnectionConfig()
|
|||
config.remove(config_key::userName);
|
||||
config.remove(config_key::password);
|
||||
config.remove(config_key::port);
|
||||
config.insert(config_key::containers, QJsonArray{containerConfig});
|
||||
config.insert(config_key::containers, QJsonArray { containerConfig });
|
||||
config.insert(config_key::defaultContainer, ContainerProps::containerToString(container));
|
||||
|
||||
auto dns = m_configurator->getDnsForConfig(serverIndex);
|
||||
|
@ -86,8 +82,8 @@ void ExportController::generateConnectionConfig()
|
|||
QByteArray compressedConfig = QJsonDocument(config).toJson();
|
||||
compressedConfig = qCompress(compressedConfig, 8);
|
||||
m_amneziaCode = QString("vpn://%1")
|
||||
.arg(QString(compressedConfig.toBase64(QByteArray::Base64UrlEncoding
|
||||
| QByteArray::OmitTrailingEquals)));
|
||||
.arg(QString(compressedConfig.toBase64(QByteArray::Base64UrlEncoding
|
||||
| QByteArray::OmitTrailingEquals)));
|
||||
|
||||
m_qrCodes = generateQrCodeImageSeries(compressedConfig);
|
||||
emit exportConfigChanged();
|
||||
|
@ -108,10 +104,8 @@ void ExportController::saveFile()
|
|||
QString fileExtension = ".vpn";
|
||||
QString docDir = QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation);
|
||||
QUrl fileName;
|
||||
fileName = QFileDialog::getSaveFileUrl(nullptr,
|
||||
tr("Save AmneziaVPN config"),
|
||||
QUrl::fromLocalFile(docDir + "/" + "amnezia_config"),
|
||||
"*" + fileExtension);
|
||||
fileName = QFileDialog::getSaveFileUrl(nullptr, tr("Save AmneziaVPN config"),
|
||||
QUrl::fromLocalFile(docDir + "/" + "amnezia_config"), "*" + fileExtension);
|
||||
if (fileName.isEmpty())
|
||||
return;
|
||||
if (!fileName.toString().endsWith(fileExtension)) {
|
||||
|
@ -139,10 +133,9 @@ QList<QString> ExportController::generateQrCodeImageSeries(const QByteArray &dat
|
|||
for (int i = 0; i < data.size(); i = i + k) {
|
||||
QByteArray chunk;
|
||||
QDataStream s(&chunk, QIODevice::WriteOnly);
|
||||
s << amnezia::qrMagicCode << chunksCount << (quint8) std::round(i / k) << data.mid(i, k);
|
||||
s << amnezia::qrMagicCode << chunksCount << (quint8)std::round(i / k) << data.mid(i, k);
|
||||
|
||||
QByteArray ba = chunk.toBase64(QByteArray::Base64UrlEncoding
|
||||
| QByteArray::OmitTrailingEquals);
|
||||
QByteArray ba = chunk.toBase64(QByteArray::Base64UrlEncoding | QByteArray::OmitTrailingEquals);
|
||||
|
||||
qrcodegen::QrCode qr = qrcodegen::QrCode::encodeText(ba, qrcodegen::QrCode::Ecc::LOW);
|
||||
QString svg = QString::fromStdString(toSvgString(qr, 0));
|
||||
|
|
|
@ -5,40 +5,42 @@
|
|||
|
||||
#include "core/errorstrings.h"
|
||||
|
||||
namespace {
|
||||
enum class ConfigTypes { Amnezia, OpenVpn, WireGuard };
|
||||
|
||||
ConfigTypes checkConfigFormat(const QString &config)
|
||||
namespace
|
||||
{
|
||||
const QString openVpnConfigPatternCli = "client";
|
||||
const QString openVpnConfigPatternProto1 = "proto tcp";
|
||||
const QString openVpnConfigPatternProto2 = "proto udp";
|
||||
const QString openVpnConfigPatternDriver1 = "dev tun";
|
||||
const QString openVpnConfigPatternDriver2 = "dev tap";
|
||||
enum class ConfigTypes {
|
||||
Amnezia,
|
||||
OpenVpn,
|
||||
WireGuard
|
||||
};
|
||||
|
||||
const QString wireguardConfigPatternSectionInterface = "[Interface]";
|
||||
const QString wireguardConfigPatternSectionPeer = "[Peer]";
|
||||
ConfigTypes 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 ConfigTypes::OpenVpn;
|
||||
} else if (config.contains(wireguardConfigPatternSectionInterface)
|
||||
&& config.contains(wireguardConfigPatternSectionPeer)) {
|
||||
return ConfigTypes::WireGuard;
|
||||
const QString wireguardConfigPatternSectionInterface = "[Interface]";
|
||||
const QString wireguardConfigPatternSectionPeer = "[Peer]";
|
||||
|
||||
if (config.contains(openVpnConfigPatternCli)
|
||||
&& (config.contains(openVpnConfigPatternProto1) || config.contains(openVpnConfigPatternProto2))
|
||||
&& (config.contains(openVpnConfigPatternDriver1) || config.contains(openVpnConfigPatternDriver2))) {
|
||||
return ConfigTypes::OpenVpn;
|
||||
} else if (config.contains(wireguardConfigPatternSectionInterface)
|
||||
&& config.contains(wireguardConfigPatternSectionPeer)) {
|
||||
return ConfigTypes::WireGuard;
|
||||
}
|
||||
return ConfigTypes::Amnezia;
|
||||
}
|
||||
return ConfigTypes::Amnezia;
|
||||
}
|
||||
} // namespace
|
||||
|
||||
ImportController::ImportController(const QSharedPointer<ServersModel> &serversModel,
|
||||
const QSharedPointer<ContainersModel> &containersModel,
|
||||
const std::shared_ptr<Settings> &settings,
|
||||
QObject *parent) : QObject(parent), m_serversModel(serversModel), m_containersModel(containersModel), m_settings(settings)
|
||||
const std::shared_ptr<Settings> &settings, QObject *parent)
|
||||
: QObject(parent), m_serversModel(serversModel), m_containersModel(containersModel), m_settings(settings)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void ImportController::extractConfigFromFile(const QUrl &fileUrl)
|
||||
|
@ -88,8 +90,7 @@ void ImportController::importConfig()
|
|||
m_serversModel->addServer(m_config);
|
||||
|
||||
if (!m_config.value(config_key::containers).toArray().isEmpty()) {
|
||||
auto newServerIndex = m_serversModel->index(m_serversModel->getServersCount() - 1);
|
||||
m_serversModel->setData(newServerIndex, true, ServersModel::Roles::IsDefaultRole);
|
||||
m_serversModel->setDefaultServerIndex(m_serversModel->getServersCount() - 1);
|
||||
}
|
||||
|
||||
emit importFinished();
|
||||
|
@ -116,12 +117,12 @@ QJsonObject ImportController::extractAmneziaConfig(QString &data)
|
|||
return QJsonDocument::fromJson(ba).object();
|
||||
}
|
||||
|
||||
//bool ImportController::importConnectionFromQr(const QByteArray &data)
|
||||
// bool ImportController::importConnectionFromQr(const QByteArray &data)
|
||||
//{
|
||||
// QJsonObject dataObj = QJsonDocument::fromJson(data).object();
|
||||
// if (!dataObj.isEmpty()) {
|
||||
// return importConnection(dataObj);
|
||||
// }
|
||||
// QJsonObject dataObj = QJsonDocument::fromJson(data).object();
|
||||
// if (!dataObj.isEmpty()) {
|
||||
// return importConnection(dataObj);
|
||||
// }
|
||||
|
||||
// QByteArray ba_uncompressed = qUncompress(data);
|
||||
// if (!ba_uncompressed.isEmpty()) {
|
||||
|
@ -159,7 +160,6 @@ QJsonObject ImportController::extractOpenVpnConfig(const QString &data)
|
|||
config[config_key::defaultContainer] = "amnezia-openvpn";
|
||||
config[config_key::description] = m_settings->nextAvailableServerName();
|
||||
|
||||
|
||||
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(data);
|
||||
if (dnsMatch.hasNext()) {
|
||||
|
@ -206,7 +206,9 @@ QJsonObject ImportController::extractWireGuardConfig(const QString &data)
|
|||
config[config_key::defaultContainer] = "amnezia-wireguard";
|
||||
config[config_key::description] = m_settings->nextAvailableServerName();
|
||||
|
||||
const static QRegularExpression dnsRegExp("DNS = (\\b\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\b).*(\\b\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\b)");
|
||||
const static QRegularExpression dnsRegExp(
|
||||
"DNS = "
|
||||
"(\\b\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\b).*(\\b\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\b)");
|
||||
QRegularExpressionMatch dnsMatch = dnsRegExp.match(data);
|
||||
if (dnsMatch.hasMatch()) {
|
||||
config[config_key::dns1] = dnsMatch.captured(1);
|
||||
|
|
|
@ -67,8 +67,7 @@ void InstallController::installServer(DockerContainer container, QJsonObject &co
|
|||
server.insert(config_key::defaultContainer, ContainerProps::containerToString(container));
|
||||
|
||||
m_serversModel->addServer(server);
|
||||
auto newServerIndex = m_serversModel->index(m_serversModel->getServersCount() - 1);
|
||||
m_serversModel->setData(newServerIndex, true, ServersModel::Roles::IsDefaultRole);
|
||||
m_serversModel->setDefaultServerIndex(m_serversModel->getServersCount() - 1);
|
||||
|
||||
emit installServerFinished(isInstalledContainerFound);
|
||||
return;
|
||||
|
|
|
@ -78,7 +78,7 @@ QVariant ContainersModel::data(const QModelIndex &index, int role) const
|
|||
return QVariant();
|
||||
}
|
||||
|
||||
void ContainersModel::setCurrentlyProcessedServerIndex(int index)
|
||||
void ContainersModel::setCurrentlyProcessedServerIndex(const int index)
|
||||
{
|
||||
beginResetModel();
|
||||
m_currentlyProcessedServerIndex = index;
|
||||
|
|
|
@ -3,11 +3,11 @@
|
|||
|
||||
#include <QAbstractListModel>
|
||||
#include <QJsonObject>
|
||||
#include <vector>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include "settings.h"
|
||||
#include "containers/containers_defs.h"
|
||||
#include "settings.h"
|
||||
|
||||
class ContainersModel : public QAbstractListModel
|
||||
{
|
||||
|
@ -44,7 +44,7 @@ public slots:
|
|||
DockerContainer getDefaultContainer();
|
||||
QString getDefaultContainerName();
|
||||
|
||||
void setCurrentlyProcessedServerIndex(int index);
|
||||
void setCurrentlyProcessedServerIndex(const int index);
|
||||
void setCurrentlyProcessedContainerIndex(int index);
|
||||
int getCurrentlyProcessedContainerIndex();
|
||||
|
||||
|
@ -57,7 +57,6 @@ protected:
|
|||
private:
|
||||
QMap<DockerContainer, QJsonObject> m_containers;
|
||||
|
||||
|
||||
int m_currentlyProcessedServerIndex;
|
||||
int m_currentlyProcessedContainerIndex;
|
||||
DockerContainer m_defaultContainerIndex;
|
||||
|
|
|
@ -5,6 +5,7 @@ ServersModel::ServersModel(std::shared_ptr<Settings> settings, QObject *parent)
|
|||
{
|
||||
m_servers = m_settings->serversArray();
|
||||
m_defaultServerIndex = m_settings->defaultServerIndex();
|
||||
m_currenlyProcessedServerIndex = m_defaultServerIndex;
|
||||
}
|
||||
|
||||
int ServersModel::rowCount(const QModelIndex &parent) const
|
||||
|
@ -28,10 +29,6 @@ bool ServersModel::setData(const QModelIndex &index, const QVariant &value, int
|
|||
m_servers.replace(index.row(), server);
|
||||
break;
|
||||
}
|
||||
case IsDefaultRole: {
|
||||
setDefaultServerIndex(index.row());
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
return true;
|
||||
}
|
||||
|
@ -62,6 +59,10 @@ QVariant ServersModel::data(const QModelIndex &index, int role) const
|
|||
case CredentialsLoginRole: return m_settings->serverCredentials(index.row()).userName;
|
||||
case IsDefaultRole: return index.row() == m_defaultServerIndex;
|
||||
case IsCurrentlyProcessedRole: return index.row() == m_currenlyProcessedServerIndex;
|
||||
case HasWriteAccess: {
|
||||
auto credentials = m_settings->serverCredentials(index.row());
|
||||
return (!credentials.userName.isEmpty() && !credentials.secretData.isEmpty());
|
||||
}
|
||||
}
|
||||
|
||||
return QVariant();
|
||||
|
@ -73,6 +74,13 @@ QVariant ServersModel::data(const int index, int role) const
|
|||
return data(modelIndex, role);
|
||||
}
|
||||
|
||||
void ServersModel::setDefaultServerIndex(const int index)
|
||||
{
|
||||
m_settings->setDefaultServer(index);
|
||||
m_defaultServerIndex = m_settings->defaultServerIndex();
|
||||
emit defaultServerIndexChanged();
|
||||
}
|
||||
|
||||
const int ServersModel::getDefaultServerIndex()
|
||||
{
|
||||
return m_defaultServerIndex;
|
||||
|
@ -83,10 +91,10 @@ const int ServersModel::getServersCount()
|
|||
return m_servers.count();
|
||||
}
|
||||
|
||||
void ServersModel::setCurrentlyProcessedServerIndex(int index)
|
||||
void ServersModel::setCurrentlyProcessedServerIndex(const int index)
|
||||
{
|
||||
m_currenlyProcessedServerIndex = index;
|
||||
emit currentlyProcessedServerIndexChanged();
|
||||
emit currentlyProcessedServerIndexChanged(m_currenlyProcessedServerIndex);
|
||||
}
|
||||
|
||||
int ServersModel::getCurrentlyProcessedServerIndex()
|
||||
|
@ -101,8 +109,7 @@ bool ServersModel::isDefaultServerCurrentlyProcessed()
|
|||
|
||||
bool ServersModel::isCurrentlyProcessedServerHasWriteAccess()
|
||||
{
|
||||
auto credentials = m_settings->serverCredentials(m_currenlyProcessedServerIndex);
|
||||
return (!credentials.userName.isEmpty() && !credentials.secretData.isEmpty());
|
||||
return qvariant_cast<bool>(data(m_currenlyProcessedServerIndex, HasWriteAccess));
|
||||
}
|
||||
|
||||
void ServersModel::addServer(const QJsonObject &server)
|
||||
|
@ -140,11 +147,6 @@ QHash<int, QByteArray> ServersModel::roleNames() const
|
|||
roles[CredentialsLoginRole] = "credentialsLogin";
|
||||
roles[IsDefaultRole] = "isDefault";
|
||||
roles[IsCurrentlyProcessedRole] = "isCurrentlyProcessed";
|
||||
roles[HasWriteAccess] = "hasWriteAccess";
|
||||
return roles;
|
||||
}
|
||||
|
||||
void ServersModel::setDefaultServerIndex(const int index)
|
||||
{
|
||||
m_settings->setDefaultServer(index);
|
||||
m_defaultServerIndex = m_settings->defaultServerIndex();
|
||||
}
|
||||
|
|
|
@ -5,13 +5,6 @@
|
|||
|
||||
#include "settings.h"
|
||||
|
||||
struct ServerModelContent
|
||||
{
|
||||
QString desc;
|
||||
QString address;
|
||||
bool isDefault;
|
||||
};
|
||||
|
||||
class ServersModel : public QAbstractListModel
|
||||
{
|
||||
Q_OBJECT
|
||||
|
@ -22,7 +15,8 @@ public:
|
|||
CredentialsRole,
|
||||
CredentialsLoginRole,
|
||||
IsDefaultRole,
|
||||
IsCurrentlyProcessedRole
|
||||
IsCurrentlyProcessedRole,
|
||||
HasWriteAccess
|
||||
};
|
||||
|
||||
ServersModel(std::shared_ptr<Settings> settings, QObject *parent = nullptr);
|
||||
|
@ -33,14 +27,20 @@ public:
|
|||
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
|
||||
QVariant data(const int index, int role = Qt::DisplayRole) const;
|
||||
|
||||
Q_PROPERTY(int defaultIndex READ getDefaultServerIndex WRITE setDefaultServerIndex NOTIFY defaultServerIndexChanged)
|
||||
Q_PROPERTY(int currentlyProcessedIndex READ getCurrentlyProcessedServerIndex WRITE setCurrentlyProcessedServerIndex
|
||||
NOTIFY currentlyProcessedServerIndexChanged)
|
||||
|
||||
public slots:
|
||||
void setDefaultServerIndex(const int index);
|
||||
const int getDefaultServerIndex();
|
||||
bool isDefaultServerCurrentlyProcessed();
|
||||
|
||||
bool isCurrentlyProcessedServerHasWriteAccess();
|
||||
|
||||
const int getServersCount();
|
||||
|
||||
void setCurrentlyProcessedServerIndex(int index);
|
||||
void setCurrentlyProcessedServerIndex(const int index);
|
||||
int getCurrentlyProcessedServerIndex();
|
||||
|
||||
void addServer(const QJsonObject &server);
|
||||
|
@ -50,11 +50,10 @@ protected:
|
|||
QHash<int, QByteArray> roleNames() const override;
|
||||
|
||||
signals:
|
||||
void currentlyProcessedServerIndexChanged();
|
||||
void currentlyProcessedServerIndexChanged(const int index);
|
||||
void defaultServerIndexChanged();
|
||||
|
||||
private:
|
||||
void setDefaultServerIndex(const int index);
|
||||
|
||||
QJsonArray m_servers;
|
||||
|
||||
std::shared_ptr<Settings> m_settings;
|
||||
|
|
|
@ -1,14 +1,12 @@
|
|||
#include "ServerListLogic.h"
|
||||
|
||||
#include "vpnconnection.h"
|
||||
#include "../models/servers_model.h"
|
||||
#include "../uilogic.h"
|
||||
#include "vpnconnection.h"
|
||||
|
||||
ServerListLogic::ServerListLogic(UiLogic *logic, QObject *parent):
|
||||
PageLogicBase(logic, parent),
|
||||
m_serverListModel{new ServersModel(m_settings, this)}
|
||||
ServerListLogic::ServerListLogic(UiLogic *logic, QObject *parent)
|
||||
: PageLogicBase(logic, parent), m_serverListModel { new ServersModel(m_settings, this) }
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void ServerListLogic::onServerListPushbuttonDefaultClicked(int index)
|
||||
|
@ -31,19 +29,19 @@ int ServerListLogic::currServerIdx() const
|
|||
|
||||
void ServerListLogic::onUpdatePage()
|
||||
{
|
||||
const QJsonArray &servers = m_settings->serversArray();
|
||||
int defaultServer = m_settings->defaultServerIndex();
|
||||
QVector<ServerModelContent> serverListContent;
|
||||
for(int i = 0; i < servers.size(); i++) {
|
||||
ServerModelContent c;
|
||||
auto server = servers.at(i).toObject();
|
||||
c.desc = server.value(config_key::description).toString();
|
||||
c.address = server.value(config_key::hostName).toString();
|
||||
if (c.desc.isEmpty()) {
|
||||
c.desc = c.address;
|
||||
}
|
||||
c.isDefault = (i == defaultServer);
|
||||
serverListContent.push_back(c);
|
||||
}
|
||||
// qobject_cast<ServersModel*>(m_serverListModel)->setContent(serverListContent);
|
||||
// const QJsonArray &servers = m_settings->serversArray();
|
||||
// int defaultServer = m_settings->defaultServerIndex();
|
||||
// QVector<ServerModelContent> serverListContent;
|
||||
// for(int i = 0; i < servers.size(); i++) {
|
||||
// ServerModelContent c;
|
||||
// auto server = servers.at(i).toObject();
|
||||
// c.desc = server.value(config_key::description).toString();
|
||||
// c.address = server.value(config_key::hostName).toString();
|
||||
// if (c.desc.isEmpty()) {
|
||||
// c.desc = c.address;
|
||||
// }
|
||||
// c.isDefault = (i == defaultServer);
|
||||
// serverListContent.push_back(c);
|
||||
// }
|
||||
// qobject_cast<ServersModel*>(m_serverListModel)->setContent(serverListContent);
|
||||
}
|
||||
|
|
|
@ -8,96 +8,115 @@ Item {
|
|||
id: root
|
||||
|
||||
property string headerText
|
||||
property string textFieldPlaceholderText
|
||||
property bool textFieldEditable: true
|
||||
property alias errorText: errorField.text
|
||||
|
||||
property string buttonText
|
||||
property var clickedFunc
|
||||
|
||||
property alias textField: textField
|
||||
property alias textFieldText: textField.text
|
||||
property string textFieldPlaceholderText
|
||||
property bool textFieldEditable: true
|
||||
|
||||
implicitHeight: 74
|
||||
implicitWidth: content.implicitWidth
|
||||
implicitHeight: content.implicitHeight
|
||||
|
||||
Rectangle {
|
||||
id: backgroud
|
||||
ColumnLayout {
|
||||
id: content
|
||||
anchors.fill: parent
|
||||
color: "#1c1d21"
|
||||
radius: 16
|
||||
border.color: textField.focus ? "#d7d8db" : "#2C2D30"
|
||||
border.width: 1
|
||||
|
||||
Behavior on border.color {
|
||||
PropertyAnimation { duration: 200 }
|
||||
}
|
||||
}
|
||||
Rectangle {
|
||||
id: backgroud
|
||||
Layout.fillWidth: true
|
||||
Layout.preferredHeight: 74
|
||||
color: "#1c1d21"
|
||||
radius: 16
|
||||
border.color: textField.focus ? "#d7d8db" : "#2C2D30"
|
||||
border.width: 1
|
||||
|
||||
RowLayout {
|
||||
anchors.fill: backgroud
|
||||
ColumnLayout {
|
||||
|
||||
LabelTextType {
|
||||
text: root.headerText
|
||||
color: "#878b91"
|
||||
|
||||
Layout.fillWidth: true
|
||||
Layout.rightMargin: 16
|
||||
Layout.leftMargin: 16
|
||||
Layout.topMargin: 16
|
||||
Behavior on border.color {
|
||||
PropertyAnimation { duration: 200 }
|
||||
}
|
||||
|
||||
TextField {
|
||||
id: textField
|
||||
RowLayout {
|
||||
anchors.fill: backgroud
|
||||
ColumnLayout {
|
||||
LabelTextType {
|
||||
text: root.headerText
|
||||
color: "#878b91"
|
||||
|
||||
enabled: root.textFieldEditable
|
||||
color: "#d7d8db"
|
||||
Layout.fillWidth: true
|
||||
Layout.rightMargin: 16
|
||||
Layout.leftMargin: 16
|
||||
Layout.topMargin: 16
|
||||
}
|
||||
|
||||
placeholderText: textFieldPlaceholderText
|
||||
placeholderTextColor: "#494B50"
|
||||
TextField {
|
||||
id: textField
|
||||
|
||||
selectionColor: "#412102"
|
||||
selectedTextColor: "#D7D8DB"
|
||||
enabled: root.textFieldEditable
|
||||
color: "#d7d8db"
|
||||
|
||||
font.pixelSize: 16
|
||||
font.weight: 400
|
||||
font.family: "PT Root UI VF"
|
||||
placeholderText: textFieldPlaceholderText
|
||||
placeholderTextColor: "#494B50"
|
||||
|
||||
height: 24
|
||||
Layout.fillWidth: true
|
||||
Layout.rightMargin: 16
|
||||
Layout.leftMargin: 16
|
||||
Layout.bottomMargin: 16
|
||||
topPadding: 0
|
||||
rightPadding: 0
|
||||
leftPadding: 0
|
||||
bottomPadding: 0
|
||||
selectionColor: "#412102"
|
||||
selectedTextColor: "#D7D8DB"
|
||||
|
||||
background: Rectangle {
|
||||
anchors.fill: parent
|
||||
color: "#1c1d21"
|
||||
font.pixelSize: 16
|
||||
font.weight: 400
|
||||
font.family: "PT Root UI VF"
|
||||
|
||||
height: 24
|
||||
Layout.fillWidth: true
|
||||
Layout.rightMargin: 16
|
||||
Layout.leftMargin: 16
|
||||
Layout.bottomMargin: 16
|
||||
topPadding: 0
|
||||
rightPadding: 0
|
||||
leftPadding: 0
|
||||
bottomPadding: 0
|
||||
|
||||
background: Rectangle {
|
||||
anchors.fill: parent
|
||||
color: "#1c1d21"
|
||||
}
|
||||
|
||||
onTextChanged: {
|
||||
root.errorText = ""
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
BasicButtonType {
|
||||
visible: root.buttonText !== ""
|
||||
|
||||
defaultColor: "transparent"
|
||||
hoveredColor: Qt.rgba(1, 1, 1, 0.08)
|
||||
pressedColor: Qt.rgba(1, 1, 1, 0.12)
|
||||
disabledColor: "#878B91"
|
||||
textColor: "#D7D8DB"
|
||||
borderWidth: 0
|
||||
|
||||
text: buttonText
|
||||
|
||||
Layout.rightMargin: 24
|
||||
|
||||
onClicked: {
|
||||
if (clickedFunc && typeof clickedFunc === "function") {
|
||||
clickedFunc()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
BasicButtonType {
|
||||
visible: root.buttonText !== ""
|
||||
SmallTextType {
|
||||
id: errorField
|
||||
|
||||
defaultColor: "transparent"
|
||||
hoveredColor: Qt.rgba(1, 1, 1, 0.08)
|
||||
pressedColor: Qt.rgba(1, 1, 1, 0.12)
|
||||
disabledColor: "#878B91"
|
||||
textColor: "#D7D8DB"
|
||||
borderWidth: 0
|
||||
|
||||
text: buttonText
|
||||
|
||||
Layout.rightMargin: 24
|
||||
|
||||
onClicked: {
|
||||
if (clickedFunc && typeof clickedFunc === "function") {
|
||||
clickedFunc()
|
||||
}
|
||||
}
|
||||
text: root.errorText
|
||||
visible: root.errorText !== ""
|
||||
color: "#EB5757"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
47
client/ui/qml/Filters/ContainersModelFilters.qml
Normal file
47
client/ui/qml/Filters/ContainersModelFilters.qml
Normal file
|
@ -0,0 +1,47 @@
|
|||
pragma Singleton
|
||||
|
||||
import QtQuick 2.15
|
||||
|
||||
import SortFilterProxyModel 0.2
|
||||
|
||||
import ProtocolEnum 1.0
|
||||
|
||||
Item {
|
||||
ValueFilter {
|
||||
id: vpnTypeFilter
|
||||
roleName: "serviceType"
|
||||
value: ProtocolEnum.Vpn
|
||||
}
|
||||
|
||||
ValueFilter {
|
||||
id: serviceTypeFilter
|
||||
roleName: "serviceType"
|
||||
value: ProtocolEnum.Other
|
||||
}
|
||||
|
||||
ValueFilter {
|
||||
id: supportedFilter
|
||||
roleName: "isSupported"
|
||||
value: true
|
||||
}
|
||||
|
||||
ValueFilter {
|
||||
id: installedFilter
|
||||
roleName: "isInstalled"
|
||||
value: true
|
||||
}
|
||||
|
||||
function getWriteAccessProtocolsListFilters() {
|
||||
return [vpnTypeFilter, supportedFilter]
|
||||
}
|
||||
function getReadAccessProtocolsListFilters() {
|
||||
return [vpnTypeFilter, supportedFilter, installedFilter]
|
||||
}
|
||||
|
||||
function getWriteAccessServicesListFilters() {
|
||||
return [serviceTypeFilter, supportedFilter]
|
||||
}
|
||||
function getReadAccessServicesListFilters() {
|
||||
return [serviceTypeFilter, supportedFilter, installedFilter]
|
||||
}
|
||||
}
|
|
@ -7,6 +7,7 @@ import SortFilterProxyModel 0.2
|
|||
import PageEnum 1.0
|
||||
import ProtocolEnum 1.0
|
||||
import ContainerProps 1.0
|
||||
import ContainersModelFilters 1.0
|
||||
|
||||
import "./"
|
||||
import "../Controls2"
|
||||
|
@ -161,10 +162,7 @@ PageType {
|
|||
headerBackButtonImage: "qrc:/images/controls/arrow-left.svg"
|
||||
|
||||
rootButtonClickedFunction: function() {
|
||||
// todo check if server index changed before set Currently processed
|
||||
// todo make signal slot for change server index in containersModel
|
||||
ServersModel.setCurrentlyProcessedServerIndex(serversMenuContent.currentIndex)
|
||||
ContainersModel.setCurrentlyProcessedServerIndex(serversMenuContent.currentIndex)
|
||||
ServersModel.currentlyProcessedIndex = serversMenuContent.currentIndex
|
||||
containersDropDown.menuVisible = true
|
||||
}
|
||||
|
||||
|
@ -177,39 +175,22 @@ PageType {
|
|||
function onCurrentlyProcessedServerIndexChanged() {
|
||||
updateContainersModelFilters()
|
||||
}
|
||||
}
|
||||
|
||||
function updateContainersModelFilters() {
|
||||
if (ServersModel.isCurrentlyProcessedServerHasWriteAccess()) {
|
||||
proxyContainersModel.filters = [serviceTypeFilter, supportedFilter]
|
||||
} else {
|
||||
proxyContainersModel.filters = installedFilter
|
||||
}
|
||||
function updateContainersModelFilters() {
|
||||
if (ServersModel.isCurrentlyProcessedServerHasWriteAccess()) {
|
||||
proxyContainersModel.filters = ContainersModelFilters.getWriteAccessProtocolsListFilters()
|
||||
} else {
|
||||
proxyContainersModel.filters = ContainersModelFilters.getReadAccessProtocolsListFilters()
|
||||
}
|
||||
}
|
||||
|
||||
ValueFilter {
|
||||
id: serviceTypeFilter
|
||||
roleName: "serviceType"
|
||||
value: ProtocolEnum.Vpn
|
||||
}
|
||||
ValueFilter {
|
||||
id: supportedFilter
|
||||
roleName: "isSupported"
|
||||
value: true
|
||||
}
|
||||
ValueFilter {
|
||||
id: installedFilter
|
||||
roleName: "isInstalled"
|
||||
value: true
|
||||
}
|
||||
|
||||
model: SortFilterProxyModel {
|
||||
id: proxyContainersModel
|
||||
sourceModel: ContainersModel
|
||||
|
||||
Component.onCompleted: updateContainersModelFilters()
|
||||
}
|
||||
|
||||
Component.onCompleted: updateContainersModelFilters()
|
||||
currentIndex: ContainersModel.getDefaultContainer()
|
||||
}
|
||||
}
|
||||
|
@ -267,7 +248,7 @@ PageType {
|
|||
height: serversMenuContent.contentItem.height
|
||||
|
||||
model: ServersModel
|
||||
currentIndex: ServersModel.getDefaultServerIndex()
|
||||
currentIndex: ServersModel.defaultIndex
|
||||
|
||||
clip: true
|
||||
interactive: false
|
||||
|
@ -305,8 +286,8 @@ PageType {
|
|||
onClicked: {
|
||||
serversMenuContent.currentIndex = index
|
||||
|
||||
isDefault = true
|
||||
ContainersModel.setCurrentlyProcessedServerIndex(index)
|
||||
ServersModel.currentlyProcessedIndex = index
|
||||
ServersModel.defaultIndex = index
|
||||
|
||||
root.currentServerName = name
|
||||
root.currentServerHostName = hostName
|
||||
|
@ -328,8 +309,7 @@ PageType {
|
|||
z: 1
|
||||
|
||||
onClicked: function() {
|
||||
ServersModel.setCurrentlyProcessedServerIndex(index)
|
||||
ContainersModel.setCurrentlyProcessedServerIndex(index)
|
||||
ServersModel.currentlyProcessedIndex = index
|
||||
goToPage(PageEnum.PageSettingsServerInfo)
|
||||
menu.visible = false
|
||||
}
|
||||
|
|
|
@ -29,6 +29,14 @@ PageType {
|
|||
}
|
||||
}
|
||||
|
||||
Connections {
|
||||
target: ServersModel
|
||||
|
||||
function onCurrentlyProcessedServerIndexChanged() {
|
||||
content.isServerWithWriteAccess = ServersModel.isCurrentlyProcessedServerHasWriteAccess()
|
||||
}
|
||||
}
|
||||
|
||||
FlickableType {
|
||||
id: fl
|
||||
anchors.top: parent.top
|
||||
|
@ -42,7 +50,10 @@ PageType {
|
|||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
|
||||
property bool isServerWithWriteAccess: ServersModel.isCurrentlyProcessedServerHasWriteAccess() //todo make it property?
|
||||
|
||||
LabelWithButtonType {
|
||||
visible: content.isServerWithWriteAccess
|
||||
Layout.fillWidth: true
|
||||
|
||||
text: qsTr("Clear Amnezia cache")
|
||||
|
@ -65,9 +76,12 @@ PageType {
|
|||
}
|
||||
}
|
||||
|
||||
DividerType {}
|
||||
DividerType {
|
||||
visible: content.isServerWithWriteAccess
|
||||
}
|
||||
|
||||
LabelWithButtonType {
|
||||
visible: content.isServerWithWriteAccess
|
||||
Layout.fillWidth: true
|
||||
|
||||
text: qsTr("Проверить сервер на наличие ранее установленных сервисов Amnezia")
|
||||
|
@ -78,12 +92,14 @@ PageType {
|
|||
}
|
||||
}
|
||||
|
||||
DividerType {}
|
||||
DividerType {
|
||||
visible: content.isServerWithWriteAccess
|
||||
}
|
||||
|
||||
LabelWithButtonType {
|
||||
Layout.fillWidth: true
|
||||
|
||||
text: "Remove server from application"
|
||||
text: qsTr("Remove server from application")
|
||||
textColor: "#EB5757"
|
||||
|
||||
clickedFunction: function() {
|
||||
|
@ -115,9 +131,10 @@ PageType {
|
|||
DividerType {}
|
||||
|
||||
LabelWithButtonType {
|
||||
visible: content.isServerWithWriteAccess
|
||||
Layout.fillWidth: true
|
||||
|
||||
text: "Clear server from Amnezia software"
|
||||
text: qsTr("Clear server from Amnezia software")
|
||||
textColor: "#EB5757"
|
||||
|
||||
clickedFunction: function() {
|
||||
|
@ -142,7 +159,9 @@ PageType {
|
|||
}
|
||||
}
|
||||
|
||||
DividerType {}
|
||||
DividerType {
|
||||
visible: content.isServerWithWriteAccess
|
||||
}
|
||||
|
||||
QuestionDrawer {
|
||||
id: questionDrawer
|
||||
|
|
|
@ -54,7 +54,13 @@ PageType {
|
|||
actionButtonImage: "qrc:/images/controls/edit-3.svg"
|
||||
|
||||
headerText: name
|
||||
descriptionText: credentialsLogin + " · " + hostName
|
||||
descriptionText: {
|
||||
if (ServersModel.isCurrentlyProcessedServerHasWriteAccess()) {
|
||||
return credentialsLogin + " · " + hostName
|
||||
} else {
|
||||
return hostName
|
||||
}
|
||||
}
|
||||
|
||||
actionButtonFunction: function() {
|
||||
serverNameEditDrawer.visible = true
|
||||
|
@ -123,10 +129,14 @@ PageType {
|
|||
}
|
||||
|
||||
TabButtonType {
|
||||
visible: protocolsPage.installedProtocolsCount
|
||||
width: protocolsPage.installedProtocolsCount ? undefined : 0
|
||||
isSelected: tabBar.currentIndex === 0
|
||||
text: qsTr("Protocols")
|
||||
}
|
||||
TabButtonType {
|
||||
visible: servicesPage.installedServicesCount
|
||||
width: servicesPage.installedServicesCount ? undefined : 0
|
||||
isSelected: tabBar.currentIndex === 1
|
||||
text: qsTr("Services")
|
||||
}
|
||||
|
@ -143,9 +153,11 @@ PageType {
|
|||
currentIndex: tabBar.currentIndex
|
||||
|
||||
PageSettingsServerProtocols {
|
||||
id: protocolsPage
|
||||
stackView: root.stackView
|
||||
}
|
||||
PageSettingsServerServices {
|
||||
id: servicesPage
|
||||
stackView: root.stackView
|
||||
}
|
||||
PageSettingsServerData {
|
||||
|
|
|
@ -7,6 +7,7 @@ import SortFilterProxyModel 0.2
|
|||
import PageEnum 1.0
|
||||
import ProtocolEnum 1.0
|
||||
import ContainerProps 1.0
|
||||
import ContainersModelFilters 1.0
|
||||
|
||||
import "./"
|
||||
import "../Controls2"
|
||||
|
@ -17,22 +18,31 @@ import "../Components"
|
|||
PageType {
|
||||
id: root
|
||||
|
||||
SortFilterProxyModel {
|
||||
id: containersProxyModel
|
||||
sourceModel: ContainersModel
|
||||
filters: [
|
||||
ValueFilter {
|
||||
roleName: "serviceType"
|
||||
value: ProtocolEnum.Vpn
|
||||
},
|
||||
ValueFilter {
|
||||
roleName: "isSupported"
|
||||
value: true
|
||||
}
|
||||
]
|
||||
}
|
||||
property var installedProtocolsCount
|
||||
|
||||
SettingsContainersListView {
|
||||
model: containersProxyModel
|
||||
Connections {
|
||||
target: ServersModel
|
||||
|
||||
function onCurrentlyProcessedServerIndexChanged() {
|
||||
updateContainersModelFilters()
|
||||
}
|
||||
}
|
||||
|
||||
function updateContainersModelFilters() {
|
||||
if (ServersModel.isCurrentlyProcessedServerHasWriteAccess()) {
|
||||
proxyContainersModel.filters = ContainersModelFilters.getWriteAccessProtocolsListFilters()
|
||||
} else {
|
||||
proxyContainersModel.filters = ContainersModelFilters.getReadAccessProtocolsListFilters()
|
||||
}
|
||||
root.installedProtocolsCount = proxyContainersModel.count
|
||||
}
|
||||
|
||||
model: SortFilterProxyModel {
|
||||
id: proxyContainersModel
|
||||
sourceModel: ContainersModel
|
||||
}
|
||||
|
||||
Component.onCompleted: updateContainersModelFilters()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,6 +7,7 @@ import SortFilterProxyModel 0.2
|
|||
import PageEnum 1.0
|
||||
import ProtocolEnum 1.0
|
||||
import ContainerProps 1.0
|
||||
import ContainersModelFilters 1.0
|
||||
|
||||
import "./"
|
||||
import "../Controls2"
|
||||
|
@ -17,22 +18,31 @@ import "../Components"
|
|||
PageType {
|
||||
id: root
|
||||
|
||||
SortFilterProxyModel {
|
||||
id: containersProxyModel
|
||||
sourceModel: ContainersModel
|
||||
filters: [
|
||||
ValueFilter {
|
||||
roleName: "serviceType"
|
||||
value: ProtocolEnum.Other
|
||||
},
|
||||
ValueFilter {
|
||||
roleName: "isSupported"
|
||||
value: true
|
||||
}
|
||||
]
|
||||
}
|
||||
property var installedServicesCount
|
||||
|
||||
SettingsContainersListView {
|
||||
model: containersProxyModel
|
||||
Connections {
|
||||
target: ServersModel
|
||||
|
||||
function onCurrentlyProcessedServerIndexChanged() {
|
||||
updateContainersModelFilters()
|
||||
}
|
||||
}
|
||||
|
||||
function updateContainersModelFilters() {
|
||||
if (ServersModel.isCurrentlyProcessedServerHasWriteAccess()) {
|
||||
proxyContainersModel.filters = ContainersModelFilters.getWriteAccessServicesListFilters()
|
||||
} else {
|
||||
proxyContainersModel.filters = ContainersModelFilters.getReadAccessServicesListFilters()
|
||||
}
|
||||
root.installedServicesCount = proxyContainersModel.count
|
||||
}
|
||||
|
||||
model: SortFilterProxyModel {
|
||||
id: proxyContainersModel
|
||||
sourceModel: ContainersModel
|
||||
}
|
||||
|
||||
Component.onCompleted: updateContainersModelFilters()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -89,8 +89,7 @@ PageType {
|
|||
rightImageSource: "qrc:/images/controls/chevron-right.svg"
|
||||
|
||||
clickedFunction: function() {
|
||||
ServersModel.setCurrentlyProcessedServerIndex(index)
|
||||
ContainersModel.setCurrentlyProcessedServerIndex(index)
|
||||
ServersModel.currentlyProcessedIndex = index
|
||||
goToPage(PageEnum.PageSettingsServerInfo)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -79,6 +79,10 @@ PageType {
|
|||
text: qsTr("Set up a server the easy way")
|
||||
|
||||
onClicked: function() {
|
||||
if (!isCredentialsFilled()) {
|
||||
return
|
||||
}
|
||||
|
||||
InstallController.setShouldCreateServer(true)
|
||||
InstallController.setCurrentlyInstalledServerCredentials(hostname.textField.text, username.textField.text, secretData.textField.text)
|
||||
|
||||
|
@ -100,6 +104,10 @@ PageType {
|
|||
text: qsTr("Select protocol to install")
|
||||
|
||||
onClicked: function() {
|
||||
if (!isCredentialsFilled()) {
|
||||
return
|
||||
}
|
||||
|
||||
InstallController.setShouldCreateServer(true)
|
||||
InstallController.setCurrentlyInstalledServerCredentials(hostname.textField.text, username.textField.text, secretData.textField.text)
|
||||
|
||||
|
@ -108,4 +116,25 @@ PageType {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
function isCredentialsFilled() {
|
||||
var hasEmptyField = false
|
||||
|
||||
if (hostname.textFieldText === "") {
|
||||
hostname.errorText = qsTr("ip address cannot be empty")
|
||||
hasEmptyField = true
|
||||
} else if (!hostname.textField.acceptableInput) {
|
||||
hostname.errorText = qsTr("Enter the address in the format 255.255.255.255:88")
|
||||
}
|
||||
|
||||
if (username.textFieldText === "") {
|
||||
username.errorText = qsTr("login cannot be empty")
|
||||
hasEmptyField = true
|
||||
}
|
||||
if (secretData.textFieldText === "") {
|
||||
secretData.errorText = qsTr("password/private key cannot be empty")
|
||||
hasEmptyField = true
|
||||
}
|
||||
return !hasEmptyField
|
||||
}
|
||||
}
|
||||
|
|
|
@ -61,7 +61,7 @@ PageType {
|
|||
|
||||
function onServerAlreadyExists(serverIndex) {
|
||||
goToStartPage()
|
||||
ServersModel.setCurrentlyProcessedServerIndex(serverIndex)
|
||||
ServersModel.currentlyProcessedIndex = serverIndex
|
||||
goToPage(PageEnum.PageSettingsServerInfo, false)
|
||||
|
||||
PageController.showErrorMessage(qsTr("The server has already been added to the application"))
|
||||
|
|
|
@ -147,18 +147,28 @@ PageType {
|
|||
|
||||
imageSource: "qrc:/images/controls/chevron-right.svg"
|
||||
|
||||
model: ServersModel
|
||||
currentIndex: ServersModel.getDefaultServerIndex()
|
||||
model: SortFilterProxyModel {
|
||||
id: proxyServersModel
|
||||
sourceModel: ServersModel
|
||||
filters: [
|
||||
ValueFilter {
|
||||
roleName: "hasWriteAccess"
|
||||
value: true
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
currentIndex: 0
|
||||
|
||||
clickedFunction: function() {
|
||||
serverSelector.text = selectedText
|
||||
ContainersModel.setCurrentlyProcessedServerIndex(currentIndex)
|
||||
ServersModel.currentlyProcessedIndex = currentIndex
|
||||
protocolSelector.visible = true
|
||||
}
|
||||
|
||||
Component.onCompleted: {
|
||||
serverSelector.text = selectedText
|
||||
ContainersModel.setCurrentlyProcessedServerIndex(currentIndex)
|
||||
ServersModel.currentlyProcessedIndex = currentIndex
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -169,7 +179,7 @@ PageType {
|
|||
height: parent.height * 0.5
|
||||
|
||||
ColumnLayout {
|
||||
id: header
|
||||
id: protocolSelectorHeader
|
||||
|
||||
anchors.top: parent.top
|
||||
anchors.left: parent.left
|
||||
|
@ -187,12 +197,12 @@ PageType {
|
|||
}
|
||||
|
||||
FlickableType {
|
||||
anchors.top: header.bottom
|
||||
anchors.top: protocolSelectorHeader.bottom
|
||||
anchors.topMargin: 16
|
||||
contentHeight: col.implicitHeight
|
||||
contentHeight: protocolSelectorContent.implicitHeight
|
||||
|
||||
Column {
|
||||
id: col
|
||||
id: protocolSelectorContent
|
||||
anchors.top: parent.top
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
|
@ -265,7 +275,7 @@ PageType {
|
|||
}
|
||||
|
||||
DropDownType {
|
||||
id: connectionTypeSelector
|
||||
id: exportTypeSelector
|
||||
|
||||
property int currentIndex
|
||||
|
||||
|
@ -283,8 +293,6 @@ PageType {
|
|||
headerText: qsTr("Connection format")
|
||||
|
||||
listView: ListViewType {
|
||||
id: connectionTypeSelectorListView
|
||||
|
||||
rootWidth: root.width
|
||||
dividerVisible: true
|
||||
|
||||
|
@ -294,14 +302,14 @@ PageType {
|
|||
currentIndex: 0
|
||||
|
||||
clickedFunction: function() {
|
||||
connectionTypeSelector.text = selectedText
|
||||
connectionTypeSelector.currentIndex = currentIndex
|
||||
connectionTypeSelector.menuVisible = false
|
||||
exportTypeSelector.text = selectedText
|
||||
exportTypeSelector.currentIndex = currentIndex
|
||||
exportTypeSelector.menuVisible = false
|
||||
}
|
||||
|
||||
Component.onCompleted: {
|
||||
connectionTypeSelector.text = selectedText
|
||||
connectionTypeSelector.currentIndex = currentIndex
|
||||
exportTypeSelector.text = selectedText
|
||||
exportTypeSelector.currentIndex = currentIndex
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -50,8 +50,7 @@ PageType {
|
|||
|
||||
Component.onCompleted: {
|
||||
var pagePath = PageController.getPagePath(PageEnum.PageHome)
|
||||
ServersModel.setCurrentlyProcessedServerIndex(ServersModel.getDefaultServerIndex())
|
||||
ContainersModel.setCurrentlyProcessedServerIndex(ServersModel.getDefaultServerIndex())
|
||||
ServersModel.currentlyProcessedIndex = ServersModel.defaultIndex
|
||||
tabBarStackView.push(pagePath, { "objectName" : pagePath })
|
||||
}
|
||||
}
|
||||
|
@ -65,8 +64,8 @@ PageType {
|
|||
|
||||
topPadding: 8
|
||||
bottomPadding: 8//34
|
||||
leftPadding: 96
|
||||
rightPadding: 96
|
||||
leftPadding: shareTabButton.visible ? 96 : 128
|
||||
rightPadding: shareTabButton.visible ? 96 : 128
|
||||
|
||||
background: Rectangle {
|
||||
border.width: 1
|
||||
|
@ -78,11 +77,25 @@ PageType {
|
|||
isSelected: tabBar.currentIndex === 0
|
||||
image: "qrc:/images/controls/home.svg"
|
||||
onClicked: {
|
||||
ContainersModel.setCurrentlyProcessedServerIndex(ServersModel.getDefaultServerIndex())
|
||||
ServersModel.currentlyProcessedIndex = ServersModel.defaultIndex
|
||||
tabBarStackView.goToTabBarPage(PageEnum.PageHome)
|
||||
}
|
||||
}
|
||||
TabImageButtonType {
|
||||
id: shareTabButton
|
||||
|
||||
Connections {
|
||||
target: ServersModel
|
||||
|
||||
function onDefaultServerIndexChanged() {
|
||||
shareTabButton.visible = ServersModel.isCurrentlyProcessedServerHasWriteAccess()
|
||||
shareTabButton.width = ServersModel.isCurrentlyProcessedServerHasWriteAccess() ? undefined : 0
|
||||
}
|
||||
}
|
||||
|
||||
visible: ServersModel.isCurrentlyProcessedServerHasWriteAccess()
|
||||
width: visible ? undefined : 0
|
||||
|
||||
isSelected: tabBar.currentIndex === 1
|
||||
image: "qrc:/images/controls/share-2.svg"
|
||||
onClicked: {
|
||||
|
@ -100,8 +113,8 @@ PageType {
|
|||
|
||||
MouseArea {
|
||||
anchors.fill: tabBar
|
||||
anchors.leftMargin: 96
|
||||
anchors.rightMargin: 96
|
||||
anchors.leftMargin: shareTabButton.visible ? 96 : 128
|
||||
anchors.rightMargin: shareTabButton.visible ? 96 : 128
|
||||
cursorShape: Qt.PointingHandCursor
|
||||
enabled: false
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue