mirror of
https://github.com/amnezia-vpn/amnezia-client.git
synced 2026-06-23 02:00:20 +07:00
Merge branch 'feature/graphview' of github.com:amnezia-vpn/amnezia-client into feature/graphview-ios
This commit is contained in:
@@ -14,8 +14,8 @@ jobs:
|
|||||||
runs-on: ubuntu-20.04
|
runs-on: ubuntu-20.04
|
||||||
|
|
||||||
env:
|
env:
|
||||||
QT_VERSION: 6.5.1
|
QT_VERSION: 6.6.2
|
||||||
QIF_VERSION: 4.6
|
QIF_VERSION: 4.7
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: 'Install Qt'
|
- name: 'Install Qt'
|
||||||
@@ -72,8 +72,8 @@ jobs:
|
|||||||
runs-on: windows-latest
|
runs-on: windows-latest
|
||||||
|
|
||||||
env:
|
env:
|
||||||
QT_VERSION: 6.5.1
|
QT_VERSION: 6.6.2
|
||||||
QIF_VERSION: 4.6
|
QIF_VERSION: 4.7
|
||||||
BUILD_ARCH: 64
|
BUILD_ARCH: 64
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
@@ -134,7 +134,7 @@ jobs:
|
|||||||
runs-on: macos-13
|
runs-on: macos-13
|
||||||
|
|
||||||
env:
|
env:
|
||||||
QT_VERSION: 6.5.2
|
QT_VERSION: 6.6.2
|
||||||
CC: cc
|
CC: cc
|
||||||
CXX: c++
|
CXX: c++
|
||||||
|
|
||||||
@@ -227,7 +227,7 @@ jobs:
|
|||||||
env:
|
env:
|
||||||
# Keep compat with MacOS 10.15 aka Catalina by Qt 6.4
|
# Keep compat with MacOS 10.15 aka Catalina by Qt 6.4
|
||||||
QT_VERSION: 6.4.3
|
QT_VERSION: 6.4.3
|
||||||
QIF_VERSION: 4.6
|
QIF_VERSION: 4.7
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: 'Setup xcode'
|
- name: 'Setup xcode'
|
||||||
@@ -286,7 +286,7 @@ jobs:
|
|||||||
|
|
||||||
env:
|
env:
|
||||||
ANDROID_BUILD_PLATFORM: android-34
|
ANDROID_BUILD_PLATFORM: android-34
|
||||||
QT_VERSION: 6.6.1
|
QT_VERSION: 6.6.2
|
||||||
QT_MODULES: 'qtremoteobjects qt5compat qtimageformats qtshadertools qtcharts'
|
QT_MODULES: 'qtremoteobjects qt5compat qtimageformats qtshadertools qtcharts'
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
|
|||||||
@@ -131,3 +131,6 @@ client/3rd/ShadowSocks/ss_ios.xcconfig
|
|||||||
|
|
||||||
# UML generated pics
|
# UML generated pics
|
||||||
out/
|
out/
|
||||||
|
|
||||||
|
# CMake files
|
||||||
|
CMakeFiles/
|
||||||
+1
-1
@@ -11,7 +11,7 @@ string(TIMESTAMP CURRENT_DATE "%Y-%m-%d")
|
|||||||
set(RELEASE_DATE "${CURRENT_DATE}")
|
set(RELEASE_DATE "${CURRENT_DATE}")
|
||||||
|
|
||||||
set(APP_MAJOR_VERSION ${CMAKE_PROJECT_VERSION_MAJOR}.${CMAKE_PROJECT_VERSION_MINOR}.${CMAKE_PROJECT_VERSION_PATCH})
|
set(APP_MAJOR_VERSION ${CMAKE_PROJECT_VERSION_MAJOR}.${CMAKE_PROJECT_VERSION_MINOR}.${CMAKE_PROJECT_VERSION_PATCH})
|
||||||
set(APP_ANDROID_VERSION_CODE 45)
|
set(APP_ANDROID_VERSION_CODE 46)
|
||||||
|
|
||||||
if(${CMAKE_SYSTEM_NAME} STREQUAL "Linux")
|
if(${CMAKE_SYSTEM_NAME} STREQUAL "Linux")
|
||||||
set(MZ_PLATFORM_NAME "linux")
|
set(MZ_PLATFORM_NAME "linux")
|
||||||
|
|||||||
@@ -15,6 +15,15 @@ set(PACKAGES
|
|||||||
Core5Compat Concurrent LinguistTools Charts
|
Core5Compat Concurrent LinguistTools Charts
|
||||||
)
|
)
|
||||||
|
|
||||||
|
execute_process(
|
||||||
|
WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}"
|
||||||
|
COMMAND git rev-parse --short HEAD
|
||||||
|
OUTPUT_VARIABLE GIT_COMMIT_HASH
|
||||||
|
OUTPUT_STRIP_TRAILING_WHITESPACE
|
||||||
|
)
|
||||||
|
|
||||||
|
add_definitions(-DGIT_COMMIT_HASH="${GIT_COMMIT_HASH}")
|
||||||
|
|
||||||
if(IOS)
|
if(IOS)
|
||||||
set(PACKAGES ${PACKAGES} Multimedia)
|
set(PACKAGES ${PACKAGES} Multimedia)
|
||||||
endif()
|
endif()
|
||||||
@@ -57,6 +66,7 @@ set(AMNEZIAVPN_TS_FILES
|
|||||||
${CMAKE_CURRENT_LIST_DIR}/translations/amneziavpn_ru.ts
|
${CMAKE_CURRENT_LIST_DIR}/translations/amneziavpn_ru.ts
|
||||||
${CMAKE_CURRENT_LIST_DIR}/translations/amneziavpn_zh_CN.ts
|
${CMAKE_CURRENT_LIST_DIR}/translations/amneziavpn_zh_CN.ts
|
||||||
${CMAKE_CURRENT_LIST_DIR}/translations/amneziavpn_fa_IR.ts
|
${CMAKE_CURRENT_LIST_DIR}/translations/amneziavpn_fa_IR.ts
|
||||||
|
${CMAKE_CURRENT_LIST_DIR}/translations/amneziavpn_ar.ts
|
||||||
)
|
)
|
||||||
|
|
||||||
file(GLOB_RECURSE AMNEZIAVPN_TS_SOURCES *.qrc *.cpp *.h *.ui)
|
file(GLOB_RECURSE AMNEZIAVPN_TS_SOURCES *.qrc *.cpp *.h *.ui)
|
||||||
|
|||||||
@@ -286,10 +286,16 @@ void AmneziaApplication::initModels()
|
|||||||
m_containersModel.reset(new ContainersModel(this));
|
m_containersModel.reset(new ContainersModel(this));
|
||||||
m_engine->rootContext()->setContextProperty("ContainersModel", m_containersModel.get());
|
m_engine->rootContext()->setContextProperty("ContainersModel", m_containersModel.get());
|
||||||
|
|
||||||
|
m_defaultServerContainersModel.reset(new ContainersModel(this));
|
||||||
|
m_engine->rootContext()->setContextProperty("DefaultServerContainersModel", m_defaultServerContainersModel.get());
|
||||||
|
|
||||||
m_serversModel.reset(new ServersModel(m_settings, this));
|
m_serversModel.reset(new ServersModel(m_settings, this));
|
||||||
m_engine->rootContext()->setContextProperty("ServersModel", m_serversModel.get());
|
m_engine->rootContext()->setContextProperty("ServersModel", m_serversModel.get());
|
||||||
connect(m_serversModel.get(), &ServersModel::containersUpdated, m_containersModel.get(),
|
connect(m_serversModel.get(), &ServersModel::containersUpdated, m_containersModel.get(),
|
||||||
&ContainersModel::updateModel);
|
&ContainersModel::updateModel);
|
||||||
|
connect(m_serversModel.get(), &ServersModel::defaultServerContainersUpdated, m_defaultServerContainersModel.get(),
|
||||||
|
&ContainersModel::updateModel);
|
||||||
|
m_serversModel->resetModel();
|
||||||
|
|
||||||
m_languageModel.reset(new LanguageModel(m_settings, this));
|
m_languageModel.reset(new LanguageModel(m_settings, this));
|
||||||
m_engine->rootContext()->setContextProperty("LanguageModel", m_languageModel.get());
|
m_engine->rootContext()->setContextProperty("LanguageModel", m_languageModel.get());
|
||||||
@@ -333,7 +339,7 @@ void AmneziaApplication::initModels()
|
|||||||
connect(m_configurator.get(), &VpnConfigurator::newVpnConfigCreated, this,
|
connect(m_configurator.get(), &VpnConfigurator::newVpnConfigCreated, this,
|
||||||
[this](const QString &clientId, const QString &clientName, const DockerContainer container,
|
[this](const QString &clientId, const QString &clientName, const DockerContainer container,
|
||||||
ServerCredentials credentials) {
|
ServerCredentials credentials) {
|
||||||
m_serversModel->reloadContainerConfig();
|
m_serversModel->reloadDefaultServerContainerConfig();
|
||||||
m_clientManagementModel->appendClient(clientId, clientName, container, credentials);
|
m_clientManagementModel->appendClient(clientId, clientName, container, credentials);
|
||||||
emit m_configurator->clientModelUpdated();
|
emit m_configurator->clientModelUpdated();
|
||||||
});
|
});
|
||||||
@@ -385,7 +391,13 @@ void AmneziaApplication::initControllers()
|
|||||||
m_engine->rootContext()->setContextProperty("ApiController", m_apiController.get());
|
m_engine->rootContext()->setContextProperty("ApiController", m_apiController.get());
|
||||||
connect(m_apiController.get(), &ApiController::updateStarted, this,
|
connect(m_apiController.get(), &ApiController::updateStarted, this,
|
||||||
[this]() { emit m_vpnConnection->connectionStateChanged(Vpn::ConnectionState::Connecting); });
|
[this]() { emit m_vpnConnection->connectionStateChanged(Vpn::ConnectionState::Connecting); });
|
||||||
connect(m_apiController.get(), &ApiController::errorOccurred, this,
|
connect(m_apiController.get(), &ApiController::errorOccurred, this, [this](const QString &errorMessage) {
|
||||||
[this]() { emit m_vpnConnection->connectionStateChanged(Vpn::ConnectionState::Disconnected); });
|
if (m_connectionController->isConnectionInProgress()) {
|
||||||
connect(m_apiController.get(), &ApiController::updateFinished, m_connectionController.get(), &ConnectionController::toggleConnection);
|
emit m_pageController->showErrorMessage(errorMessage);
|
||||||
|
}
|
||||||
|
|
||||||
|
emit m_vpnConnection->connectionStateChanged(Vpn::ConnectionState::Disconnected);
|
||||||
|
});
|
||||||
|
connect(m_apiController.get(), &ApiController::updateFinished, m_connectionController.get(),
|
||||||
|
&ConnectionController::toggleConnection);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -94,6 +94,7 @@ private:
|
|||||||
QCommandLineParser m_parser;
|
QCommandLineParser m_parser;
|
||||||
|
|
||||||
QSharedPointer<ContainersModel> m_containersModel;
|
QSharedPointer<ContainersModel> m_containersModel;
|
||||||
|
QSharedPointer<ContainersModel> m_defaultServerContainersModel;
|
||||||
QSharedPointer<ServersModel> m_serversModel;
|
QSharedPointer<ServersModel> m_serversModel;
|
||||||
QSharedPointer<LanguageModel> m_languageModel;
|
QSharedPointer<LanguageModel> m_languageModel;
|
||||||
QSharedPointer<ProtocolsModel> m_protocolsModel;
|
QSharedPointer<ProtocolsModel> m_protocolsModel;
|
||||||
|
|||||||
@@ -22,7 +22,7 @@
|
|||||||
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" android:maxSdkVersion="28" />
|
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" android:maxSdkVersion="28" />
|
||||||
<uses-permission android:name="android.permission.CAMERA" />
|
<uses-permission android:name="android.permission.CAMERA" />
|
||||||
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
|
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
|
||||||
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_SPECIAL_USE" />
|
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_SYSTEM_EXEMPTED" />
|
||||||
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
|
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
|
||||||
|
|
||||||
<!-- Enable when VPN-per-app mode will be implemented -->
|
<!-- Enable when VPN-per-app mode will be implemented -->
|
||||||
@@ -137,14 +137,13 @@
|
|||||||
android:name=".AmneziaVpnService"
|
android:name=".AmneziaVpnService"
|
||||||
android:process=":amneziaVpnService"
|
android:process=":amneziaVpnService"
|
||||||
android:permission="android.permission.BIND_VPN_SERVICE"
|
android:permission="android.permission.BIND_VPN_SERVICE"
|
||||||
android:foregroundServiceType="specialUse"
|
android:foregroundServiceType="systemExempted"
|
||||||
android:exported="false">
|
android:exported="false"
|
||||||
|
tools:ignore="ForegroundServicePermission">
|
||||||
|
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
<action android:name="android.net.VpnService" />
|
<action android:name="android.net.VpnService" />
|
||||||
</intent-filter>
|
</intent-filter>
|
||||||
|
|
||||||
<property android:name="android.app.PROPERTY_SPECIAL_USE_FGS_SUBTYPE" android:value="vpn" />
|
|
||||||
</service>
|
</service>
|
||||||
|
|
||||||
<provider
|
<provider
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import android.app.Notification
|
|||||||
import android.app.PendingIntent
|
import android.app.PendingIntent
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.content.pm.ServiceInfo.FOREGROUND_SERVICE_TYPE_MANIFEST
|
import android.content.pm.ServiceInfo.FOREGROUND_SERVICE_TYPE_MANIFEST
|
||||||
import android.content.pm.ServiceInfo.FOREGROUND_SERVICE_TYPE_SPECIAL_USE
|
import android.content.pm.ServiceInfo.FOREGROUND_SERVICE_TYPE_SYSTEM_EXEMPTED
|
||||||
import android.net.VpnService
|
import android.net.VpnService
|
||||||
import android.os.Build
|
import android.os.Build
|
||||||
import android.os.Handler
|
import android.os.Handler
|
||||||
@@ -156,7 +156,7 @@ class AmneziaVpnService : VpnService() {
|
|||||||
*/
|
*/
|
||||||
private val foregroundServiceTypeCompat
|
private val foregroundServiceTypeCompat
|
||||||
get() = when {
|
get() = when {
|
||||||
Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE -> FOREGROUND_SERVICE_TYPE_SPECIAL_USE
|
Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE -> FOREGROUND_SERVICE_TYPE_SYSTEM_EXEMPTED
|
||||||
Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q -> FOREGROUND_SERVICE_TYPE_MANIFEST
|
Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q -> FOREGROUND_SERVICE_TYPE_MANIFEST
|
||||||
else -> 0
|
else -> 0
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -211,13 +211,7 @@ ErrorCode ServerController::uploadFileToHost(const ServerCredentials &credential
|
|||||||
localFile.write(data);
|
localFile.write(data);
|
||||||
localFile.close();
|
localFile.close();
|
||||||
|
|
||||||
#ifdef Q_OS_WINDOWS
|
error = m_sshClient.sftpFileCopy(overwriteMode, localFile.fileName(), remotePath, "non_desc");
|
||||||
error = m_sshClient.sftpFileCopy(overwriteMode, localFile.fileName().toLocal8Bit().toStdString(), remotePath.toStdString(),
|
|
||||||
"non_desc");
|
|
||||||
#else
|
|
||||||
error = m_sshClient.sftpFileCopy(overwriteMode, localFile.fileName().toStdString(), remotePath.toStdString(),
|
|
||||||
"non_desc");
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (error != ErrorCode::NoError) {
|
if (error != ErrorCode::NoError) {
|
||||||
return error;
|
return error;
|
||||||
|
|||||||
+13
-15
@@ -222,7 +222,7 @@ namespace libssh {
|
|||||||
return fromLibsshErrorCode();
|
return fromLibsshErrorCode();
|
||||||
}
|
}
|
||||||
|
|
||||||
ErrorCode Client::sftpFileCopy(const SftpOverwriteMode overwriteMode, const std::string& localPath, const std::string& remotePath, const std::string& fileDesc)
|
ErrorCode Client::sftpFileCopy(const SftpOverwriteMode overwriteMode, const QString& localPath, const QString& remotePath, const QString &fileDesc)
|
||||||
{
|
{
|
||||||
m_sftpSession = sftp_new(m_session);
|
m_sftpSession = sftp_new(m_session);
|
||||||
|
|
||||||
@@ -245,40 +245,38 @@ namespace libssh {
|
|||||||
const size_t bufferSize = 16384;
|
const size_t bufferSize = 16384;
|
||||||
char buffer[bufferSize];
|
char buffer[bufferSize];
|
||||||
|
|
||||||
file = sftp_open(m_sftpSession, remotePath.c_str(), accessType, S_IRWXU);
|
file = sftp_open(m_sftpSession, remotePath.toStdString().c_str(), accessType, S_IRWXU);
|
||||||
|
|
||||||
if (file == nullptr) {
|
if (file == nullptr) {
|
||||||
return closeSftpSession();
|
return closeSftpSession();
|
||||||
}
|
}
|
||||||
|
|
||||||
int localFileSize = std::filesystem::file_size(localPath);
|
int localFileSize = QFileInfo(localPath).size();
|
||||||
int chunksCount = localFileSize / (bufferSize);
|
int chunksCount = localFileSize / (bufferSize);
|
||||||
|
|
||||||
std::ifstream fin(localPath, std::ios::binary | std::ios::in);
|
QFile fin(localPath);
|
||||||
|
|
||||||
if (fin.is_open()) {
|
if (fin.open(QIODevice::ReadOnly)) {
|
||||||
for (int currentChunkId = 0; currentChunkId < chunksCount; currentChunkId++) {
|
for (int currentChunkId = 0; currentChunkId < chunksCount; currentChunkId++) {
|
||||||
fin.read(buffer, bufferSize);
|
QByteArray chunk = fin.read(bufferSize);
|
||||||
|
if (chunk.size() != bufferSize) return ErrorCode::SshSftpEofError;
|
||||||
|
|
||||||
int bytesWritten = sftp_write(file, buffer, bufferSize);
|
int bytesWritten = sftp_write(file, chunk.data(), chunk.size());
|
||||||
|
|
||||||
std::string chunk(buffer, bufferSize);
|
if (bytesWritten != chunk.size()) {
|
||||||
|
|
||||||
if (bytesWritten != bufferSize) {
|
|
||||||
fin.close();
|
fin.close();
|
||||||
sftp_close(file);
|
sftp_close(file);
|
||||||
return closeSftpSession();
|
return closeSftpSession();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int lastChunkSize = localFileSize % (bufferSize);
|
int lastChunkSize = localFileSize % bufferSize;
|
||||||
|
|
||||||
if (lastChunkSize != 0) {
|
if (lastChunkSize != 0) {
|
||||||
fin.read(buffer, lastChunkSize);
|
QByteArray lastChunk = fin.read(lastChunkSize);
|
||||||
|
if (lastChunk.size() != lastChunkSize) return ErrorCode::SshSftpEofError;
|
||||||
|
|
||||||
std::string chunk(buffer, lastChunkSize);
|
int bytesWritten = sftp_write(file, lastChunk.data(), lastChunkSize);
|
||||||
|
|
||||||
int bytesWritten = sftp_write(file, buffer, lastChunkSize);
|
|
||||||
|
|
||||||
if (bytesWritten != lastChunkSize) {
|
if (bytesWritten != lastChunkSize) {
|
||||||
fin.close();
|
fin.close();
|
||||||
|
|||||||
@@ -33,9 +33,9 @@ namespace libssh {
|
|||||||
const std::function<ErrorCode (const QString &, Client &)> &cbReadStdErr);
|
const std::function<ErrorCode (const QString &, Client &)> &cbReadStdErr);
|
||||||
ErrorCode writeResponse(const QString &data);
|
ErrorCode writeResponse(const QString &data);
|
||||||
ErrorCode sftpFileCopy(const SftpOverwriteMode overwriteMode,
|
ErrorCode sftpFileCopy(const SftpOverwriteMode overwriteMode,
|
||||||
const std::string& localPath,
|
const QString &localPath,
|
||||||
const std::string& remotePath,
|
const QString &remotePath,
|
||||||
const std::string& fileDesc);
|
const QString& fileDesc);
|
||||||
ErrorCode getDecryptedPrivateKey(const ServerCredentials &credentials, QString &decryptedPrivateKey, const std::function<QString()> &passphraseCallback);
|
ErrorCode getDecryptedPrivateKey(const ServerCredentials &credentials, QString &decryptedPrivateKey, const std::function<QString()> &passphraseCallback);
|
||||||
private:
|
private:
|
||||||
ErrorCode closeChannel();
|
ErrorCode closeChannel();
|
||||||
|
|||||||
@@ -500,7 +500,6 @@ bool Daemon::switchServer(const InterfaceConfig& config) {
|
|||||||
QJsonObject Daemon::getStatus() {
|
QJsonObject Daemon::getStatus() {
|
||||||
Q_ASSERT(wgutils() != nullptr);
|
Q_ASSERT(wgutils() != nullptr);
|
||||||
QJsonObject json;
|
QJsonObject json;
|
||||||
logger.debug() << "Status request";
|
|
||||||
|
|
||||||
if (!wgutils()->interfaceExists() || m_connections.isEmpty()) {
|
if (!wgutils()->interfaceExists() || m_connections.isEmpty()) {
|
||||||
json.insert("connected", QJsonValue(false));
|
json.insert("connected", QJsonValue(false));
|
||||||
|
|||||||
@@ -46,8 +46,6 @@ DaemonLocalServerConnection::~DaemonLocalServerConnection() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void DaemonLocalServerConnection::readData() {
|
void DaemonLocalServerConnection::readData() {
|
||||||
logger.debug() << "Read Data";
|
|
||||||
|
|
||||||
Q_ASSERT(m_socket);
|
Q_ASSERT(m_socket);
|
||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
@@ -90,8 +88,6 @@ void DaemonLocalServerConnection::parseCommand(const QByteArray& data) {
|
|||||||
}
|
}
|
||||||
QString type = typeValue.toString();
|
QString type = typeValue.toString();
|
||||||
|
|
||||||
logger.debug() << "Command received:" << type;
|
|
||||||
|
|
||||||
if (type == "activate") {
|
if (type == "activate") {
|
||||||
InterfaceConfig config;
|
InterfaceConfig config;
|
||||||
if (!Daemon::parseConfig(obj, config)) {
|
if (!Daemon::parseConfig(obj, config)) {
|
||||||
|
|||||||
@@ -0,0 +1,6 @@
|
|||||||
|
<svg width="19" height="18" viewBox="0 0 19 18" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<rect x="0.5" width="18" height="18" rx="5" fill="white"/>
|
||||||
|
<path d="M8.49219 13.5L8.49219 9.44141L14.0191 4.99484" stroke="#0E0E11" stroke-linecap="round" stroke-linejoin="round"/>
|
||||||
|
<path d="M4.47363 5.49805L6.98828 8.0127" stroke="#0E0E11" stroke-linecap="round" stroke-linejoin="round"/>
|
||||||
|
<path d="M14.4727 9.5L14.4727 4.5033L9.50195 4.5033" stroke="#0E0E11" stroke-linecap="round" stroke-linejoin="round"/>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 511 B |
@@ -85,6 +85,7 @@ target_sources(networkextension PRIVATE
|
|||||||
${CLIENT_ROOT_DIR}/platforms/ios/LogRecord.swift
|
${CLIENT_ROOT_DIR}/platforms/ios/LogRecord.swift
|
||||||
${CLIENT_ROOT_DIR}/platforms/ios/PacketTunnelProvider.swift
|
${CLIENT_ROOT_DIR}/platforms/ios/PacketTunnelProvider.swift
|
||||||
${CLIENT_ROOT_DIR}/platforms/ios/PacketTunnelProvider+OpenVPNAdapterDelegate.swift
|
${CLIENT_ROOT_DIR}/platforms/ios/PacketTunnelProvider+OpenVPNAdapterDelegate.swift
|
||||||
|
${CLIENT_ROOT_DIR}/platforms/ios/WGConfig.swift
|
||||||
${CLIENT_ROOT_DIR}/platforms/ios/iosglue.mm
|
${CLIENT_ROOT_DIR}/platforms/ios/iosglue.mm
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -124,7 +124,10 @@ void LocalSocketController::activate(const QJsonObject &rawConfig) {
|
|||||||
// json.insert("hopindex", QJsonValue((double)hop.m_hopindex));
|
// json.insert("hopindex", QJsonValue((double)hop.m_hopindex));
|
||||||
json.insert("privateKey", wgConfig.value(amnezia::config_key::client_priv_key));
|
json.insert("privateKey", wgConfig.value(amnezia::config_key::client_priv_key));
|
||||||
json.insert("deviceIpv4Address", wgConfig.value(amnezia::config_key::client_ip));
|
json.insert("deviceIpv4Address", wgConfig.value(amnezia::config_key::client_ip));
|
||||||
|
// todo review wg ipv6
|
||||||
|
#ifndef Q_OS_WINDOWS
|
||||||
json.insert("deviceIpv6Address", "dead::1");
|
json.insert("deviceIpv6Address", "dead::1");
|
||||||
|
#endif
|
||||||
json.insert("serverPublicKey", wgConfig.value(amnezia::config_key::server_pub_key));
|
json.insert("serverPublicKey", wgConfig.value(amnezia::config_key::server_pub_key));
|
||||||
json.insert("serverPskKey", wgConfig.value(amnezia::config_key::psk_key));
|
json.insert("serverPskKey", wgConfig.value(amnezia::config_key::psk_key));
|
||||||
json.insert("serverIpv4AddrIn", wgConfig.value(amnezia::config_key::hostName));
|
json.insert("serverIpv4AddrIn", wgConfig.value(amnezia::config_key::hostName));
|
||||||
@@ -247,8 +250,6 @@ void LocalSocketController::deactivate() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void LocalSocketController::checkStatus() {
|
void LocalSocketController::checkStatus() {
|
||||||
logger.debug() << "Check status";
|
|
||||||
|
|
||||||
if (m_daemonState == eReady || m_daemonState == eInitializing) {
|
if (m_daemonState == eReady || m_daemonState == eInitializing) {
|
||||||
Q_ASSERT(m_socket);
|
Q_ASSERT(m_socket);
|
||||||
|
|
||||||
@@ -298,7 +299,6 @@ void LocalSocketController::cleanupBackendLogs() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void LocalSocketController::readData() {
|
void LocalSocketController::readData() {
|
||||||
logger.debug() << "Reading";
|
|
||||||
|
|
||||||
Q_ASSERT(m_socket);
|
Q_ASSERT(m_socket);
|
||||||
Q_ASSERT(m_daemonState == eInitializing || m_daemonState == eReady);
|
Q_ASSERT(m_daemonState == eInitializing || m_daemonState == eReady);
|
||||||
@@ -340,8 +340,6 @@ void LocalSocketController::parseCommand(const QByteArray& command) {
|
|||||||
}
|
}
|
||||||
QString type = typeValue.toString();
|
QString type = typeValue.toString();
|
||||||
|
|
||||||
logger.debug() << "Parse command:" << type;
|
|
||||||
|
|
||||||
if (m_daemonState == eInitializing && type == "status") {
|
if (m_daemonState == eInitializing && type == "status") {
|
||||||
m_daemonState = eReady;
|
m_daemonState = eReady;
|
||||||
|
|
||||||
@@ -367,6 +365,7 @@ void LocalSocketController::parseCommand(const QByteArray& command) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
emit initialized(true, connected.toBool(), datetime);
|
emit initialized(true, connected.toBool(), datetime);
|
||||||
|
checkStatus();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -59,10 +59,6 @@ class PacketTunnelProvider: NEPacketTunnelProvider {
|
|||||||
var stopHandler: (() -> Void)?
|
var stopHandler: (() -> Void)?
|
||||||
var protoType: TunnelProtoType = .none
|
var protoType: TunnelProtoType = .none
|
||||||
|
|
||||||
override init() {
|
|
||||||
super.init()
|
|
||||||
}
|
|
||||||
|
|
||||||
override func handleAppMessage(_ messageData: Data, completionHandler: ((Data?) -> Void)? = nil) {
|
override func handleAppMessage(_ messageData: Data, completionHandler: ((Data?) -> Void)? = nil) {
|
||||||
let tmpStr = String(data: messageData, encoding: .utf8)!
|
let tmpStr = String(data: messageData, encoding: .utf8)!
|
||||||
wg_log(.error, message: tmpStr)
|
wg_log(.error, message: tmpStr)
|
||||||
@@ -71,7 +67,7 @@ class PacketTunnelProvider: NEPacketTunnelProvider {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
guard let completionHandler = completionHandler else {
|
guard let completionHandler else {
|
||||||
log(.error, message: "Missing message completion handler")
|
log(.error, message: "Missing message completion handler")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -179,14 +175,16 @@ class PacketTunnelProvider: NEPacketTunnelProvider {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
let wgConfigStr = String(data: wgConfig, encoding: .utf8)!
|
guard let wgConfigStr = try? JSONDecoder().decode(WGConfig.self, from: wgConfig).str,
|
||||||
|
let tunnelConfiguration = try? TunnelConfiguration(fromWgQuickConfig: wgConfigStr)
|
||||||
guard let tunnelConfiguration = try? TunnelConfiguration(fromWgQuickConfig: wgConfigStr) else {
|
else {
|
||||||
wg_log(.error, message: "Can't parse WireGuard config")
|
wg_log(.error, message: "Can't parse WireGuard config")
|
||||||
completionHandler(nil)
|
completionHandler(nil)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
log(.info, message: "wgConfig: \(wgConfigStr.replacingOccurrences(of: "\n", with: " "))")
|
||||||
|
|
||||||
if tunnelConfiguration.peers.first!.allowedIPs
|
if tunnelConfiguration.peers.first!.allowedIPs
|
||||||
.map({ $0.stringRepresentation })
|
.map({ $0.stringRepresentation })
|
||||||
.joined(separator: ", ") == "0.0.0.0/0, ::/0" {
|
.joined(separator: ", ") == "0.0.0.0/0, ::/0" {
|
||||||
|
|||||||
@@ -0,0 +1,135 @@
|
|||||||
|
import Foundation
|
||||||
|
|
||||||
|
struct WGConfigData: Decodable {
|
||||||
|
let initPacketMagicHeader, responsePacketMagicHeader: String?
|
||||||
|
let underloadPacketMagicHeader, transportPacketMagicHeader: String?
|
||||||
|
let junkPacketCount, junkPacketMinSize, junkPacketMaxSize: String?
|
||||||
|
let initPacketJunkSize, responsePacketJunkSize: String?
|
||||||
|
|
||||||
|
var settings: String {
|
||||||
|
junkPacketCount == nil ? "" :
|
||||||
|
"""
|
||||||
|
Jc = \(junkPacketCount!)
|
||||||
|
Jmin = \(junkPacketMinSize!)
|
||||||
|
Jmax = \(junkPacketMaxSize!)
|
||||||
|
S1 = \(initPacketJunkSize!)
|
||||||
|
S2 = \(responsePacketJunkSize!)
|
||||||
|
H1 = \(initPacketMagicHeader!)
|
||||||
|
H2 = \(responsePacketMagicHeader!)
|
||||||
|
H3 = \(underloadPacketMagicHeader!)
|
||||||
|
H4 = \(transportPacketMagicHeader!)
|
||||||
|
|
||||||
|
"""
|
||||||
|
}
|
||||||
|
|
||||||
|
let clientIP: String
|
||||||
|
let clientPrivateKey: String
|
||||||
|
let clientPublicKey: String
|
||||||
|
let serverPublicKey: String
|
||||||
|
let presharedKey: String
|
||||||
|
let hostName: String
|
||||||
|
let port: Int
|
||||||
|
|
||||||
|
var allowedIPs: [String]
|
||||||
|
var persistentKeepAlive: String
|
||||||
|
|
||||||
|
enum CodingKeys: String, CodingKey {
|
||||||
|
case initPacketMagicHeader = "H1", responsePacketMagicHeader = "H2"
|
||||||
|
case underloadPacketMagicHeader = "H3", transportPacketMagicHeader = "H4"
|
||||||
|
case junkPacketCount = "Jc", junkPacketMinSize = "Jmin", junkPacketMaxSize = "Jmax"
|
||||||
|
case initPacketJunkSize = "S1", responsePacketJunkSize = "S2"
|
||||||
|
|
||||||
|
case clientIP = "client_ip" // "10.8.1.16"
|
||||||
|
case clientPrivateKey = "client_priv_key"
|
||||||
|
case clientPublicKey = "client_pub_key"
|
||||||
|
case serverPublicKey = "server_pub_key"
|
||||||
|
case presharedKey = "psk_key"
|
||||||
|
|
||||||
|
case allowedIPs = "allowed_ips"
|
||||||
|
case persistentKeepAlive = "persistent_keep_alive"
|
||||||
|
case hostName
|
||||||
|
case port
|
||||||
|
}
|
||||||
|
|
||||||
|
init(from decoder: Decoder) throws {
|
||||||
|
let container = try decoder.container(keyedBy: CodingKeys.self)
|
||||||
|
self.initPacketMagicHeader = try container.decodeIfPresent(String.self, forKey: .initPacketMagicHeader)
|
||||||
|
self.responsePacketMagicHeader = try container.decodeIfPresent(String.self, forKey: .responsePacketMagicHeader)
|
||||||
|
self.underloadPacketMagicHeader = try container.decodeIfPresent(String.self, forKey: .underloadPacketMagicHeader)
|
||||||
|
self.transportPacketMagicHeader = try container.decodeIfPresent(String.self, forKey: .transportPacketMagicHeader)
|
||||||
|
self.junkPacketCount = try container.decodeIfPresent(String.self, forKey: .junkPacketCount)
|
||||||
|
self.junkPacketMinSize = try container.decodeIfPresent(String.self, forKey: .junkPacketMinSize)
|
||||||
|
self.junkPacketMaxSize = try container.decodeIfPresent(String.self, forKey: .junkPacketMaxSize)
|
||||||
|
self.initPacketJunkSize = try container.decodeIfPresent(String.self, forKey: .initPacketJunkSize)
|
||||||
|
self.responsePacketJunkSize = try container.decodeIfPresent(String.self, forKey: .responsePacketJunkSize)
|
||||||
|
self.clientIP = try container.decode(String.self, forKey: .clientIP)
|
||||||
|
self.clientPrivateKey = try container.decode(String.self, forKey: .clientPrivateKey)
|
||||||
|
self.clientPublicKey = try container.decode(String.self, forKey: .clientPublicKey)
|
||||||
|
self.serverPublicKey = try container.decode(String.self, forKey: .serverPublicKey)
|
||||||
|
self.presharedKey = try container.decode(String.self, forKey: .presharedKey)
|
||||||
|
self.allowedIPs = try container.decodeIfPresent([String].self, forKey: .allowedIPs) ?? ["0.0.0.0/0", "::/0"]
|
||||||
|
self.persistentKeepAlive = try container.decodeIfPresent(String.self, forKey: .persistentKeepAlive) ?? "25"
|
||||||
|
self.hostName = try container.decode(String.self, forKey: .hostName)
|
||||||
|
self.port = try container.decode(Int.self, forKey: .port)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct WGConfig: Decodable {
|
||||||
|
let data: WGConfigData
|
||||||
|
let configVersion: Int
|
||||||
|
let description: String
|
||||||
|
let dns1: String
|
||||||
|
let dns2: String
|
||||||
|
let hostName: String
|
||||||
|
let `protocol`: String
|
||||||
|
let splitTunnelSites: [String]
|
||||||
|
let splitTunnelType: Int
|
||||||
|
|
||||||
|
enum CodingKeys: String, CodingKey {
|
||||||
|
case awgConfigData = "awg_config_data", wgConfigData = "wireguard_config_data"
|
||||||
|
case configData
|
||||||
|
case configVersion = "config_version"
|
||||||
|
case description
|
||||||
|
case dns1
|
||||||
|
case dns2
|
||||||
|
case hostName
|
||||||
|
case `protocol`
|
||||||
|
case splitTunnelSites
|
||||||
|
case splitTunnelType
|
||||||
|
}
|
||||||
|
|
||||||
|
init(from decoder: Decoder) throws {
|
||||||
|
let container = try decoder.container(keyedBy: CodingKeys.self)
|
||||||
|
|
||||||
|
if container.contains(.awgConfigData) {
|
||||||
|
self.data = try container.decode(WGConfigData.self, forKey: .awgConfigData)
|
||||||
|
} else {
|
||||||
|
self.data = try container.decode(WGConfigData.self, forKey: .wgConfigData)
|
||||||
|
}
|
||||||
|
|
||||||
|
self.configVersion = try container.decode(Int.self, forKey: .configVersion)
|
||||||
|
self.description = try container.decode(String.self, forKey: .description)
|
||||||
|
self.dns1 = try container.decode(String.self, forKey: .dns1)
|
||||||
|
self.dns2 = try container.decode(String.self, forKey: .dns2)
|
||||||
|
self.hostName = try container.decode(String.self, forKey: .hostName)
|
||||||
|
self.protocol = try container.decode(String.self, forKey: .protocol)
|
||||||
|
self.splitTunnelSites = try container.decode([String].self, forKey: .splitTunnelSites)
|
||||||
|
self.splitTunnelType = try container.decode(Int.self, forKey: .splitTunnelType)
|
||||||
|
}
|
||||||
|
|
||||||
|
var str: String {
|
||||||
|
"""
|
||||||
|
[Interface]
|
||||||
|
Address = \(data.clientIP)/32
|
||||||
|
DNS = \(dns1), \(dns2)
|
||||||
|
PrivateKey = \(data.clientPrivateKey)
|
||||||
|
\(data.settings)
|
||||||
|
[Peer]
|
||||||
|
PublicKey = \(data.serverPublicKey)
|
||||||
|
PresharedKey = \(data.presharedKey)
|
||||||
|
AllowedIPs = \(data.allowedIPs.joined(separator: ", "))
|
||||||
|
Endpoint = \(data.hostName):\(data.port)
|
||||||
|
PersistentKeepalive = \(data.persistentKeepAlive)
|
||||||
|
"""
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -400,9 +400,10 @@ bool IosController::setupCloak()
|
|||||||
bool IosController::setupWireGuard()
|
bool IosController::setupWireGuard()
|
||||||
{
|
{
|
||||||
QJsonObject config = m_rawConfig[ProtocolProps::key_proto_config_data(amnezia::Proto::WireGuard)].toObject();
|
QJsonObject config = m_rawConfig[ProtocolProps::key_proto_config_data(amnezia::Proto::WireGuard)].toObject();
|
||||||
|
|
||||||
QString wgConfig = config[config_key::config].toString();
|
|
||||||
|
|
||||||
|
QJsonDocument doc(m_rawConfig);
|
||||||
|
QString wgConfig(doc.toJson(QJsonDocument::Compact));
|
||||||
|
|
||||||
return startWireGuard(wgConfig);
|
return startWireGuard(wgConfig);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -410,8 +411,9 @@ bool IosController::setupAwg()
|
|||||||
{
|
{
|
||||||
QJsonObject config = m_rawConfig[ProtocolProps::key_proto_config_data(amnezia::Proto::Awg)].toObject();
|
QJsonObject config = m_rawConfig[ProtocolProps::key_proto_config_data(amnezia::Proto::Awg)].toObject();
|
||||||
|
|
||||||
QString wgConfig = config[config_key::config].toString();
|
QJsonDocument doc(m_rawConfig);
|
||||||
|
QString wgConfig(doc.toJson(QJsonDocument::Compact));
|
||||||
|
|
||||||
return startWireGuard(wgConfig);
|
return startWireGuard(wgConfig);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -20,9 +20,20 @@ WireguardProtocol::WireguardProtocol(const QJsonObject &configuration, QObject *
|
|||||||
});
|
});
|
||||||
connect(m_impl.get(), &ControllerImpl::disconnected, this,
|
connect(m_impl.get(), &ControllerImpl::disconnected, this,
|
||||||
[this]() { emit connectionStateChanged(Vpn::ConnectionState::Disconnected); });
|
[this]() { emit connectionStateChanged(Vpn::ConnectionState::Disconnected); });
|
||||||
|
|
||||||
|
connect(m_impl.get(), &ControllerImpl::statusUpdated, this,
|
||||||
|
&WireguardProtocol::statusUpdated);
|
||||||
|
|
||||||
m_impl->initialize(nullptr, nullptr);
|
m_impl->initialize(nullptr, nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void WireguardProtocol::statusUpdated(const QString& serverIpv4Gateway, const QString& deviceIpv4Address,
|
||||||
|
uint64_t txBytes, uint64_t rxBytes) {
|
||||||
|
setBytesChanged(rxBytes, txBytes);
|
||||||
|
QThread::msleep(1000);
|
||||||
|
m_impl->checkStatus();
|
||||||
|
}
|
||||||
|
|
||||||
WireguardProtocol::~WireguardProtocol()
|
WireguardProtocol::~WireguardProtocol()
|
||||||
{
|
{
|
||||||
WireguardProtocol::stop();
|
WireguardProtocol::stop();
|
||||||
|
|||||||
@@ -21,7 +21,8 @@ public:
|
|||||||
|
|
||||||
ErrorCode start() override;
|
ErrorCode start() override;
|
||||||
void stop() override;
|
void stop() override;
|
||||||
|
void statusUpdated(const QString& serverIpv4Gateway, const QString& deviceIpv4Address,
|
||||||
|
uint64_t txBytes, uint64_t rxBytes);
|
||||||
ErrorCode startMzImpl();
|
ErrorCode startMzImpl();
|
||||||
ErrorCode stopMzImpl();
|
ErrorCode stopMzImpl();
|
||||||
|
|
||||||
|
|||||||
@@ -160,7 +160,6 @@
|
|||||||
<file>ui/qml/Components/SettingsContainersListView.qml</file>
|
<file>ui/qml/Components/SettingsContainersListView.qml</file>
|
||||||
<file>ui/qml/Controls2/TextTypes/ListItemTitleType.qml</file>
|
<file>ui/qml/Controls2/TextTypes/ListItemTitleType.qml</file>
|
||||||
<file>ui/qml/Controls2/DividerType.qml</file>
|
<file>ui/qml/Controls2/DividerType.qml</file>
|
||||||
<file>ui/qml/Controls2/DrawerType.qml</file>
|
|
||||||
<file>ui/qml/Controls2/StackViewType.qml</file>
|
<file>ui/qml/Controls2/StackViewType.qml</file>
|
||||||
<file>ui/qml/Pages2/PageSettings.qml</file>
|
<file>ui/qml/Pages2/PageSettings.qml</file>
|
||||||
<file>images/controls/amnezia.svg</file>
|
<file>images/controls/amnezia.svg</file>
|
||||||
@@ -226,5 +225,8 @@
|
|||||||
<file>images/controls/close.svg</file>
|
<file>images/controls/close.svg</file>
|
||||||
<file>images/controls/search.svg</file>
|
<file>images/controls/search.svg</file>
|
||||||
<file>ui/qml/Controls2/GraphViewType.qml</file>
|
<file>ui/qml/Controls2/GraphViewType.qml</file>
|
||||||
|
<file>ui/qml/Components/HomeSplitTunnelingDrawer.qml</file>
|
||||||
|
<file>images/controls/split-tunneling.svg</file>
|
||||||
|
<file>ui/qml/Controls2/DrawerType2.qml</file>
|
||||||
</qresource>
|
</qresource>
|
||||||
</RCC>
|
</RCC>
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
+1190
-886
File diff suppressed because it is too large
Load Diff
+1047
-792
File diff suppressed because it is too large
Load Diff
+1189
-782
File diff suppressed because it is too large
Load Diff
@@ -70,14 +70,17 @@ QJsonObject ApiController::fillApiPayload(const QString &protocol, const ApiCont
|
|||||||
void ApiController::updateServerConfigFromApi()
|
void ApiController::updateServerConfigFromApi()
|
||||||
{
|
{
|
||||||
QtConcurrent::run([this]() {
|
QtConcurrent::run([this]() {
|
||||||
|
if (m_isConfigUpdateStarted) {
|
||||||
|
emit updateFinished(false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
auto serverConfig = m_serversModel->getDefaultServerConfig();
|
auto serverConfig = m_serversModel->getDefaultServerConfig();
|
||||||
auto containerConfig = serverConfig.value(config_key::containers).toArray();
|
auto containerConfig = serverConfig.value(config_key::containers).toArray();
|
||||||
|
|
||||||
bool isConfigUpdateStarted = false;
|
|
||||||
|
|
||||||
if (serverConfig.value(config_key::configVersion).toInt() && containerConfig.isEmpty()) {
|
if (serverConfig.value(config_key::configVersion).toInt() && containerConfig.isEmpty()) {
|
||||||
emit updateStarted();
|
emit updateStarted();
|
||||||
isConfigUpdateStarted = true;
|
m_isConfigUpdateStarted = true;
|
||||||
|
|
||||||
QNetworkAccessManager manager;
|
QNetworkAccessManager manager;
|
||||||
|
|
||||||
@@ -110,6 +113,12 @@ void ApiController::updateServerConfigFromApi()
|
|||||||
QByteArray ba = QByteArray::fromBase64(data.toUtf8(),
|
QByteArray ba = QByteArray::fromBase64(data.toUtf8(),
|
||||||
QByteArray::Base64UrlEncoding | QByteArray::OmitTrailingEquals);
|
QByteArray::Base64UrlEncoding | QByteArray::OmitTrailingEquals);
|
||||||
|
|
||||||
|
if (ba.isEmpty()) {
|
||||||
|
emit errorOccurred(errorString(ApiConfigDownloadError));
|
||||||
|
m_isConfigUpdateStarted = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
QByteArray ba_uncompressed = qUncompress(ba);
|
QByteArray ba_uncompressed = qUncompress(ba);
|
||||||
if (!ba_uncompressed.isEmpty()) {
|
if (!ba_uncompressed.isEmpty()) {
|
||||||
ba = ba_uncompressed;
|
ba = ba_uncompressed;
|
||||||
@@ -127,17 +136,18 @@ void ApiController::updateServerConfigFromApi()
|
|||||||
|
|
||||||
auto defaultContainer = apiConfig.value(config_key::defaultContainer).toString();
|
auto defaultContainer = apiConfig.value(config_key::defaultContainer).toString();
|
||||||
serverConfig.insert(config_key::defaultContainer, defaultContainer);
|
serverConfig.insert(config_key::defaultContainer, defaultContainer);
|
||||||
m_serversModel->editServer(serverConfig);
|
m_serversModel->editServer(serverConfig, m_serversModel->getDefaultServerIndex());
|
||||||
emit m_serversModel->defaultContainerChanged(ContainerProps::containerFromString(defaultContainer));
|
|
||||||
} else {
|
} else {
|
||||||
qDebug() << reply->error();
|
qDebug() << reply->error();
|
||||||
qDebug() << reply->attribute(QNetworkRequest::HttpStatusCodeAttribute);
|
qDebug() << reply->attribute(QNetworkRequest::HttpStatusCodeAttribute);
|
||||||
emit errorOccurred(errorString(ApiConfigDownloadError));
|
emit errorOccurred(errorString(ApiConfigDownloadError));
|
||||||
|
m_isConfigUpdateStarted = false;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
emit updateFinished(isConfigUpdateStarted);
|
emit updateFinished(m_isConfigUpdateStarted);
|
||||||
|
m_isConfigUpdateStarted = false;
|
||||||
return;
|
return;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -153,5 +163,5 @@ void ApiController::clearApiConfig()
|
|||||||
|
|
||||||
serverConfig.insert(config_key::defaultContainer, ContainerProps::containerToString(DockerContainer::None));
|
serverConfig.insert(config_key::defaultContainer, ContainerProps::containerToString(DockerContainer::None));
|
||||||
|
|
||||||
m_serversModel->editServer(serverConfig);
|
m_serversModel->editServer(serverConfig, m_serversModel->getDefaultServerIndex());
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -39,6 +39,8 @@ private:
|
|||||||
|
|
||||||
QSharedPointer<ServersModel> m_serversModel;
|
QSharedPointer<ServersModel> m_serversModel;
|
||||||
QSharedPointer<ContainersModel> m_containersModel;
|
QSharedPointer<ContainersModel> m_containersModel;
|
||||||
|
|
||||||
|
bool m_isConfigUpdateStarted = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // APICONTROLLER_H
|
#endif // APICONTROLLER_H
|
||||||
|
|||||||
@@ -52,7 +52,7 @@ void ConnectionController::openConnection()
|
|||||||
int serverIndex = m_serversModel->getDefaultServerIndex();
|
int serverIndex = m_serversModel->getDefaultServerIndex();
|
||||||
ServerCredentials credentials = m_serversModel->getServerCredentials(serverIndex);
|
ServerCredentials credentials = m_serversModel->getServerCredentials(serverIndex);
|
||||||
|
|
||||||
DockerContainer container = m_serversModel->getDefaultContainer(serverIndex);
|
DockerContainer container = qvariant_cast<DockerContainer>(m_serversModel->data(serverIndex, ServersModel::Roles::DefaultContainerRole));
|
||||||
const QJsonObject &containerConfig = m_containersModel->getContainerConfig(container);
|
const QJsonObject &containerConfig = m_containersModel->getContainerConfig(container);
|
||||||
|
|
||||||
if (container == DockerContainer::None) {
|
if (container == DockerContainer::None) {
|
||||||
|
|||||||
@@ -45,7 +45,7 @@ void ExportController::generateFullAccessConfig()
|
|||||||
{
|
{
|
||||||
clearPreviousConfig();
|
clearPreviousConfig();
|
||||||
|
|
||||||
int serverIndex = m_serversModel->getCurrentlyProcessedServerIndex();
|
int serverIndex = m_serversModel->getProcessedServerIndex();
|
||||||
QJsonObject config = m_settings->server(serverIndex);
|
QJsonObject config = m_settings->server(serverIndex);
|
||||||
|
|
||||||
QJsonArray containers = config.value(config_key::containers).toArray();
|
QJsonArray containers = config.value(config_key::containers).toArray();
|
||||||
@@ -99,7 +99,7 @@ void ExportController::generateConnectionConfig(const QString &clientName)
|
|||||||
{
|
{
|
||||||
clearPreviousConfig();
|
clearPreviousConfig();
|
||||||
|
|
||||||
int serverIndex = m_serversModel->getCurrentlyProcessedServerIndex();
|
int serverIndex = m_serversModel->getProcessedServerIndex();
|
||||||
ServerCredentials credentials = m_serversModel->getServerCredentials(serverIndex);
|
ServerCredentials credentials = m_serversModel->getServerCredentials(serverIndex);
|
||||||
|
|
||||||
DockerContainer container = static_cast<DockerContainer>(m_containersModel->getCurrentlyProcessedContainerIndex());
|
DockerContainer container = static_cast<DockerContainer>(m_containersModel->getCurrentlyProcessedContainerIndex());
|
||||||
@@ -155,7 +155,7 @@ void ExportController::generateOpenVpnConfig(const QString &clientName)
|
|||||||
{
|
{
|
||||||
clearPreviousConfig();
|
clearPreviousConfig();
|
||||||
|
|
||||||
int serverIndex = m_serversModel->getCurrentlyProcessedServerIndex();
|
int serverIndex = m_serversModel->getProcessedServerIndex();
|
||||||
ServerCredentials credentials = m_serversModel->getServerCredentials(serverIndex);
|
ServerCredentials credentials = m_serversModel->getServerCredentials(serverIndex);
|
||||||
|
|
||||||
DockerContainer container = static_cast<DockerContainer>(m_containersModel->getCurrentlyProcessedContainerIndex());
|
DockerContainer container = static_cast<DockerContainer>(m_containersModel->getCurrentlyProcessedContainerIndex());
|
||||||
@@ -193,7 +193,7 @@ void ExportController::generateWireGuardConfig(const QString &clientName)
|
|||||||
{
|
{
|
||||||
clearPreviousConfig();
|
clearPreviousConfig();
|
||||||
|
|
||||||
int serverIndex = m_serversModel->getCurrentlyProcessedServerIndex();
|
int serverIndex = m_serversModel->getProcessedServerIndex();
|
||||||
ServerCredentials credentials = m_serversModel->getServerCredentials(serverIndex);
|
ServerCredentials credentials = m_serversModel->getServerCredentials(serverIndex);
|
||||||
|
|
||||||
DockerContainer container = static_cast<DockerContainer>(m_containersModel->getCurrentlyProcessedContainerIndex());
|
DockerContainer container = static_cast<DockerContainer>(m_containersModel->getCurrentlyProcessedContainerIndex());
|
||||||
@@ -232,7 +232,7 @@ void ExportController::generateShadowSocksConfig()
|
|||||||
{
|
{
|
||||||
clearPreviousConfig();
|
clearPreviousConfig();
|
||||||
|
|
||||||
int serverIndex = m_serversModel->getCurrentlyProcessedServerIndex();
|
int serverIndex = m_serversModel->getProcessedServerIndex();
|
||||||
ServerCredentials credentials = m_serversModel->getServerCredentials(serverIndex);
|
ServerCredentials credentials = m_serversModel->getServerCredentials(serverIndex);
|
||||||
|
|
||||||
DockerContainer container = static_cast<DockerContainer>(m_containersModel->getCurrentlyProcessedContainerIndex());
|
DockerContainer container = static_cast<DockerContainer>(m_containersModel->getCurrentlyProcessedContainerIndex());
|
||||||
@@ -268,7 +268,7 @@ void ExportController::generateCloakConfig()
|
|||||||
{
|
{
|
||||||
clearPreviousConfig();
|
clearPreviousConfig();
|
||||||
|
|
||||||
int serverIndex = m_serversModel->getCurrentlyProcessedServerIndex();
|
int serverIndex = m_serversModel->getProcessedServerIndex();
|
||||||
ServerCredentials credentials = m_serversModel->getServerCredentials(serverIndex);
|
ServerCredentials credentials = m_serversModel->getServerCredentials(serverIndex);
|
||||||
|
|
||||||
DockerContainer container = static_cast<DockerContainer>(m_containersModel->getCurrentlyProcessedContainerIndex());
|
DockerContainer container = static_cast<DockerContainer>(m_containersModel->getCurrentlyProcessedContainerIndex());
|
||||||
@@ -328,7 +328,7 @@ void ExportController::updateClientManagementModel(const DockerContainer contain
|
|||||||
void ExportController::revokeConfig(const int row, const DockerContainer container, ServerCredentials credentials)
|
void ExportController::revokeConfig(const int row, const DockerContainer container, ServerCredentials credentials)
|
||||||
{
|
{
|
||||||
ErrorCode errorCode = m_clientManagementModel->revokeClient(row, container, credentials,
|
ErrorCode errorCode = m_clientManagementModel->revokeClient(row, container, credentials,
|
||||||
m_serversModel->getCurrentlyProcessedServerIndex());
|
m_serversModel->getProcessedServerIndex());
|
||||||
if (errorCode != ErrorCode::NoError) {
|
if (errorCode != ErrorCode::NoError) {
|
||||||
emit exportErrorOccurred(errorString(errorCode));
|
emit exportErrorOccurred(errorString(errorCode));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -176,7 +176,7 @@ void InstallController::installServer(DockerContainer container, QJsonObject &co
|
|||||||
|
|
||||||
void InstallController::installContainer(DockerContainer container, QJsonObject &config)
|
void InstallController::installContainer(DockerContainer container, QJsonObject &config)
|
||||||
{
|
{
|
||||||
int serverIndex = m_serversModel->getCurrentlyProcessedServerIndex();
|
int serverIndex = m_serversModel->getProcessedServerIndex();
|
||||||
ServerCredentials serverCredentials =
|
ServerCredentials serverCredentials =
|
||||||
qvariant_cast<ServerCredentials>(m_serversModel->data(serverIndex, ServersModel::Roles::CredentialsRole));
|
qvariant_cast<ServerCredentials>(m_serversModel->data(serverIndex, ServersModel::Roles::CredentialsRole));
|
||||||
|
|
||||||
@@ -238,7 +238,7 @@ bool InstallController::isServerAlreadyExists()
|
|||||||
|
|
||||||
void InstallController::scanServerForInstalledContainers()
|
void InstallController::scanServerForInstalledContainers()
|
||||||
{
|
{
|
||||||
int serverIndex = m_serversModel->getCurrentlyProcessedServerIndex();
|
int serverIndex = m_serversModel->getProcessedServerIndex();
|
||||||
ServerCredentials serverCredentials =
|
ServerCredentials serverCredentials =
|
||||||
qvariant_cast<ServerCredentials>(m_serversModel->data(serverIndex, ServersModel::Roles::CredentialsRole));
|
qvariant_cast<ServerCredentials>(m_serversModel->data(serverIndex, ServersModel::Roles::CredentialsRole));
|
||||||
|
|
||||||
@@ -267,7 +267,7 @@ void InstallController::scanServerForInstalledContainers()
|
|||||||
|
|
||||||
void InstallController::updateContainer(QJsonObject config)
|
void InstallController::updateContainer(QJsonObject config)
|
||||||
{
|
{
|
||||||
int serverIndex = m_serversModel->getCurrentlyProcessedServerIndex();
|
int serverIndex = m_serversModel->getProcessedServerIndex();
|
||||||
ServerCredentials serverCredentials =
|
ServerCredentials serverCredentials =
|
||||||
qvariant_cast<ServerCredentials>(m_serversModel->data(serverIndex, ServersModel::Roles::CredentialsRole));
|
qvariant_cast<ServerCredentials>(m_serversModel->data(serverIndex, ServersModel::Roles::CredentialsRole));
|
||||||
|
|
||||||
@@ -283,8 +283,8 @@ void InstallController::updateContainer(QJsonObject config)
|
|||||||
m_serversModel->updateContainerConfig(container, config);
|
m_serversModel->updateContainerConfig(container, config);
|
||||||
m_protocolModel->updateModel(config);
|
m_protocolModel->updateModel(config);
|
||||||
|
|
||||||
if ((serverIndex == m_serversModel->getDefaultServerIndex())
|
auto defaultContainer = qvariant_cast<DockerContainer>(m_serversModel->data(serverIndex, ServersModel::Roles::DefaultContainerRole));
|
||||||
&& (container == m_serversModel->getDefaultContainer(serverIndex))) {
|
if ((serverIndex == m_serversModel->getDefaultServerIndex()) && (container == defaultContainer)) {
|
||||||
emit currentContainerUpdated();
|
emit currentContainerUpdated();
|
||||||
} else {
|
} else {
|
||||||
emit updateContainerFinished(tr("Settings updated successfully"));
|
emit updateContainerFinished(tr("Settings updated successfully"));
|
||||||
@@ -296,27 +296,27 @@ void InstallController::updateContainer(QJsonObject config)
|
|||||||
emit installationErrorOccurred(errorString(errorCode));
|
emit installationErrorOccurred(errorString(errorCode));
|
||||||
}
|
}
|
||||||
|
|
||||||
void InstallController::rebootCurrentlyProcessedServer()
|
void InstallController::rebootProcessedServer()
|
||||||
{
|
{
|
||||||
int serverIndex = m_serversModel->getCurrentlyProcessedServerIndex();
|
int serverIndex = m_serversModel->getProcessedServerIndex();
|
||||||
QString serverName = m_serversModel->data(serverIndex, ServersModel::Roles::NameRole).toString();
|
QString serverName = m_serversModel->data(serverIndex, ServersModel::Roles::NameRole).toString();
|
||||||
|
|
||||||
m_serversModel->rebootServer();
|
m_serversModel->rebootServer();
|
||||||
emit rebootCurrentlyProcessedServerFinished(tr("Server '%1' was rebooted").arg(serverName));
|
emit rebootProcessedServerFinished(tr("Server '%1' was rebooted").arg(serverName));
|
||||||
}
|
}
|
||||||
|
|
||||||
void InstallController::removeCurrentlyProcessedServer()
|
void InstallController::removeProcessedServer()
|
||||||
{
|
{
|
||||||
int serverIndex = m_serversModel->getCurrentlyProcessedServerIndex();
|
int serverIndex = m_serversModel->getProcessedServerIndex();
|
||||||
QString serverName = m_serversModel->data(serverIndex, ServersModel::Roles::NameRole).toString();
|
QString serverName = m_serversModel->data(serverIndex, ServersModel::Roles::NameRole).toString();
|
||||||
|
|
||||||
m_serversModel->removeServer();
|
m_serversModel->removeServer();
|
||||||
emit removeCurrentlyProcessedServerFinished(tr("Server '%1' was removed").arg(serverName));
|
emit removeProcessedServerFinished(tr("Server '%1' was removed").arg(serverName));
|
||||||
}
|
}
|
||||||
|
|
||||||
void InstallController::removeAllContainers()
|
void InstallController::removeAllContainers()
|
||||||
{
|
{
|
||||||
int serverIndex = m_serversModel->getCurrentlyProcessedServerIndex();
|
int serverIndex = m_serversModel->getProcessedServerIndex();
|
||||||
QString serverName = m_serversModel->data(serverIndex, ServersModel::Roles::NameRole).toString();
|
QString serverName = m_serversModel->data(serverIndex, ServersModel::Roles::NameRole).toString();
|
||||||
|
|
||||||
ErrorCode errorCode = m_serversModel->removeAllContainers();
|
ErrorCode errorCode = m_serversModel->removeAllContainers();
|
||||||
@@ -329,7 +329,7 @@ void InstallController::removeAllContainers()
|
|||||||
|
|
||||||
void InstallController::removeCurrentlyProcessedContainer()
|
void InstallController::removeCurrentlyProcessedContainer()
|
||||||
{
|
{
|
||||||
int serverIndex = m_serversModel->getCurrentlyProcessedServerIndex();
|
int serverIndex = m_serversModel->getProcessedServerIndex();
|
||||||
QString serverName = m_serversModel->data(serverIndex, ServersModel::Roles::NameRole).toString();
|
QString serverName = m_serversModel->data(serverIndex, ServersModel::Roles::NameRole).toString();
|
||||||
|
|
||||||
int container = m_containersModel->getCurrentlyProcessedContainerIndex();
|
int container = m_containersModel->getCurrentlyProcessedContainerIndex();
|
||||||
@@ -377,7 +377,7 @@ void InstallController::mountSftpDrive(const QString &port, const QString &passw
|
|||||||
QString mountPath;
|
QString mountPath;
|
||||||
QString cmd;
|
QString cmd;
|
||||||
|
|
||||||
int serverIndex = m_serversModel->getCurrentlyProcessedServerIndex();
|
int serverIndex = m_serversModel->getProcessedServerIndex();
|
||||||
ServerCredentials serverCredentials =
|
ServerCredentials serverCredentials =
|
||||||
qvariant_cast<ServerCredentials>(m_serversModel->data(serverIndex, ServersModel::Roles::CredentialsRole));
|
qvariant_cast<ServerCredentials>(m_serversModel->data(serverIndex, ServersModel::Roles::CredentialsRole));
|
||||||
QString hostname = serverCredentials.hostName;
|
QString hostname = serverCredentials.hostName;
|
||||||
|
|||||||
@@ -30,8 +30,8 @@ public slots:
|
|||||||
|
|
||||||
void updateContainer(QJsonObject config);
|
void updateContainer(QJsonObject config);
|
||||||
|
|
||||||
void removeCurrentlyProcessedServer();
|
void removeProcessedServer();
|
||||||
void rebootCurrentlyProcessedServer();
|
void rebootProcessedServer();
|
||||||
void removeAllContainers();
|
void removeAllContainers();
|
||||||
void removeCurrentlyProcessedContainer();
|
void removeCurrentlyProcessedContainer();
|
||||||
|
|
||||||
@@ -54,8 +54,8 @@ signals:
|
|||||||
|
|
||||||
void scanServerFinished(bool isInstalledContainerFound);
|
void scanServerFinished(bool isInstalledContainerFound);
|
||||||
|
|
||||||
void rebootCurrentlyProcessedServerFinished(const QString &finishedMessage);
|
void rebootProcessedServerFinished(const QString &finishedMessage);
|
||||||
void removeCurrentlyProcessedServerFinished(const QString &finishedMessage);
|
void removeProcessedServerFinished(const QString &finishedMessage);
|
||||||
void removeAllContainersFinished(const QString &finishedMessage);
|
void removeAllContainersFinished(const QString &finishedMessage);
|
||||||
void removeCurrentlyProcessedContainerFinished(const QString &finishedMessage);
|
void removeCurrentlyProcessedContainerFinished(const QString &finishedMessage);
|
||||||
|
|
||||||
|
|||||||
@@ -118,36 +118,6 @@ void PageController::showOnStartup()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void PageController::updateDrawerRootPage(PageLoader::PageEnum page)
|
|
||||||
{
|
|
||||||
m_drawerLayer = 0;
|
|
||||||
m_currentRootPage = page;
|
|
||||||
}
|
|
||||||
|
|
||||||
void PageController::goToDrawerRootPage()
|
|
||||||
{
|
|
||||||
|
|
||||||
m_drawerLayer = 0;
|
|
||||||
|
|
||||||
emit showTopCloseButton(false);
|
|
||||||
emit forceCloseDrawer();
|
|
||||||
}
|
|
||||||
|
|
||||||
void PageController::drawerOpen()
|
|
||||||
{
|
|
||||||
m_drawerLayer = m_drawerLayer + 1;
|
|
||||||
emit showTopCloseButton(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
void PageController::drawerClose()
|
|
||||||
{
|
|
||||||
m_drawerLayer = m_drawerLayer -1;
|
|
||||||
if (m_drawerLayer <= 0) {
|
|
||||||
emit showTopCloseButton(false);
|
|
||||||
m_drawerLayer = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool PageController::isTriggeredByConnectButton()
|
bool PageController::isTriggeredByConnectButton()
|
||||||
{
|
{
|
||||||
return m_isTriggeredByConnectButton;
|
return m_isTriggeredByConnectButton;
|
||||||
|
|||||||
@@ -82,11 +82,6 @@ public slots:
|
|||||||
|
|
||||||
void showOnStartup();
|
void showOnStartup();
|
||||||
|
|
||||||
void updateDrawerRootPage(PageLoader::PageEnum page);
|
|
||||||
void goToDrawerRootPage();
|
|
||||||
void drawerOpen();
|
|
||||||
void drawerClose();
|
|
||||||
|
|
||||||
bool isTriggeredByConnectButton();
|
bool isTriggeredByConnectButton();
|
||||||
void setTriggeredBtConnectButton(bool trigger);
|
void setTriggeredBtConnectButton(bool trigger);
|
||||||
|
|
||||||
@@ -118,17 +113,11 @@ signals:
|
|||||||
void showPassphraseRequestDrawer();
|
void showPassphraseRequestDrawer();
|
||||||
void passphraseRequestDrawerClosed(QString passphrase);
|
void passphraseRequestDrawerClosed(QString passphrase);
|
||||||
|
|
||||||
void showTopCloseButton(bool visible);
|
|
||||||
void forceCloseDrawer();
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QSharedPointer<ServersModel> m_serversModel;
|
QSharedPointer<ServersModel> m_serversModel;
|
||||||
|
|
||||||
std::shared_ptr<Settings> m_settings;
|
std::shared_ptr<Settings> m_settings;
|
||||||
|
|
||||||
PageLoader::PageEnum m_currentRootPage;
|
|
||||||
int m_drawerLayer;
|
|
||||||
|
|
||||||
bool m_isTriggeredByConnectButton;
|
bool m_isTriggeredByConnectButton;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ SettingsController::SettingsController(const QSharedPointer<ServersModel> &serve
|
|||||||
m_sitesModel(sitesModel),
|
m_sitesModel(sitesModel),
|
||||||
m_settings(settings)
|
m_settings(settings)
|
||||||
{
|
{
|
||||||
m_appVersion = QString("%1: %2 (%3)").arg(tr("Software version"), QString(APP_VERSION), __DATE__);
|
m_appVersion = QString("%1 (%2, %3)").arg(QString(APP_VERSION), __DATE__, GIT_COMMIT_HASH);
|
||||||
|
|
||||||
#ifdef Q_OS_ANDROID
|
#ifdef Q_OS_ANDROID
|
||||||
if (!m_settings->isScreenshotsEnabled()) {
|
if (!m_settings->isScreenshotsEnabled()) {
|
||||||
|
|||||||
@@ -45,6 +45,7 @@ QString LanguageModel::getLocalLanguageName(const LanguageSettings::AvailableLan
|
|||||||
case LanguageSettings::AvailableLanguageEnum::Russian: strLanguage = "Русский"; break;
|
case LanguageSettings::AvailableLanguageEnum::Russian: strLanguage = "Русский"; break;
|
||||||
case LanguageSettings::AvailableLanguageEnum::China_cn: strLanguage = "\347\256\200\344\275\223\344\270\255\346\226\207"; break;
|
case LanguageSettings::AvailableLanguageEnum::China_cn: strLanguage = "\347\256\200\344\275\223\344\270\255\346\226\207"; break;
|
||||||
case LanguageSettings::AvailableLanguageEnum::Persian: strLanguage = "فارسی"; break;
|
case LanguageSettings::AvailableLanguageEnum::Persian: strLanguage = "فارسی"; break;
|
||||||
|
case LanguageSettings::AvailableLanguageEnum::Arabic: strLanguage = "العربية"; break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -59,6 +60,7 @@ void LanguageModel::changeLanguage(const LanguageSettings::AvailableLanguageEnum
|
|||||||
case LanguageSettings::AvailableLanguageEnum::Russian: emit updateTranslations(QLocale::Russian); break;
|
case LanguageSettings::AvailableLanguageEnum::Russian: emit updateTranslations(QLocale::Russian); break;
|
||||||
case LanguageSettings::AvailableLanguageEnum::China_cn: emit updateTranslations(QLocale::Chinese); break;
|
case LanguageSettings::AvailableLanguageEnum::China_cn: emit updateTranslations(QLocale::Chinese); break;
|
||||||
case LanguageSettings::AvailableLanguageEnum::Persian: emit updateTranslations(QLocale::Persian); break;
|
case LanguageSettings::AvailableLanguageEnum::Persian: emit updateTranslations(QLocale::Persian); break;
|
||||||
|
case LanguageSettings::AvailableLanguageEnum::Arabic: emit updateTranslations(QLocale::Arabic); break;
|
||||||
default: emit updateTranslations(QLocale::English); break;
|
default: emit updateTranslations(QLocale::English); break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -71,6 +73,7 @@ int LanguageModel::getCurrentLanguageIndex()
|
|||||||
case QLocale::Russian: return static_cast<int>(LanguageSettings::AvailableLanguageEnum::Russian); break;
|
case QLocale::Russian: return static_cast<int>(LanguageSettings::AvailableLanguageEnum::Russian); break;
|
||||||
case QLocale::Chinese: return static_cast<int>(LanguageSettings::AvailableLanguageEnum::China_cn); break;
|
case QLocale::Chinese: return static_cast<int>(LanguageSettings::AvailableLanguageEnum::China_cn); break;
|
||||||
case QLocale::Persian: return static_cast<int>(LanguageSettings::AvailableLanguageEnum::Persian); break;
|
case QLocale::Persian: return static_cast<int>(LanguageSettings::AvailableLanguageEnum::Persian); break;
|
||||||
|
case QLocale::Arabic: return static_cast<int>(LanguageSettings::AvailableLanguageEnum::Arabic); break;
|
||||||
default: return static_cast<int>(LanguageSettings::AvailableLanguageEnum::English); break;
|
default: return static_cast<int>(LanguageSettings::AvailableLanguageEnum::English); break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,7 +13,8 @@ namespace LanguageSettings
|
|||||||
English,
|
English,
|
||||||
Russian,
|
Russian,
|
||||||
China_cn,
|
China_cn,
|
||||||
Persian
|
Persian,
|
||||||
|
Arabic
|
||||||
};
|
};
|
||||||
Q_ENUM_NS(AvailableLanguageEnum)
|
Q_ENUM_NS(AvailableLanguageEnum)
|
||||||
|
|
||||||
|
|||||||
+144
-111
@@ -5,19 +5,13 @@
|
|||||||
ServersModel::ServersModel(std::shared_ptr<Settings> settings, QObject *parent)
|
ServersModel::ServersModel(std::shared_ptr<Settings> settings, QObject *parent)
|
||||||
: m_settings(settings), QAbstractListModel(parent)
|
: m_settings(settings), QAbstractListModel(parent)
|
||||||
{
|
{
|
||||||
m_servers = m_settings->serversArray();
|
|
||||||
m_defaultServerIndex = m_settings->defaultServerIndex();
|
|
||||||
m_currentlyProcessedServerIndex = m_defaultServerIndex;
|
|
||||||
|
|
||||||
connect(this, &ServersModel::defaultServerIndexChanged, this, &ServersModel::defaultServerNameChanged);
|
connect(this, &ServersModel::defaultServerIndexChanged, this, &ServersModel::defaultServerNameChanged);
|
||||||
connect(this, &ServersModel::defaultContainerChanged, this, &ServersModel::defaultServerDescriptionChanged);
|
|
||||||
connect(this, &ServersModel::defaultServerIndexChanged, this, [this](const int serverIndex) {
|
connect(this, &ServersModel::defaultServerIndexChanged, this, [this](const int serverIndex) {
|
||||||
auto defaultContainer = ContainerProps::containerFromString(m_servers.at(serverIndex).toObject().value(config_key::defaultContainer).toString());
|
auto defaultContainer = ContainerProps::containerFromString(m_servers.at(serverIndex).toObject().value(config_key::defaultContainer).toString());
|
||||||
emit ServersModel::defaultContainerChanged(defaultContainer);
|
emit ServersModel::defaultServerDefaultContainerChanged(defaultContainer);
|
||||||
});
|
emit ServersModel::defaultServerNameChanged();
|
||||||
connect(this, &ServersModel::currentlyProcessedServerIndexChanged, this, [this](const int serverIndex) {
|
updateDefaultServerContainersModel();
|
||||||
auto defaultContainer = ContainerProps::containerFromString(m_servers.at(serverIndex).toObject().value(config_key::defaultContainer).toString());
|
|
||||||
emit ServersModel::defaultContainerChanged(defaultContainer);
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -74,16 +68,14 @@ QVariant ServersModel::data(const QModelIndex &index, int role) const
|
|||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
case ServerDescriptionRole: {
|
case ServerDescriptionRole: {
|
||||||
if (configVersion) {
|
auto description = getServerDescription(server, index.row());
|
||||||
return server.value(config_key::description).toString();
|
return configVersion ? description : description + server.value(config_key::hostName).toString();
|
||||||
}
|
|
||||||
return server.value(config_key::hostName).toString();
|
|
||||||
}
|
}
|
||||||
case HostNameRole: return server.value(config_key::hostName).toString();
|
case HostNameRole: return server.value(config_key::hostName).toString();
|
||||||
case CredentialsRole: return QVariant::fromValue(serverCredentials(index.row()));
|
case CredentialsRole: return QVariant::fromValue(serverCredentials(index.row()));
|
||||||
case CredentialsLoginRole: return serverCredentials(index.row()).userName;
|
case CredentialsLoginRole: return serverCredentials(index.row()).userName;
|
||||||
case IsDefaultRole: return index.row() == m_defaultServerIndex;
|
case IsDefaultRole: return index.row() == m_defaultServerIndex;
|
||||||
case IsCurrentlyProcessedRole: return index.row() == m_currentlyProcessedServerIndex;
|
case IsCurrentlyProcessedRole: return index.row() == m_processedServerIndex;
|
||||||
case HasWriteAccessRole: {
|
case HasWriteAccessRole: {
|
||||||
auto credentials = serverCredentials(index.row());
|
auto credentials = serverCredentials(index.row());
|
||||||
return (!credentials.userName.isEmpty() && !credentials.secretData.isEmpty());
|
return (!credentials.userName.isEmpty() && !credentials.secretData.isEmpty());
|
||||||
@@ -95,6 +87,13 @@ QVariant ServersModel::data(const QModelIndex &index, int role) const
|
|||||||
case DefaultContainerRole: {
|
case DefaultContainerRole: {
|
||||||
return ContainerProps::containerFromString(server.value(config_key::defaultContainer).toString());
|
return ContainerProps::containerFromString(server.value(config_key::defaultContainer).toString());
|
||||||
}
|
}
|
||||||
|
case IsServerFromApiRole: {
|
||||||
|
return server.value(config_key::configVersion).toInt();
|
||||||
|
}
|
||||||
|
case HasAmneziaDns: {
|
||||||
|
QString primaryDns = server.value(config_key::dns1).toString();
|
||||||
|
return primaryDns == protocols::dns::amneziaDnsIp;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return QVariant();
|
return QVariant();
|
||||||
@@ -111,8 +110,9 @@ void ServersModel::resetModel()
|
|||||||
beginResetModel();
|
beginResetModel();
|
||||||
m_servers = m_settings->serversArray();
|
m_servers = m_settings->serversArray();
|
||||||
m_defaultServerIndex = m_settings->defaultServerIndex();
|
m_defaultServerIndex = m_settings->defaultServerIndex();
|
||||||
m_currentlyProcessedServerIndex = m_defaultServerIndex;
|
m_processedServerIndex = m_defaultServerIndex;
|
||||||
endResetModel();
|
endResetModel();
|
||||||
|
emit defaultServerIndexChanged(m_defaultServerIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ServersModel::setDefaultServerIndex(const int index)
|
void ServersModel::setDefaultServerIndex(const int index)
|
||||||
@@ -132,12 +132,7 @@ const QString ServersModel::getDefaultServerName()
|
|||||||
return qvariant_cast<QString>(data(m_defaultServerIndex, NameRole));
|
return qvariant_cast<QString>(data(m_defaultServerIndex, NameRole));
|
||||||
}
|
}
|
||||||
|
|
||||||
const QString ServersModel::getDefaultServerHostName()
|
QString ServersModel::getServerDescription(const QJsonObject &server, const int index) const
|
||||||
{
|
|
||||||
return qvariant_cast<QString>(data(m_defaultServerIndex, HostNameRole));
|
|
||||||
}
|
|
||||||
|
|
||||||
QString ServersModel::getDefaultServerDescription(const QJsonObject &server)
|
|
||||||
{
|
{
|
||||||
const auto configVersion = server.value(config_key::configVersion).toInt();
|
const auto configVersion = server.value(config_key::configVersion).toInt();
|
||||||
|
|
||||||
@@ -145,13 +140,12 @@ QString ServersModel::getDefaultServerDescription(const QJsonObject &server)
|
|||||||
|
|
||||||
if (configVersion) {
|
if (configVersion) {
|
||||||
return server.value(config_key::description).toString();
|
return server.value(config_key::description).toString();
|
||||||
} else if (isDefaultServerHasWriteAccess()) {
|
} else if (data(index, HasWriteAccessRole).toBool()) {
|
||||||
if (m_isAmneziaDnsEnabled
|
if (m_isAmneziaDnsEnabled && isAmneziaDnsContainerInstalled(index)) {
|
||||||
&& isAmneziaDnsContainerInstalled(m_defaultServerIndex)) {
|
|
||||||
description += "Amnezia DNS | ";
|
description += "Amnezia DNS | ";
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (isDefaultServerConfigContainsAmneziaDns()) {
|
if (data(index, HasAmneziaDns).toBool()) {
|
||||||
description += "Amnezia DNS | ";
|
description += "Amnezia DNS | ";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -162,7 +156,7 @@ const QString ServersModel::getDefaultServerDescriptionCollapsed()
|
|||||||
{
|
{
|
||||||
const QJsonObject server = m_servers.at(m_defaultServerIndex).toObject();
|
const QJsonObject server = m_servers.at(m_defaultServerIndex).toObject();
|
||||||
const auto configVersion = server.value(config_key::configVersion).toInt();
|
const auto configVersion = server.value(config_key::configVersion).toInt();
|
||||||
auto description = getDefaultServerDescription(server);
|
auto description = getServerDescription(server, m_defaultServerIndex);
|
||||||
if (configVersion) {
|
if (configVersion) {
|
||||||
return description;
|
return description;
|
||||||
}
|
}
|
||||||
@@ -176,7 +170,7 @@ const QString ServersModel::getDefaultServerDescriptionExpanded()
|
|||||||
{
|
{
|
||||||
const QJsonObject server = m_servers.at(m_defaultServerIndex).toObject();
|
const QJsonObject server = m_servers.at(m_defaultServerIndex).toObject();
|
||||||
const auto configVersion = server.value(config_key::configVersion).toInt();
|
const auto configVersion = server.value(config_key::configVersion).toInt();
|
||||||
auto description = getDefaultServerDescription(server);
|
auto description = getServerDescription(server, m_defaultServerIndex);
|
||||||
if (configVersion) {
|
if (configVersion) {
|
||||||
return description;
|
return description;
|
||||||
}
|
}
|
||||||
@@ -199,26 +193,21 @@ bool ServersModel::hasServerWithWriteAccess()
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ServersModel::setCurrentlyProcessedServerIndex(const int index)
|
void ServersModel::setProcessedServerIndex(const int index)
|
||||||
{
|
{
|
||||||
m_currentlyProcessedServerIndex = index;
|
m_processedServerIndex = index;
|
||||||
updateContainersModel();
|
updateContainersModel();
|
||||||
emit currentlyProcessedServerIndexChanged(m_currentlyProcessedServerIndex);
|
emit processedServerIndexChanged(m_processedServerIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
int ServersModel::getCurrentlyProcessedServerIndex()
|
int ServersModel::getProcessedServerIndex()
|
||||||
{
|
{
|
||||||
return m_currentlyProcessedServerIndex;
|
return m_processedServerIndex;
|
||||||
}
|
}
|
||||||
|
|
||||||
QString ServersModel::getCurrentlyProcessedServerHostName()
|
const ServerCredentials ServersModel::getProcessedServerCredentials()
|
||||||
{
|
{
|
||||||
return qvariant_cast<QString>(data(m_currentlyProcessedServerIndex, HostNameRole));
|
return serverCredentials(m_processedServerIndex);
|
||||||
}
|
|
||||||
|
|
||||||
const ServerCredentials ServersModel::getCurrentlyProcessedServerCredentials()
|
|
||||||
{
|
|
||||||
return serverCredentials(m_currentlyProcessedServerIndex);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const ServerCredentials ServersModel::getServerCredentials(const int index)
|
const ServerCredentials ServersModel::getServerCredentials(const int index)
|
||||||
@@ -228,12 +217,17 @@ const ServerCredentials ServersModel::getServerCredentials(const int index)
|
|||||||
|
|
||||||
bool ServersModel::isDefaultServerCurrentlyProcessed()
|
bool ServersModel::isDefaultServerCurrentlyProcessed()
|
||||||
{
|
{
|
||||||
return m_defaultServerIndex == m_currentlyProcessedServerIndex;
|
return m_defaultServerIndex == m_processedServerIndex;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ServersModel::isCurrentlyProcessedServerHasWriteAccess()
|
bool ServersModel::isDefaultServerFromApi()
|
||||||
{
|
{
|
||||||
return qvariant_cast<bool>(data(m_currentlyProcessedServerIndex, HasWriteAccessRole));
|
return qvariant_cast<bool>(data(m_defaultServerIndex, IsServerFromApiRole));
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ServersModel::isProcessedServerHasWriteAccess()
|
||||||
|
{
|
||||||
|
return qvariant_cast<bool>(data(m_processedServerIndex, HasWriteAccessRole));
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ServersModel::isDefaultServerHasWriteAccess()
|
bool ServersModel::isDefaultServerHasWriteAccess()
|
||||||
@@ -249,40 +243,42 @@ void ServersModel::addServer(const QJsonObject &server)
|
|||||||
endResetModel();
|
endResetModel();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ServersModel::editServer(const QJsonObject &server)
|
void ServersModel::editServer(const QJsonObject &server, const int serverIndex)
|
||||||
{
|
{
|
||||||
m_settings->editServer(m_currentlyProcessedServerIndex, server);
|
m_settings->editServer(serverIndex, server);
|
||||||
m_servers.replace(m_currentlyProcessedServerIndex, m_settings->serversArray().at(m_currentlyProcessedServerIndex));
|
m_servers.replace(serverIndex, m_settings->serversArray().at(serverIndex));
|
||||||
emit dataChanged(index(m_currentlyProcessedServerIndex, 0), index(m_currentlyProcessedServerIndex, 0));
|
emit dataChanged(index(serverIndex, 0), index(serverIndex, 0));
|
||||||
|
|
||||||
|
if (serverIndex == m_defaultServerIndex) {
|
||||||
|
updateDefaultServerContainersModel();
|
||||||
|
}
|
||||||
updateContainersModel();
|
updateContainersModel();
|
||||||
|
|
||||||
|
if (serverIndex == m_defaultServerIndex) {
|
||||||
|
auto defaultContainer = qvariant_cast<DockerContainer>(getDefaultServerData("defaultContainer"));
|
||||||
|
emit defaultServerDefaultContainerChanged(defaultContainer);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ServersModel::removeServer()
|
void ServersModel::removeServer()
|
||||||
{
|
{
|
||||||
beginResetModel();
|
beginResetModel();
|
||||||
m_settings->removeServer(m_currentlyProcessedServerIndex);
|
m_settings->removeServer(m_processedServerIndex);
|
||||||
m_servers = m_settings->serversArray();
|
m_servers = m_settings->serversArray();
|
||||||
|
|
||||||
if (m_settings->defaultServerIndex() == m_currentlyProcessedServerIndex) {
|
if (m_settings->defaultServerIndex() == m_processedServerIndex) {
|
||||||
setDefaultServerIndex(0);
|
setDefaultServerIndex(0);
|
||||||
} else if (m_settings->defaultServerIndex() > m_currentlyProcessedServerIndex) {
|
} else if (m_settings->defaultServerIndex() > m_processedServerIndex) {
|
||||||
setDefaultServerIndex(m_settings->defaultServerIndex() - 1);
|
setDefaultServerIndex(m_settings->defaultServerIndex() - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_settings->serversCount() == 0) {
|
if (m_settings->serversCount() == 0) {
|
||||||
setDefaultServerIndex(-1);
|
setDefaultServerIndex(-1);
|
||||||
}
|
}
|
||||||
setCurrentlyProcessedServerIndex(m_defaultServerIndex);
|
setProcessedServerIndex(m_defaultServerIndex);
|
||||||
endResetModel();
|
endResetModel();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ServersModel::isDefaultServerConfigContainsAmneziaDns()
|
|
||||||
{
|
|
||||||
const QJsonObject server = m_servers.at(m_defaultServerIndex).toObject();
|
|
||||||
QString primaryDns = server.value(config_key::dns1).toString();
|
|
||||||
return primaryDns == protocols::dns::amneziaDnsIp;
|
|
||||||
}
|
|
||||||
|
|
||||||
QHash<int, QByteArray> ServersModel::roleNames() const
|
QHash<int, QByteArray> ServersModel::roleNames() const
|
||||||
{
|
{
|
||||||
QHash<int, QByteArray> roles;
|
QHash<int, QByteArray> roles;
|
||||||
@@ -290,6 +286,8 @@ QHash<int, QByteArray> ServersModel::roleNames() const
|
|||||||
roles[NameRole] = "serverName";
|
roles[NameRole] = "serverName";
|
||||||
roles[NameRole] = "name";
|
roles[NameRole] = "name";
|
||||||
roles[ServerDescriptionRole] = "serverDescription";
|
roles[ServerDescriptionRole] = "serverDescription";
|
||||||
|
roles[CollapsedServerDescriptionRole] = "collapsedServerDescription";
|
||||||
|
roles[ExpandedServerDescriptionRole] = "expandedServerDescription";
|
||||||
|
|
||||||
roles[HostNameRole] = "hostName";
|
roles[HostNameRole] = "hostName";
|
||||||
|
|
||||||
@@ -304,6 +302,8 @@ QHash<int, QByteArray> ServersModel::roleNames() const
|
|||||||
roles[ContainsAmneziaDnsRole] = "containsAmneziaDns";
|
roles[ContainsAmneziaDnsRole] = "containsAmneziaDns";
|
||||||
|
|
||||||
roles[DefaultContainerRole] = "defaultContainer";
|
roles[DefaultContainerRole] = "defaultContainer";
|
||||||
|
|
||||||
|
roles[IsServerFromApiRole] = "isServerFromApi";
|
||||||
return roles;
|
return roles;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -322,28 +322,29 @@ ServerCredentials ServersModel::serverCredentials(int index) const
|
|||||||
|
|
||||||
void ServersModel::updateContainersModel()
|
void ServersModel::updateContainersModel()
|
||||||
{
|
{
|
||||||
auto containers = m_servers.at(m_currentlyProcessedServerIndex).toObject().value(config_key::containers).toArray();
|
auto containers = m_servers.at(m_processedServerIndex).toObject().value(config_key::containers).toArray();
|
||||||
emit containersUpdated(containers);
|
emit containersUpdated(containers);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ServersModel::updateDefaultServerContainersModel()
|
||||||
|
{
|
||||||
|
auto containers = m_servers.at(m_defaultServerIndex).toObject().value(config_key::containers).toArray();
|
||||||
|
emit defaultServerContainersUpdated(containers);
|
||||||
|
}
|
||||||
|
|
||||||
QJsonObject ServersModel::getDefaultServerConfig()
|
QJsonObject ServersModel::getDefaultServerConfig()
|
||||||
{
|
{
|
||||||
return m_servers.at(m_defaultServerIndex).toObject();
|
return m_servers.at(m_defaultServerIndex).toObject();
|
||||||
}
|
}
|
||||||
|
|
||||||
QJsonObject ServersModel::getCurrentlyProcessedServerConfig()
|
void ServersModel::reloadDefaultServerContainerConfig()
|
||||||
{
|
{
|
||||||
return m_servers.at(m_currentlyProcessedServerIndex).toObject();
|
QJsonObject server = m_servers.at(m_defaultServerIndex).toObject();
|
||||||
}
|
|
||||||
|
|
||||||
void ServersModel::reloadContainerConfig()
|
|
||||||
{
|
|
||||||
QJsonObject server = m_servers.at(m_currentlyProcessedServerIndex).toObject();
|
|
||||||
auto container = ContainerProps::containerFromString(server.value(config_key::defaultContainer).toString());
|
auto container = ContainerProps::containerFromString(server.value(config_key::defaultContainer).toString());
|
||||||
|
|
||||||
auto containers = server.value(config_key::containers).toArray();
|
auto containers = server.value(config_key::containers).toArray();
|
||||||
|
|
||||||
auto config = m_settings->containerConfig(m_currentlyProcessedServerIndex, container);
|
auto config = m_settings->containerConfig(m_defaultServerIndex, container);
|
||||||
for (auto i = 0; i < containers.size(); i++) {
|
for (auto i = 0; i < containers.size(); i++) {
|
||||||
auto c = ContainerProps::containerFromString(containers.at(i).toObject().value(config_key::container).toString());
|
auto c = ContainerProps::containerFromString(containers.at(i).toObject().value(config_key::container).toString());
|
||||||
if (c == container) {
|
if (c == container) {
|
||||||
@@ -353,13 +354,13 @@ void ServersModel::reloadContainerConfig()
|
|||||||
}
|
}
|
||||||
|
|
||||||
server.insert(config_key::containers, containers);
|
server.insert(config_key::containers, containers);
|
||||||
editServer(server);
|
editServer(server, m_defaultServerIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ServersModel::updateContainerConfig(const int containerIndex, const QJsonObject config)
|
void ServersModel::updateContainerConfig(const int containerIndex, const QJsonObject config)
|
||||||
{
|
{
|
||||||
auto container = static_cast<DockerContainer>(containerIndex);
|
auto container = static_cast<DockerContainer>(containerIndex);
|
||||||
QJsonObject server = m_servers.at(m_currentlyProcessedServerIndex).toObject();
|
QJsonObject server = m_servers.at(m_processedServerIndex).toObject();
|
||||||
|
|
||||||
auto containers = server.value(config_key::containers).toArray();
|
auto containers = server.value(config_key::containers).toArray();
|
||||||
for (auto i = 0; i < containers.size(); i++) {
|
for (auto i = 0; i < containers.size(); i++) {
|
||||||
@@ -377,30 +378,25 @@ void ServersModel::updateContainerConfig(const int containerIndex, const QJsonOb
|
|||||||
server.insert(config_key::defaultContainer, ContainerProps::containerToString(container));
|
server.insert(config_key::defaultContainer, ContainerProps::containerToString(container));
|
||||||
}
|
}
|
||||||
|
|
||||||
editServer(server);
|
editServer(server, m_processedServerIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ServersModel::addContainerConfig(const int containerIndex, const QJsonObject config)
|
void ServersModel::addContainerConfig(const int containerIndex, const QJsonObject config)
|
||||||
{
|
{
|
||||||
auto container = static_cast<DockerContainer>(containerIndex);
|
auto container = static_cast<DockerContainer>(containerIndex);
|
||||||
QJsonObject server = m_servers.at(m_currentlyProcessedServerIndex).toObject();
|
QJsonObject server = m_servers.at(m_processedServerIndex).toObject();
|
||||||
|
|
||||||
auto containers = server.value(config_key::containers).toArray();
|
auto containers = server.value(config_key::containers).toArray();
|
||||||
containers.push_back(config);
|
containers.push_back(config);
|
||||||
|
|
||||||
server.insert(config_key::containers, containers);
|
server.insert(config_key::containers, containers);
|
||||||
|
|
||||||
bool isDefaultContainerChanged = false;
|
|
||||||
auto defaultContainer = server.value(config_key::defaultContainer).toString();
|
auto defaultContainer = server.value(config_key::defaultContainer).toString();
|
||||||
if ((ContainerProps::containerFromString(defaultContainer) == DockerContainer::None || ContainerProps::containerService(container) != ServiceType::Other)) {
|
if ((ContainerProps::containerFromString(defaultContainer) == DockerContainer::None || ContainerProps::containerService(container) != ServiceType::Other)) {
|
||||||
server.insert(config_key::defaultContainer, ContainerProps::containerToString(container));
|
server.insert(config_key::defaultContainer, ContainerProps::containerToString(container));
|
||||||
isDefaultContainerChanged = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
editServer(server);
|
editServer(server, m_processedServerIndex);
|
||||||
if (isDefaultContainerChanged) {
|
|
||||||
emit defaultContainerChanged(container);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ServersModel::setDefaultContainer(const int serverIndex, const int containerIndex)
|
void ServersModel::setDefaultContainer(const int serverIndex, const int containerIndex)
|
||||||
@@ -408,18 +404,12 @@ void ServersModel::setDefaultContainer(const int serverIndex, const int containe
|
|||||||
auto container = static_cast<DockerContainer>(containerIndex);
|
auto container = static_cast<DockerContainer>(containerIndex);
|
||||||
QJsonObject s = m_servers.at(serverIndex).toObject();
|
QJsonObject s = m_servers.at(serverIndex).toObject();
|
||||||
s.insert(config_key::defaultContainer, ContainerProps::containerToString(container));
|
s.insert(config_key::defaultContainer, ContainerProps::containerToString(container));
|
||||||
editServer(s); //check
|
editServer(s, serverIndex); //check
|
||||||
emit defaultContainerChanged(container);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
DockerContainer ServersModel::getDefaultContainer(const int serverIndex)
|
const QString ServersModel::getDefaultServerDefaultContainerName()
|
||||||
{
|
{
|
||||||
return qvariant_cast<DockerContainer>(data(serverIndex, DefaultContainerRole));
|
auto defaultContainer = qvariant_cast<DockerContainer>(getDefaultServerData("defaultContainer"));
|
||||||
}
|
|
||||||
|
|
||||||
const QString ServersModel::getDefaultContainerName()
|
|
||||||
{
|
|
||||||
auto defaultContainer = getDefaultContainer(m_defaultServerIndex);
|
|
||||||
return ContainerProps::containerHumanNames().value(defaultContainer);
|
return ContainerProps::containerHumanNames().value(defaultContainer);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -427,15 +417,14 @@ ErrorCode ServersModel::removeAllContainers()
|
|||||||
{
|
{
|
||||||
ServerController serverController(m_settings);
|
ServerController serverController(m_settings);
|
||||||
ErrorCode errorCode =
|
ErrorCode errorCode =
|
||||||
serverController.removeAllContainers(m_settings->serverCredentials(m_currentlyProcessedServerIndex));
|
serverController.removeAllContainers(m_settings->serverCredentials(m_processedServerIndex));
|
||||||
|
|
||||||
if (errorCode == ErrorCode::NoError) {
|
if (errorCode == ErrorCode::NoError) {
|
||||||
QJsonObject s = m_servers.at(m_currentlyProcessedServerIndex).toObject();
|
QJsonObject s = m_servers.at(m_processedServerIndex).toObject();
|
||||||
s.insert(config_key::containers, {});
|
s.insert(config_key::containers, {});
|
||||||
s.insert(config_key::defaultContainer, ContainerProps::containerToString(DockerContainer::None));
|
s.insert(config_key::defaultContainer, ContainerProps::containerToString(DockerContainer::None));
|
||||||
|
|
||||||
editServer(s);
|
editServer(s, m_processedServerIndex);
|
||||||
emit defaultContainerChanged(DockerContainer::None);
|
|
||||||
}
|
}
|
||||||
return errorCode;
|
return errorCode;
|
||||||
}
|
}
|
||||||
@@ -443,7 +432,7 @@ ErrorCode ServersModel::removeAllContainers()
|
|||||||
ErrorCode ServersModel::rebootServer()
|
ErrorCode ServersModel::rebootServer()
|
||||||
{
|
{
|
||||||
ServerController serverController(m_settings);
|
ServerController serverController(m_settings);
|
||||||
auto credentials = m_settings->serverCredentials(m_currentlyProcessedServerIndex);
|
auto credentials = m_settings->serverCredentials(m_processedServerIndex);
|
||||||
|
|
||||||
ErrorCode errorCode = serverController.rebootServer(credentials);
|
ErrorCode errorCode = serverController.rebootServer(credentials);
|
||||||
return errorCode;
|
return errorCode;
|
||||||
@@ -452,13 +441,13 @@ ErrorCode ServersModel::rebootServer()
|
|||||||
ErrorCode ServersModel::removeContainer(const int containerIndex)
|
ErrorCode ServersModel::removeContainer(const int containerIndex)
|
||||||
{
|
{
|
||||||
ServerController serverController(m_settings);
|
ServerController serverController(m_settings);
|
||||||
auto credentials = m_settings->serverCredentials(m_currentlyProcessedServerIndex);
|
auto credentials = m_settings->serverCredentials(m_processedServerIndex);
|
||||||
auto dockerContainer = static_cast<DockerContainer>(containerIndex);
|
auto dockerContainer = static_cast<DockerContainer>(containerIndex);
|
||||||
|
|
||||||
ErrorCode errorCode = serverController.removeContainer(credentials, dockerContainer);
|
ErrorCode errorCode = serverController.removeContainer(credentials, dockerContainer);
|
||||||
|
|
||||||
if (errorCode == ErrorCode::NoError) {
|
if (errorCode == ErrorCode::NoError) {
|
||||||
QJsonObject server = m_servers.at(m_currentlyProcessedServerIndex).toObject();
|
QJsonObject server = m_servers.at(m_processedServerIndex).toObject();
|
||||||
|
|
||||||
auto containers = server.value(config_key::containers).toArray();
|
auto containers = server.value(config_key::containers).toArray();
|
||||||
for (auto it = containers.begin(); it != containers.end(); it++) {
|
for (auto it = containers.begin(); it != containers.end(); it++) {
|
||||||
@@ -480,32 +469,37 @@ ErrorCode ServersModel::removeContainer(const int containerIndex)
|
|||||||
server.insert(config_key::defaultContainer, ContainerProps::containerToString(defaultContainer));
|
server.insert(config_key::defaultContainer, ContainerProps::containerToString(defaultContainer));
|
||||||
}
|
}
|
||||||
|
|
||||||
editServer(server);
|
editServer(server, m_processedServerIndex);
|
||||||
emit defaultContainerChanged(defaultContainer);
|
|
||||||
}
|
}
|
||||||
return errorCode;
|
return errorCode;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ServersModel::clearCachedProfiles()
|
void ServersModel::clearCachedProfiles()
|
||||||
{
|
{
|
||||||
const auto &containers = m_settings->containers(m_currentlyProcessedServerIndex);
|
const auto &containers = m_settings->containers(m_processedServerIndex);
|
||||||
for (DockerContainer container : containers.keys()) {
|
for (DockerContainer container : containers.keys()) {
|
||||||
m_settings->clearLastConnectionConfig(m_currentlyProcessedServerIndex, container);
|
m_settings->clearLastConnectionConfig(m_processedServerIndex, container);
|
||||||
}
|
}
|
||||||
|
|
||||||
m_servers.replace(m_currentlyProcessedServerIndex, m_settings->server(m_currentlyProcessedServerIndex));
|
m_servers.replace(m_processedServerIndex, m_settings->server(m_processedServerIndex));
|
||||||
|
if (m_processedServerIndex == m_defaultServerIndex) {
|
||||||
|
updateDefaultServerContainersModel();
|
||||||
|
}
|
||||||
updateContainersModel();
|
updateContainersModel();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ServersModel::clearCachedProfile(const DockerContainer container)
|
void ServersModel::clearCachedProfile(const DockerContainer container)
|
||||||
{
|
{
|
||||||
m_settings->clearLastConnectionConfig(m_currentlyProcessedServerIndex, container);
|
m_settings->clearLastConnectionConfig(m_processedServerIndex, container);
|
||||||
|
|
||||||
m_servers.replace(m_currentlyProcessedServerIndex, m_settings->server(m_currentlyProcessedServerIndex));
|
m_servers.replace(m_processedServerIndex, m_settings->server(m_processedServerIndex));
|
||||||
|
if (m_processedServerIndex == m_defaultServerIndex) {
|
||||||
|
updateDefaultServerContainersModel();
|
||||||
|
}
|
||||||
updateContainersModel();
|
updateContainersModel();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ServersModel::isAmneziaDnsContainerInstalled(const int serverIndex)
|
bool ServersModel::isAmneziaDnsContainerInstalled(const int serverIndex) const
|
||||||
{
|
{
|
||||||
QJsonObject server = m_servers.at(serverIndex).toObject();
|
QJsonObject server = m_servers.at(serverIndex).toObject();
|
||||||
auto containers = server.value(config_key::containers).toArray();
|
auto containers = server.value(config_key::containers).toArray();
|
||||||
@@ -544,16 +538,6 @@ void ServersModel::toggleAmneziaDns(bool enabled)
|
|||||||
emit defaultServerDescriptionChanged();
|
emit defaultServerDescriptionChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ServersModel::isDefaultServerFromApi()
|
|
||||||
{
|
|
||||||
return m_settings->server(m_defaultServerIndex).value(config_key::configVersion).toInt();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ServersModel::isCurrentlyProcessedServerFromApi()
|
|
||||||
{
|
|
||||||
return m_settings->server(m_currentlyProcessedServerIndex).value(config_key::configVersion).toInt();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ServersModel::isServerFromApiAlreadyExists(const quint16 crc)
|
bool ServersModel::isServerFromApiAlreadyExists(const quint16 crc)
|
||||||
{
|
{
|
||||||
for (const auto &server : qAsConst(m_servers)) {
|
for (const auto &server : qAsConst(m_servers)) {
|
||||||
@@ -564,3 +548,52 @@ bool ServersModel::isServerFromApiAlreadyExists(const quint16 crc)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QVariant ServersModel::getDefaultServerData(const QString roleString)
|
||||||
|
{
|
||||||
|
auto roles = roleNames();
|
||||||
|
for (auto it = roles.begin(); it != roles.end(); it++) {
|
||||||
|
if (QString(it.value()) == roleString) {
|
||||||
|
return data(m_defaultServerIndex, it.key());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
void ServersModel::setDefaultServerData(const QString roleString, const QVariant &value)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
QVariant ServersModel::getProcessedServerData(const QString roleString)
|
||||||
|
{
|
||||||
|
auto roles = roleNames();
|
||||||
|
for (auto it = roles.begin(); it != roles.end(); it++) {
|
||||||
|
if (QString(it.value()) == roleString) {
|
||||||
|
return data(m_processedServerIndex, it.key());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
void ServersModel::setProcessedServerData(const QString roleString, const QVariant &value)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ServersModel::isDefaultServerDefaultContainerHasSplitTunneling()
|
||||||
|
{
|
||||||
|
auto server = m_servers.at(m_defaultServerIndex).toObject();
|
||||||
|
auto defaultContainer = ContainerProps::containerFromString(server.value(config_key::defaultContainer).toString());
|
||||||
|
auto containerConfig = server.value(config_key::containers).toArray().at(defaultContainer).toObject();
|
||||||
|
auto protocolConfig = containerConfig.value(ContainerProps::containerTypeToString(defaultContainer)).toObject();
|
||||||
|
|
||||||
|
if (defaultContainer == DockerContainer::Awg || defaultContainer == DockerContainer::WireGuard) {
|
||||||
|
return !(protocolConfig.value(config_key::last_config).toString().contains("AllowedIPs = 0.0.0.0/0, ::/0"));
|
||||||
|
} else if (defaultContainer == DockerContainer::Cloak || defaultContainer == DockerContainer::OpenVpn || defaultContainer == DockerContainer::ShadowSocks) {
|
||||||
|
return !(protocolConfig.value(config_key::last_config).toString().contains("redirect-gateway"));
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|||||||
@@ -12,7 +12,8 @@ public:
|
|||||||
enum Roles {
|
enum Roles {
|
||||||
NameRole = Qt::UserRole + 1,
|
NameRole = Qt::UserRole + 1,
|
||||||
ServerDescriptionRole,
|
ServerDescriptionRole,
|
||||||
|
CollapsedServerDescriptionRole,
|
||||||
|
ExpandedServerDescriptionRole,
|
||||||
HostNameRole,
|
HostNameRole,
|
||||||
|
|
||||||
CredentialsRole,
|
CredentialsRole,
|
||||||
@@ -25,7 +26,11 @@ public:
|
|||||||
|
|
||||||
ContainsAmneziaDnsRole,
|
ContainsAmneziaDnsRole,
|
||||||
|
|
||||||
DefaultContainerRole
|
DefaultContainerRole,
|
||||||
|
|
||||||
|
IsServerFromApiRole,
|
||||||
|
|
||||||
|
HasAmneziaDns
|
||||||
};
|
};
|
||||||
|
|
||||||
ServersModel(std::shared_ptr<Settings> settings, QObject *parent = nullptr);
|
ServersModel(std::shared_ptr<Settings> settings, QObject *parent = nullptr);
|
||||||
@@ -40,47 +45,43 @@ public:
|
|||||||
|
|
||||||
Q_PROPERTY(int defaultIndex READ getDefaultServerIndex WRITE setDefaultServerIndex NOTIFY defaultServerIndexChanged)
|
Q_PROPERTY(int defaultIndex READ getDefaultServerIndex WRITE setDefaultServerIndex NOTIFY defaultServerIndexChanged)
|
||||||
Q_PROPERTY(QString defaultServerName READ getDefaultServerName NOTIFY defaultServerNameChanged)
|
Q_PROPERTY(QString defaultServerName READ getDefaultServerName NOTIFY defaultServerNameChanged)
|
||||||
Q_PROPERTY(QString defaultServerHostName READ getDefaultServerHostName NOTIFY defaultServerIndexChanged)
|
Q_PROPERTY(QString defaultServerDefaultContainerName READ getDefaultServerDefaultContainerName NOTIFY defaultServerDefaultContainerChanged)
|
||||||
Q_PROPERTY(QString defaultContainerName READ getDefaultContainerName NOTIFY defaultContainerChanged)
|
Q_PROPERTY(QString defaultServerDescriptionCollapsed READ getDefaultServerDescriptionCollapsed NOTIFY defaultServerDefaultContainerChanged)
|
||||||
Q_PROPERTY(QString defaultServerDescriptionCollapsed READ getDefaultServerDescriptionCollapsed NOTIFY defaultServerDescriptionChanged)
|
Q_PROPERTY(QString defaultServerDescriptionExpanded READ getDefaultServerDescriptionExpanded NOTIFY defaultServerDefaultContainerChanged)
|
||||||
Q_PROPERTY(QString defaultServerDescriptionExpanded READ getDefaultServerDescriptionExpanded NOTIFY defaultServerDescriptionChanged)
|
Q_PROPERTY(bool isDefaultServerDefaultContainerHasSplitTunneling READ isDefaultServerDefaultContainerHasSplitTunneling NOTIFY defaultServerDefaultContainerChanged)
|
||||||
|
Q_PROPERTY(bool isDefaultServerFromApi READ isDefaultServerFromApi NOTIFY defaultServerIndexChanged)
|
||||||
|
|
||||||
Q_PROPERTY(int currentlyProcessedIndex READ getCurrentlyProcessedServerIndex WRITE setCurrentlyProcessedServerIndex
|
Q_PROPERTY(int processedIndex READ getProcessedServerIndex WRITE setProcessedServerIndex NOTIFY processedServerIndexChanged)
|
||||||
NOTIFY currentlyProcessedServerIndexChanged)
|
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
void setDefaultServerIndex(const int index);
|
void setDefaultServerIndex(const int index);
|
||||||
const int getDefaultServerIndex();
|
const int getDefaultServerIndex();
|
||||||
const QString getDefaultServerName();
|
const QString getDefaultServerName();
|
||||||
const QString getDefaultServerHostName();
|
|
||||||
const QString getDefaultServerDescriptionCollapsed();
|
const QString getDefaultServerDescriptionCollapsed();
|
||||||
const QString getDefaultServerDescriptionExpanded();
|
const QString getDefaultServerDescriptionExpanded();
|
||||||
|
const QString getDefaultServerDefaultContainerName();
|
||||||
bool isDefaultServerCurrentlyProcessed();
|
bool isDefaultServerCurrentlyProcessed();
|
||||||
|
bool isDefaultServerFromApi();
|
||||||
|
|
||||||
bool isCurrentlyProcessedServerHasWriteAccess();
|
bool isProcessedServerHasWriteAccess();
|
||||||
bool isDefaultServerHasWriteAccess();
|
bool isDefaultServerHasWriteAccess();
|
||||||
bool hasServerWithWriteAccess();
|
bool hasServerWithWriteAccess();
|
||||||
|
|
||||||
const int getServersCount();
|
const int getServersCount();
|
||||||
|
|
||||||
void setCurrentlyProcessedServerIndex(const int index);
|
void setProcessedServerIndex(const int index);
|
||||||
int getCurrentlyProcessedServerIndex();
|
int getProcessedServerIndex();
|
||||||
|
|
||||||
QString getCurrentlyProcessedServerHostName();
|
const ServerCredentials getProcessedServerCredentials();
|
||||||
const ServerCredentials getCurrentlyProcessedServerCredentials();
|
|
||||||
const ServerCredentials getServerCredentials(const int index);
|
const ServerCredentials getServerCredentials(const int index);
|
||||||
|
|
||||||
void addServer(const QJsonObject &server);
|
void addServer(const QJsonObject &server);
|
||||||
void editServer(const QJsonObject &server);
|
void editServer(const QJsonObject &server, const int serverIndex);
|
||||||
void removeServer();
|
void removeServer();
|
||||||
|
|
||||||
bool isDefaultServerConfigContainsAmneziaDns();
|
|
||||||
bool isAmneziaDnsContainerInstalled(const int serverIndex);
|
|
||||||
|
|
||||||
QJsonObject getDefaultServerConfig();
|
QJsonObject getDefaultServerConfig();
|
||||||
QJsonObject getCurrentlyProcessedServerConfig();
|
|
||||||
|
|
||||||
void reloadContainerConfig();
|
void reloadDefaultServerContainerConfig();
|
||||||
void updateContainerConfig(const int containerIndex, const QJsonObject config);
|
void updateContainerConfig(const int containerIndex, const QJsonObject config);
|
||||||
void addContainerConfig(const int containerIndex, const QJsonObject config);
|
void addContainerConfig(const int containerIndex, const QJsonObject config);
|
||||||
|
|
||||||
@@ -92,42 +93,49 @@ public slots:
|
|||||||
ErrorCode rebootServer();
|
ErrorCode rebootServer();
|
||||||
|
|
||||||
void setDefaultContainer(const int serverIndex, const int containerIndex);
|
void setDefaultContainer(const int serverIndex, const int containerIndex);
|
||||||
DockerContainer getDefaultContainer(const int serverIndex);
|
|
||||||
const QString getDefaultContainerName();
|
|
||||||
|
|
||||||
QStringList getAllInstalledServicesName(const int serverIndex);
|
QStringList getAllInstalledServicesName(const int serverIndex);
|
||||||
|
|
||||||
void toggleAmneziaDns(bool enabled);
|
void toggleAmneziaDns(bool enabled);
|
||||||
|
|
||||||
bool isDefaultServerFromApi();
|
|
||||||
bool isCurrentlyProcessedServerFromApi();
|
|
||||||
|
|
||||||
bool isServerFromApiAlreadyExists(const quint16 crc);
|
bool isServerFromApiAlreadyExists(const quint16 crc);
|
||||||
|
|
||||||
|
QVariant getDefaultServerData(const QString roleString);
|
||||||
|
void setDefaultServerData(const QString roleString, const QVariant &value);
|
||||||
|
|
||||||
|
QVariant getProcessedServerData(const QString roleString);
|
||||||
|
void setProcessedServerData(const QString roleString, const QVariant &value);
|
||||||
|
|
||||||
|
bool isDefaultServerDefaultContainerHasSplitTunneling();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
QHash<int, QByteArray> roleNames() const override;
|
QHash<int, QByteArray> roleNames() const override;
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void currentlyProcessedServerIndexChanged(const int index);
|
void processedServerIndexChanged(const int index);
|
||||||
void defaultServerIndexChanged(const int index);
|
void defaultServerIndexChanged(const int index);
|
||||||
void defaultServerNameChanged();
|
void defaultServerNameChanged();
|
||||||
void defaultServerDescriptionChanged();
|
void defaultServerDescriptionChanged();
|
||||||
|
|
||||||
void containersUpdated(const QJsonArray &containers);
|
void containersUpdated(const QJsonArray &containers);
|
||||||
void defaultContainerChanged(const int containerIndex);
|
void defaultServerContainersUpdated(const QJsonArray &containers);
|
||||||
|
void defaultServerDefaultContainerChanged(const int containerIndex);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
ServerCredentials serverCredentials(int index) const;
|
ServerCredentials serverCredentials(int index) const;
|
||||||
void updateContainersModel();
|
void updateContainersModel();
|
||||||
|
void updateDefaultServerContainersModel();
|
||||||
|
|
||||||
QString getDefaultServerDescription(const QJsonObject &server);
|
QString getServerDescription(const QJsonObject &server, const int index) const;
|
||||||
|
|
||||||
|
bool isAmneziaDnsContainerInstalled(const int serverIndex) const;
|
||||||
|
|
||||||
QJsonArray m_servers;
|
QJsonArray m_servers;
|
||||||
|
|
||||||
std::shared_ptr<Settings> m_settings;
|
std::shared_ptr<Settings> m_settings;
|
||||||
|
|
||||||
int m_defaultServerIndex;
|
int m_defaultServerIndex;
|
||||||
int m_currentlyProcessedServerIndex;
|
int m_processedServerIndex;
|
||||||
|
|
||||||
bool m_isAmneziaDnsEnabled = m_settings->useAmneziaDns();
|
bool m_isAmneziaDnsEnabled = m_settings->useAmneziaDns();
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -113,6 +113,7 @@ void SitesModel::toggleSplitTunneling(bool enabled)
|
|||||||
m_settings->setRouteMode(Settings::RouteMode::VpnAllSites);
|
m_settings->setRouteMode(Settings::RouteMode::VpnAllSites);
|
||||||
}
|
}
|
||||||
m_isSplitTunnelingEnabled = enabled;
|
m_isSplitTunnelingEnabled = enabled;
|
||||||
|
emit splitTunnelingToggled();
|
||||||
}
|
}
|
||||||
|
|
||||||
QVector<QPair<QString, QString> > SitesModel::getCurrentSites()
|
QVector<QPair<QString, QString> > SitesModel::getCurrentSites()
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ public:
|
|||||||
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
|
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
|
||||||
|
|
||||||
Q_PROPERTY(int routeMode READ getRouteMode WRITE setRouteMode NOTIFY routeModeChanged)
|
Q_PROPERTY(int routeMode READ getRouteMode WRITE setRouteMode NOTIFY routeModeChanged)
|
||||||
|
Q_PROPERTY(bool isTunnelingEnabled READ isSplitTunnelingEnabled NOTIFY splitTunnelingToggled)
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
bool addSite(const QString &hostname, const QString &ip);
|
bool addSite(const QString &hostname, const QString &ip);
|
||||||
@@ -38,6 +39,7 @@ public slots:
|
|||||||
|
|
||||||
signals:
|
signals:
|
||||||
void routeModeChanged();
|
void routeModeChanged();
|
||||||
|
void splitTunnelingToggled();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
QHash<int, QByteArray> roleNames() const override;
|
QHash<int, QByteArray> roleNames() const override;
|
||||||
|
|||||||
@@ -138,9 +138,7 @@ Button {
|
|||||||
}
|
}
|
||||||
|
|
||||||
onClicked: {
|
onClicked: {
|
||||||
if (!ConnectionController.isConnectionInProgress) {
|
ServersModel.setProcessedServerIndex(ServersModel.defaultIndex)
|
||||||
ServersModel.setCurrentlyProcessedServerIndex(ServersModel.defaultIndex)
|
ApiController.updateServerConfigFromApi()
|
||||||
ApiController.updateServerConfigFromApi()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,18 +8,24 @@ import "../Controls2"
|
|||||||
import "../Controls2/TextTypes"
|
import "../Controls2/TextTypes"
|
||||||
import "../Config"
|
import "../Config"
|
||||||
|
|
||||||
DrawerType {
|
DrawerType2 {
|
||||||
id: root
|
id: root
|
||||||
|
|
||||||
width: parent.width
|
width: parent.width
|
||||||
height: parent.height * 0.4375
|
height: parent.height
|
||||||
|
|
||||||
|
expandedContent: ColumnLayout {
|
||||||
|
id: content
|
||||||
|
|
||||||
ColumnLayout {
|
|
||||||
anchors.top: parent.top
|
anchors.top: parent.top
|
||||||
anchors.left: parent.left
|
anchors.left: parent.left
|
||||||
anchors.right: parent.right
|
anchors.right: parent.right
|
||||||
spacing: 0
|
spacing: 0
|
||||||
|
|
||||||
|
Component.onCompleted: {
|
||||||
|
root.expandedHeight = content.implicitHeight + 32
|
||||||
|
}
|
||||||
|
|
||||||
Header2Type {
|
Header2Type {
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
Layout.topMargin: 24
|
Layout.topMargin: 24
|
||||||
@@ -40,7 +46,7 @@ DrawerType {
|
|||||||
|
|
||||||
clickedFunction: function() {
|
clickedFunction: function() {
|
||||||
PageController.goToPage(PageEnum.PageSetupWizardCredentials)
|
PageController.goToPage(PageEnum.PageSetupWizardCredentials)
|
||||||
root.visible = false
|
root.close()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -54,7 +60,7 @@ DrawerType {
|
|||||||
|
|
||||||
clickedFunction: function() {
|
clickedFunction: function() {
|
||||||
PageController.goToPage(PageEnum.PageSetupWizardConfigSource)
|
PageController.goToPage(PageEnum.PageSetupWizardConfigSource)
|
||||||
root.visible = false
|
root.close()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ ListView {
|
|||||||
id: menuContent
|
id: menuContent
|
||||||
|
|
||||||
property var rootWidth
|
property var rootWidth
|
||||||
|
property var selectedText
|
||||||
|
|
||||||
width: rootWidth
|
width: rootWidth
|
||||||
height: menuContent.contentItem.height
|
height: menuContent.contentItem.height
|
||||||
@@ -51,7 +52,7 @@ ListView {
|
|||||||
showImage: !isInstalled
|
showImage: !isInstalled
|
||||||
|
|
||||||
checkable: isInstalled && !ConnectionController.isConnected && isSupported
|
checkable: isInstalled && !ConnectionController.isConnected && isSupported
|
||||||
checked: proxyContainersModel.mapToSource(index) === ServersModel.getDefaultContainer(ServersModel.defaultIndex)
|
checked: proxyDefaultServerContainersModel.mapToSource(index) === ServersModel.getDefaultServerData("defaultContainer")
|
||||||
|
|
||||||
onClicked: {
|
onClicked: {
|
||||||
if (ConnectionController.isConnected && isInstalled) {
|
if (ConnectionController.isConnected && isInstalled) {
|
||||||
@@ -60,18 +61,18 @@ ListView {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (checked) {
|
if (checked) {
|
||||||
containersDropDown.menuVisible = false
|
containersDropDown.close()
|
||||||
ServersModel.setDefaultContainer(ServersModel.defaultIndex, proxyContainersModel.mapToSource(index))
|
ServersModel.setDefaultContainer(ServersModel.defaultIndex, proxyDefaultServerContainersModel.mapToSource(index))
|
||||||
} else {
|
} else {
|
||||||
if (!isSupported && isInstalled) {
|
if (!isSupported && isInstalled) {
|
||||||
PageController.showErrorMessage(qsTr("The selected protocol is not supported on the current platform"))
|
PageController.showErrorMessage(qsTr("The selected protocol is not supported on the current platform"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
ContainersModel.setCurrentlyProcessedContainerIndex(proxyContainersModel.mapToSource(index))
|
ContainersModel.setCurrentlyProcessedContainerIndex(proxyDefaultServerContainersModel.mapToSource(index))
|
||||||
InstallController.setShouldCreateServer(false)
|
InstallController.setShouldCreateServer(false)
|
||||||
PageController.goToPage(PageEnum.PageSetupWizardProtocolSettings)
|
PageController.goToPage(PageEnum.PageSetupWizardProtocolSettings)
|
||||||
containersDropDown.menuVisible = false
|
containersDropDown.close()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,92 @@
|
|||||||
|
import QtQuick
|
||||||
|
import QtQuick.Controls
|
||||||
|
import QtQuick.Layouts
|
||||||
|
|
||||||
|
import PageEnum 1.0
|
||||||
|
|
||||||
|
import "../Controls2"
|
||||||
|
import "../Controls2/TextTypes"
|
||||||
|
import "../Config"
|
||||||
|
|
||||||
|
DrawerType2 {
|
||||||
|
id: root
|
||||||
|
|
||||||
|
anchors.fill: parent
|
||||||
|
expandedHeight: parent.height * 0.7
|
||||||
|
|
||||||
|
expandedContent: ColumnLayout {
|
||||||
|
id: content
|
||||||
|
|
||||||
|
anchors.top: parent.top
|
||||||
|
anchors.left: parent.left
|
||||||
|
anchors.right: parent.right
|
||||||
|
spacing: 0
|
||||||
|
|
||||||
|
Header2Type {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
Layout.topMargin: 24
|
||||||
|
Layout.rightMargin: 16
|
||||||
|
Layout.leftMargin: 16
|
||||||
|
Layout.bottomMargin: 16
|
||||||
|
|
||||||
|
headerText: qsTr("Split tunneling")
|
||||||
|
descriptionText: qsTr("Allows you to connect to some sites or applications through a VPN connection and bypass others")
|
||||||
|
}
|
||||||
|
|
||||||
|
LabelWithButtonType {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
Layout.topMargin: 16
|
||||||
|
|
||||||
|
visible: ServersModel.isDefaultServerDefaultContainerHasSplitTunneling && ServersModel.getDefaultServerData("isServerFromApi")
|
||||||
|
|
||||||
|
text: qsTr("Split tunneling on the server")
|
||||||
|
descriptionText: qsTr("Enabled \nCan't be disabled for current server")
|
||||||
|
rightImageSource: "qrc:/images/controls/chevron-right.svg"
|
||||||
|
|
||||||
|
clickedFunction: function() {
|
||||||
|
// PageController.goToPage(PageEnum.PageSettingsSplitTunneling)
|
||||||
|
// root.close()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
DividerType {
|
||||||
|
visible: ServersModel.isDefaultServerDefaultContainerHasSplitTunneling && ServersModel.getDefaultServerData("isServerFromApi")
|
||||||
|
}
|
||||||
|
|
||||||
|
LabelWithButtonType {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
Layout.topMargin: 16
|
||||||
|
|
||||||
|
enabled: ! ServersModel.isDefaultServerDefaultContainerHasSplitTunneling || !ServersModel.getDefaultServerData("isServerFromApi")
|
||||||
|
|
||||||
|
text: qsTr("Site-based split tunneling")
|
||||||
|
descriptionText: enabled && SitesModel.isTunnelingEnabled ? qsTr("Enabled") : qsTr("Disabled")
|
||||||
|
rightImageSource: "qrc:/images/controls/chevron-right.svg"
|
||||||
|
|
||||||
|
clickedFunction: function() {
|
||||||
|
PageController.goToPage(PageEnum.PageSettingsSplitTunneling)
|
||||||
|
root.close()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
DividerType {
|
||||||
|
}
|
||||||
|
|
||||||
|
LabelWithButtonType {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
visible: false
|
||||||
|
|
||||||
|
text: qsTr("App-based split tunneling")
|
||||||
|
rightImageSource: "qrc:/images/controls/chevron-right.svg"
|
||||||
|
|
||||||
|
clickedFunction: function() {
|
||||||
|
// PageController.goToPage(PageEnum.PageSetupWizardConfigSource)
|
||||||
|
root.close()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
DividerType {
|
||||||
|
visible: false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -5,7 +5,7 @@ import QtQuick.Layouts
|
|||||||
import "../Controls2"
|
import "../Controls2"
|
||||||
import "../Controls2/TextTypes"
|
import "../Controls2/TextTypes"
|
||||||
|
|
||||||
DrawerType {
|
DrawerType2 {
|
||||||
id: root
|
id: root
|
||||||
|
|
||||||
property string headerText
|
property string headerText
|
||||||
@@ -16,23 +16,24 @@ DrawerType {
|
|||||||
property var yesButtonFunction
|
property var yesButtonFunction
|
||||||
property var noButtonFunction
|
property var noButtonFunction
|
||||||
|
|
||||||
width: parent.width
|
expandedContent: ColumnLayout {
|
||||||
height: content.implicitHeight + 32
|
|
||||||
|
|
||||||
ColumnLayout {
|
|
||||||
id: content
|
id: content
|
||||||
|
|
||||||
anchors.top: parent.top
|
anchors.top: parent.top
|
||||||
anchors.left: parent.left
|
anchors.left: parent.left
|
||||||
anchors.right: parent.right
|
anchors.right: parent.right
|
||||||
anchors.topMargin: 16
|
|
||||||
anchors.rightMargin: 16
|
|
||||||
anchors.leftMargin: 16
|
|
||||||
|
|
||||||
spacing: 8
|
spacing: 8
|
||||||
|
|
||||||
|
onImplicitHeightChanged: {
|
||||||
|
root.expandedHeight = content.implicitHeight + 32
|
||||||
|
}
|
||||||
|
|
||||||
Header2TextType {
|
Header2TextType {
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
|
Layout.topMargin: 16
|
||||||
|
Layout.rightMargin: 16
|
||||||
|
Layout.leftMargin: 16
|
||||||
|
|
||||||
text: headerText
|
text: headerText
|
||||||
}
|
}
|
||||||
@@ -40,6 +41,8 @@ DrawerType {
|
|||||||
ParagraphTextType {
|
ParagraphTextType {
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
Layout.topMargin: 8
|
Layout.topMargin: 8
|
||||||
|
Layout.rightMargin: 16
|
||||||
|
Layout.leftMargin: 16
|
||||||
|
|
||||||
text: descriptionText
|
text: descriptionText
|
||||||
}
|
}
|
||||||
@@ -47,10 +50,12 @@ DrawerType {
|
|||||||
BasicButtonType {
|
BasicButtonType {
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
Layout.topMargin: 16
|
Layout.topMargin: 16
|
||||||
|
Layout.rightMargin: 16
|
||||||
|
Layout.leftMargin: 16
|
||||||
|
|
||||||
text: yesButtonText
|
text: yesButtonText
|
||||||
|
|
||||||
onClicked: {
|
clickedFunc: function() {
|
||||||
if (yesButtonFunction && typeof yesButtonFunction === "function") {
|
if (yesButtonFunction && typeof yesButtonFunction === "function") {
|
||||||
yesButtonFunction()
|
yesButtonFunction()
|
||||||
}
|
}
|
||||||
@@ -59,6 +64,8 @@ DrawerType {
|
|||||||
|
|
||||||
BasicButtonType {
|
BasicButtonType {
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
|
Layout.rightMargin: 16
|
||||||
|
Layout.leftMargin: 16
|
||||||
|
|
||||||
defaultColor: "transparent"
|
defaultColor: "transparent"
|
||||||
hoveredColor: Qt.rgba(1, 1, 1, 0.08)
|
hoveredColor: Qt.rgba(1, 1, 1, 0.08)
|
||||||
@@ -69,7 +76,7 @@ DrawerType {
|
|||||||
|
|
||||||
text: noButtonText
|
text: noButtonText
|
||||||
|
|
||||||
onClicked: {
|
clickedFunc: function() {
|
||||||
if (noButtonFunction && typeof noButtonFunction === "function") {
|
if (noButtonFunction && typeof noButtonFunction === "function") {
|
||||||
noButtonFunction()
|
noButtonFunction()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,129 +5,136 @@ import QtQuick.Layouts
|
|||||||
import "../Controls2"
|
import "../Controls2"
|
||||||
import "../Controls2/TextTypes"
|
import "../Controls2/TextTypes"
|
||||||
|
|
||||||
DrawerType {
|
DrawerType2 {
|
||||||
id: root
|
id: root
|
||||||
|
|
||||||
width: parent.width
|
expandedContent: Item {
|
||||||
height: parent.height * 0.9
|
id: container
|
||||||
|
|
||||||
ColumnLayout {
|
implicitHeight: root.height * 0.9
|
||||||
id: backButton
|
|
||||||
|
|
||||||
anchors.top: parent.top
|
Component.onCompleted: {
|
||||||
anchors.left: parent.left
|
root.expandedHeight = container.implicitHeight
|
||||||
anchors.right: parent.right
|
|
||||||
anchors.topMargin: 16
|
|
||||||
|
|
||||||
BackButtonType {
|
|
||||||
backButtonImage: "qrc:/images/controls/arrow-left.svg"
|
|
||||||
backButtonFunction: function() {
|
|
||||||
root.close()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
FlickableType {
|
|
||||||
anchors.top: backButton.bottom
|
|
||||||
anchors.left: parent.left
|
|
||||||
anchors.right: parent.right
|
|
||||||
anchors.bottom: parent.bottom
|
|
||||||
contentHeight: content.implicitHeight
|
|
||||||
|
|
||||||
ColumnLayout {
|
ColumnLayout {
|
||||||
id: content
|
id: backButton
|
||||||
|
|
||||||
anchors.fill: parent
|
anchors.top: parent.top
|
||||||
|
anchors.left: parent.left
|
||||||
|
anchors.right: parent.right
|
||||||
|
anchors.topMargin: 16
|
||||||
|
|
||||||
Header2Type {
|
BackButtonType {
|
||||||
id: header
|
backButtonImage: "qrc:/images/controls/arrow-left.svg"
|
||||||
Layout.fillWidth: true
|
backButtonFunction: function() {
|
||||||
Layout.topMargin: 16
|
root.close()
|
||||||
Layout.rightMargin: 16
|
}
|
||||||
Layout.leftMargin: 16
|
|
||||||
|
|
||||||
headerText: qsTr("Choose language")
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
ListView {
|
FlickableType {
|
||||||
id: listView
|
anchors.top: backButton.bottom
|
||||||
|
anchors.left: parent.left
|
||||||
|
anchors.right: parent.right
|
||||||
|
anchors.bottom: parent.bottom
|
||||||
|
contentHeight: content.implicitHeight
|
||||||
|
|
||||||
Layout.fillWidth: true
|
ColumnLayout {
|
||||||
height: listView.contentItem.height
|
id: content
|
||||||
|
|
||||||
clip: true
|
anchors.fill: parent
|
||||||
interactive: false
|
|
||||||
|
|
||||||
model: LanguageModel
|
Header2Type {
|
||||||
currentIndex: LanguageModel.currentLanguageIndex
|
id: header
|
||||||
|
Layout.fillWidth: true
|
||||||
|
Layout.topMargin: 16
|
||||||
|
Layout.rightMargin: 16
|
||||||
|
Layout.leftMargin: 16
|
||||||
|
|
||||||
ButtonGroup {
|
headerText: qsTr("Choose language")
|
||||||
id: buttonGroup
|
|
||||||
}
|
}
|
||||||
|
|
||||||
delegate: Item {
|
ListView {
|
||||||
implicitWidth: root.width
|
id: listView
|
||||||
implicitHeight: delegateContent.implicitHeight
|
|
||||||
|
|
||||||
ColumnLayout {
|
Layout.fillWidth: true
|
||||||
id: delegateContent
|
height: listView.contentItem.height
|
||||||
|
|
||||||
anchors.fill: parent
|
clip: true
|
||||||
|
interactive: false
|
||||||
|
|
||||||
RadioButton {
|
model: LanguageModel
|
||||||
id: radioButton
|
currentIndex: LanguageModel.currentLanguageIndex
|
||||||
|
|
||||||
implicitWidth: parent.width
|
ButtonGroup {
|
||||||
implicitHeight: radioButtonContent.implicitHeight
|
id: buttonGroup
|
||||||
|
}
|
||||||
|
|
||||||
hoverEnabled: true
|
delegate: Item {
|
||||||
|
implicitWidth: root.width
|
||||||
|
implicitHeight: delegateContent.implicitHeight
|
||||||
|
|
||||||
indicator: Rectangle {
|
ColumnLayout {
|
||||||
anchors.fill: parent
|
id: delegateContent
|
||||||
color: radioButton.hovered ? "#2C2D30" : "#1C1D21"
|
|
||||||
|
|
||||||
Behavior on color {
|
anchors.fill: parent
|
||||||
PropertyAnimation { duration: 200 }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
RowLayout {
|
RadioButton {
|
||||||
id: radioButtonContent
|
id: radioButton
|
||||||
anchors.fill: parent
|
|
||||||
|
|
||||||
anchors.rightMargin: 16
|
implicitWidth: parent.width
|
||||||
anchors.leftMargin: 16
|
implicitHeight: radioButtonContent.implicitHeight
|
||||||
|
|
||||||
spacing: 0
|
hoverEnabled: true
|
||||||
|
|
||||||
z: 1
|
indicator: Rectangle {
|
||||||
|
anchors.fill: parent
|
||||||
|
color: radioButton.hovered ? "#2C2D30" : "#1C1D21"
|
||||||
|
|
||||||
ParagraphTextType {
|
Behavior on color {
|
||||||
Layout.fillWidth: true
|
PropertyAnimation { duration: 200 }
|
||||||
Layout.topMargin: 20
|
}
|
||||||
Layout.bottomMargin: 20
|
|
||||||
|
|
||||||
text: languageName
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Image {
|
RowLayout {
|
||||||
source: "qrc:/images/controls/check.svg"
|
id: radioButtonContent
|
||||||
visible: radioButton.checked
|
anchors.fill: parent
|
||||||
|
|
||||||
width: 24
|
anchors.rightMargin: 16
|
||||||
height: 24
|
anchors.leftMargin: 16
|
||||||
|
|
||||||
Layout.rightMargin: 8
|
spacing: 0
|
||||||
|
|
||||||
|
z: 1
|
||||||
|
|
||||||
|
ParagraphTextType {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
Layout.topMargin: 20
|
||||||
|
Layout.bottomMargin: 20
|
||||||
|
|
||||||
|
text: languageName
|
||||||
|
}
|
||||||
|
|
||||||
|
Image {
|
||||||
|
source: "qrc:/images/controls/check.svg"
|
||||||
|
visible: radioButton.checked
|
||||||
|
|
||||||
|
width: 24
|
||||||
|
height: 24
|
||||||
|
|
||||||
|
Layout.rightMargin: 8
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
ButtonGroup.group: buttonGroup
|
ButtonGroup.group: buttonGroup
|
||||||
checked: listView.currentIndex === index
|
checked: listView.currentIndex === index
|
||||||
|
|
||||||
onClicked: {
|
onClicked: {
|
||||||
listView.currentIndex = index
|
listView.currentIndex = index
|
||||||
LanguageModel.changeLanguage(languageIndex)
|
LanguageModel.changeLanguage(languageIndex)
|
||||||
root.close()
|
root.close()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,19 +16,18 @@ import "../Controls2/TextTypes"
|
|||||||
import "../Config"
|
import "../Config"
|
||||||
import "../Components"
|
import "../Components"
|
||||||
|
|
||||||
DrawerType {
|
DrawerType2 {
|
||||||
id: root
|
id: root
|
||||||
|
|
||||||
property alias headerText: header.headerText
|
property string headerText
|
||||||
property alias configContentHeaderText: configContentHeader.headerText
|
property string configContentHeaderText
|
||||||
property alias contentVisible: content.visible
|
property string contentVisible
|
||||||
|
|
||||||
property string configExtension: ".vpn"
|
property string configExtension: ".vpn"
|
||||||
property string configCaption: qsTr("Save AmneziaVPN config")
|
property string configCaption: qsTr("Save AmneziaVPN config")
|
||||||
property string configFileName: "amnezia_config"
|
property string configFileName: "amnezia_config"
|
||||||
|
|
||||||
width: parent.width
|
expandedHeight: parent.height * 0.9
|
||||||
height: parent.height * 0.9
|
|
||||||
|
|
||||||
onClosed: {
|
onClosed: {
|
||||||
configExtension = ".vpn"
|
configExtension = ".vpn"
|
||||||
@@ -36,8 +35,8 @@ DrawerType {
|
|||||||
configFileName = "amnezia_config"
|
configFileName = "amnezia_config"
|
||||||
}
|
}
|
||||||
|
|
||||||
Item {
|
expandedContent: Item {
|
||||||
anchors.fill: parent
|
implicitHeight: root.expandedHeight
|
||||||
|
|
||||||
Header2Type {
|
Header2Type {
|
||||||
id: header
|
id: header
|
||||||
@@ -47,6 +46,8 @@ DrawerType {
|
|||||||
anchors.topMargin: 20
|
anchors.topMargin: 20
|
||||||
anchors.leftMargin: 16
|
anchors.leftMargin: 16
|
||||||
anchors.rightMargin: 16
|
anchors.rightMargin: 16
|
||||||
|
|
||||||
|
headerText: root.headerText
|
||||||
}
|
}
|
||||||
|
|
||||||
FlickableType {
|
FlickableType {
|
||||||
@@ -64,6 +65,8 @@ DrawerType {
|
|||||||
anchors.leftMargin: 16
|
anchors.leftMargin: 16
|
||||||
anchors.rightMargin: 16
|
anchors.rightMargin: 16
|
||||||
|
|
||||||
|
visible: root.contentVisible
|
||||||
|
|
||||||
BasicButtonType {
|
BasicButtonType {
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
Layout.topMargin: 16
|
Layout.topMargin: 16
|
||||||
@@ -71,7 +74,7 @@ DrawerType {
|
|||||||
text: qsTr("Share")
|
text: qsTr("Share")
|
||||||
imageSource: "qrc:/images/controls/share-2.svg"
|
imageSource: "qrc:/images/controls/share-2.svg"
|
||||||
|
|
||||||
onClicked: {
|
clickedFunc: function() {
|
||||||
var fileName = ""
|
var fileName = ""
|
||||||
if (GC.isMobile()) {
|
if (GC.isMobile()) {
|
||||||
fileName = configFileName + configExtension
|
fileName = configFileName + configExtension
|
||||||
@@ -91,6 +94,7 @@ DrawerType {
|
|||||||
}
|
}
|
||||||
|
|
||||||
BasicButtonType {
|
BasicButtonType {
|
||||||
|
id: copyConfigTextButton
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
Layout.topMargin: 8
|
Layout.topMargin: 8
|
||||||
|
|
||||||
@@ -104,7 +108,7 @@ DrawerType {
|
|||||||
text: qsTr("Copy")
|
text: qsTr("Copy")
|
||||||
imageSource: "qrc:/images/controls/copy.svg"
|
imageSource: "qrc:/images/controls/copy.svg"
|
||||||
|
|
||||||
onClicked: {
|
clickedFunc: function() {
|
||||||
configText.selectAll()
|
configText.selectAll()
|
||||||
configText.copy()
|
configText.copy()
|
||||||
configText.select(0, 0)
|
configText.select(0, 0)
|
||||||
@@ -113,10 +117,11 @@ DrawerType {
|
|||||||
}
|
}
|
||||||
|
|
||||||
BasicButtonType {
|
BasicButtonType {
|
||||||
|
id: copyNativeConfigStringButton
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
Layout.topMargin: 8
|
Layout.topMargin: 8
|
||||||
|
|
||||||
visible: nativeConfigString.text !== ""
|
visible: false
|
||||||
|
|
||||||
defaultColor: "transparent"
|
defaultColor: "transparent"
|
||||||
hoveredColor: Qt.rgba(1, 1, 1, 0.08)
|
hoveredColor: Qt.rgba(1, 1, 1, 0.08)
|
||||||
@@ -128,7 +133,7 @@ DrawerType {
|
|||||||
text: qsTr("Copy config string")
|
text: qsTr("Copy config string")
|
||||||
imageSource: "qrc:/images/controls/copy.svg"
|
imageSource: "qrc:/images/controls/copy.svg"
|
||||||
|
|
||||||
onClicked: {
|
clickedFunc: function() {
|
||||||
nativeConfigString.selectAll()
|
nativeConfigString.selectAll()
|
||||||
nativeConfigString.copy()
|
nativeConfigString.copy()
|
||||||
nativeConfigString.select(0, 0)
|
nativeConfigString.select(0, 0)
|
||||||
@@ -149,83 +154,117 @@ DrawerType {
|
|||||||
|
|
||||||
text: qsTr("Show connection settings")
|
text: qsTr("Show connection settings")
|
||||||
|
|
||||||
onClicked: {
|
clickedFunc: function() {
|
||||||
configContentDrawer.visible = true
|
configContentDrawer.open()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
DrawerType {
|
DrawerType2 {
|
||||||
id: configContentDrawer
|
id: configContentDrawer
|
||||||
|
|
||||||
width: parent.width
|
parent: root.parent
|
||||||
height: parent.height * 0.9
|
|
||||||
|
|
||||||
BackButtonType {
|
anchors.fill: parent
|
||||||
id: backButton
|
expandedHeight: parent.height * 0.9
|
||||||
|
|
||||||
anchors.top: parent.top
|
expandedContent: Item {
|
||||||
anchors.left: parent.left
|
id: configContentContainer
|
||||||
anchors.right: parent.right
|
|
||||||
anchors.topMargin: 16
|
|
||||||
|
|
||||||
backButtonFunction: function() {
|
implicitHeight: configContentDrawer.expandedHeight
|
||||||
configContentDrawer.visible = false
|
|
||||||
|
Connections {
|
||||||
|
target: copyNativeConfigStringButton
|
||||||
|
function onClicked() {
|
||||||
|
nativeConfigString.selectAll()
|
||||||
|
nativeConfigString.copy()
|
||||||
|
nativeConfigString.select(0, 0)
|
||||||
|
PageController.showNotificationMessage(qsTr("Copied"))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
FlickableType {
|
Connections {
|
||||||
anchors.top: backButton.bottom
|
target: copyConfigTextButton
|
||||||
anchors.left: parent.left
|
function onClicked() {
|
||||||
anchors.right: parent.right
|
configText.selectAll()
|
||||||
anchors.bottom: parent.bottom
|
configText.copy()
|
||||||
contentHeight: configContent.implicitHeight + configContent.anchors.topMargin + configContent.anchors.bottomMargin
|
configText.select(0, 0)
|
||||||
|
PageController.showNotificationMessage(qsTr("Copied"))
|
||||||
ColumnLayout {
|
|
||||||
id: configContent
|
|
||||||
|
|
||||||
anchors.fill: parent
|
|
||||||
anchors.rightMargin: 16
|
|
||||||
anchors.leftMargin: 16
|
|
||||||
|
|
||||||
Header2Type {
|
|
||||||
id: configContentHeader
|
|
||||||
Layout.fillWidth: true
|
|
||||||
Layout.topMargin: 16
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
TextField {
|
BackButtonType {
|
||||||
id: nativeConfigString
|
id: backButton
|
||||||
visible: false
|
|
||||||
text: ExportController.nativeConfigString
|
anchors.top: parent.top
|
||||||
|
anchors.left: parent.left
|
||||||
|
anchors.right: parent.right
|
||||||
|
anchors.topMargin: 16
|
||||||
|
|
||||||
|
backButtonFunction: function() {
|
||||||
|
configContentDrawer.open()
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
TextArea {
|
FlickableType {
|
||||||
id: configText
|
anchors.top: backButton.bottom
|
||||||
|
anchors.left: parent.left
|
||||||
|
anchors.right: parent.right
|
||||||
|
anchors.bottom: parent.bottom
|
||||||
|
contentHeight: configContent.implicitHeight + configContent.anchors.topMargin + configContent.anchors.bottomMargin
|
||||||
|
|
||||||
Layout.fillWidth: true
|
ColumnLayout {
|
||||||
Layout.topMargin: 16
|
id: configContent
|
||||||
Layout.bottomMargin: 16
|
|
||||||
|
|
||||||
padding: 0
|
anchors.fill: parent
|
||||||
leftPadding: 0
|
anchors.rightMargin: 16
|
||||||
height: 24
|
anchors.leftMargin: 16
|
||||||
|
|
||||||
readOnly: true
|
Header2Type {
|
||||||
|
id: configContentHeader
|
||||||
|
Layout.fillWidth: true
|
||||||
|
Layout.topMargin: 16
|
||||||
|
|
||||||
color: "#D7D8DB"
|
headerText: root.configContentHeaderText
|
||||||
selectionColor: "#633303"
|
}
|
||||||
selectedTextColor: "#D7D8DB"
|
|
||||||
|
|
||||||
font.pixelSize: 16
|
TextField {
|
||||||
font.weight: Font.Medium
|
id: nativeConfigString
|
||||||
font.family: "PT Root UI VF"
|
visible: false
|
||||||
|
text: ExportController.nativeConfigString
|
||||||
|
|
||||||
text: ExportController.config
|
onTextChanged: {
|
||||||
|
copyNativeConfigStringButton.visible = nativeConfigString.text !== ""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
wrapMode: Text.Wrap
|
TextArea {
|
||||||
|
id: configText
|
||||||
|
|
||||||
background: Rectangle {
|
Layout.fillWidth: true
|
||||||
color: "transparent"
|
Layout.topMargin: 16
|
||||||
|
Layout.bottomMargin: 16
|
||||||
|
|
||||||
|
padding: 0
|
||||||
|
leftPadding: 0
|
||||||
|
height: 24
|
||||||
|
|
||||||
|
readOnly: true
|
||||||
|
|
||||||
|
color: "#D7D8DB"
|
||||||
|
selectionColor: "#633303"
|
||||||
|
selectedTextColor: "#D7D8DB"
|
||||||
|
|
||||||
|
font.pixelSize: 16
|
||||||
|
font.weight: Font.Medium
|
||||||
|
font.family: "PT Root UI VF"
|
||||||
|
|
||||||
|
text: ExportController.config
|
||||||
|
|
||||||
|
wrapMode: Text.Wrap
|
||||||
|
|
||||||
|
background: Rectangle {
|
||||||
|
color: "transparent"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,47 +16,39 @@ Button {
|
|||||||
property string textColor: "#0E0E11"
|
property string textColor: "#0E0E11"
|
||||||
|
|
||||||
property string borderColor: "#D7D8DB"
|
property string borderColor: "#D7D8DB"
|
||||||
|
property string borderFocusedColor: "#D7D8DB"
|
||||||
property int borderWidth: 0
|
property int borderWidth: 0
|
||||||
|
property int borderFocusedWidth: 1
|
||||||
|
|
||||||
property string imageSource
|
property string imageSource
|
||||||
|
property string rightImageSource
|
||||||
|
property string leftImageColor: textColor
|
||||||
|
|
||||||
property bool squareLeftSide: false
|
property bool squareLeftSide: false
|
||||||
|
|
||||||
|
property var clickedFunc
|
||||||
|
|
||||||
implicitHeight: 56
|
implicitHeight: 56
|
||||||
|
|
||||||
hoverEnabled: true
|
hoverEnabled: true
|
||||||
|
|
||||||
background: Rectangle {
|
background: Rectangle {
|
||||||
id: background
|
id: background_border
|
||||||
|
|
||||||
|
color: "transparent"
|
||||||
|
border.color: root.activeFocus ? root.borderFocusedColor : "transparent"
|
||||||
|
border.width: root.activeFocus ? root.borderFocusedWidth : "transparent"
|
||||||
|
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
radius: 16
|
radius: 16
|
||||||
color: {
|
|
||||||
if (root.enabled) {
|
|
||||||
if (root.pressed) {
|
|
||||||
return pressedColor
|
|
||||||
}
|
|
||||||
return root.hovered ? hoveredColor : defaultColor
|
|
||||||
} else {
|
|
||||||
return disabledColor
|
|
||||||
}
|
|
||||||
}
|
|
||||||
border.color: borderColor
|
|
||||||
border.width: borderWidth
|
|
||||||
|
|
||||||
Behavior on color {
|
|
||||||
PropertyAnimation { duration: 200 }
|
|
||||||
}
|
|
||||||
|
|
||||||
Rectangle {
|
Rectangle {
|
||||||
visible: root.squareLeftSide
|
id: background
|
||||||
|
|
||||||
z: 1
|
anchors.fill: background_border
|
||||||
|
anchors.margins: root.activeFocus ? 2: 0
|
||||||
|
|
||||||
width: parent.radius
|
radius: 16
|
||||||
height: parent.radius
|
|
||||||
anchors.top: parent.top
|
|
||||||
anchors.bottom: parent.bottom
|
|
||||||
anchors.left: parent.left
|
|
||||||
color: {
|
color: {
|
||||||
if (root.enabled) {
|
if (root.enabled) {
|
||||||
if (root.pressed) {
|
if (root.pressed) {
|
||||||
@@ -67,24 +59,53 @@ Button {
|
|||||||
return disabledColor
|
return disabledColor
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
border.color: root.activeFocus ? "transparent" : borderColor
|
||||||
|
border.width: root.activeFocus ? 0 : borderWidth
|
||||||
|
|
||||||
Behavior on color {
|
Behavior on color {
|
||||||
PropertyAnimation { duration: 200 }
|
PropertyAnimation { duration: 200 }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Rectangle {
|
||||||
|
visible: root.squareLeftSide
|
||||||
|
|
||||||
|
z: 1
|
||||||
|
|
||||||
|
width: parent.radius
|
||||||
|
height: parent.radius
|
||||||
|
anchors.top: parent.top
|
||||||
|
anchors.bottom: parent.bottom
|
||||||
|
anchors.left: parent.left
|
||||||
|
color: {
|
||||||
|
if (root.enabled) {
|
||||||
|
if (root.pressed) {
|
||||||
|
return pressedColor
|
||||||
|
}
|
||||||
|
return root.hovered ? hoveredColor : defaultColor
|
||||||
|
} else {
|
||||||
|
return disabledColor
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Behavior on color {
|
||||||
|
PropertyAnimation { duration: 200 }
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
MouseArea {
|
MouseArea {
|
||||||
anchors.fill: background
|
anchors.fill: background_border
|
||||||
enabled: false
|
enabled: false
|
||||||
cursorShape: Qt.PointingHandCursor
|
cursorShape: Qt.PointingHandCursor
|
||||||
}
|
}
|
||||||
|
|
||||||
contentItem: Item {
|
contentItem: Item {
|
||||||
anchors.fill: background
|
anchors.fill: background_border
|
||||||
|
|
||||||
implicitWidth: content.implicitWidth
|
implicitWidth: content.implicitWidth
|
||||||
implicitHeight: content.implicitHeight
|
implicitHeight: content.implicitHeight
|
||||||
|
|
||||||
RowLayout {
|
RowLayout {
|
||||||
id: content
|
id: content
|
||||||
anchors.centerIn: parent
|
anchors.centerIn: parent
|
||||||
@@ -99,7 +120,7 @@ Button {
|
|||||||
layer {
|
layer {
|
||||||
enabled: true
|
enabled: true
|
||||||
effect: ColorOverlay {
|
effect: ColorOverlay {
|
||||||
color: textColor
|
color: leftImageColor
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -112,6 +133,39 @@ Button {
|
|||||||
horizontalAlignment: Text.AlignLeft
|
horizontalAlignment: Text.AlignLeft
|
||||||
verticalAlignment: Text.AlignVCenter
|
verticalAlignment: Text.AlignVCenter
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Image {
|
||||||
|
Layout.preferredHeight: 20
|
||||||
|
Layout.preferredWidth: 20
|
||||||
|
|
||||||
|
source: root.rightImageSource
|
||||||
|
visible: root.rightImageSource === "" ? false : true
|
||||||
|
|
||||||
|
layer {
|
||||||
|
enabled: true
|
||||||
|
effect: ColorOverlay {
|
||||||
|
color: textColor
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Keys.onEnterPressed: {
|
||||||
|
if (root.clickedFunc && typeof root.clickedFunc === "function") {
|
||||||
|
root.clickedFunc()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Keys.onReturnPressed: {
|
||||||
|
if (root.clickedFunc && typeof root.clickedFunc === "function") {
|
||||||
|
root.clickedFunc()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
onClicked: {
|
||||||
|
if (root.clickedFunc && typeof root.clickedFunc === "function") {
|
||||||
|
root.clickedFunc()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,84 +0,0 @@
|
|||||||
import QtQuick
|
|
||||||
import QtQuick.Controls
|
|
||||||
|
|
||||||
import "../Config"
|
|
||||||
|
|
||||||
Drawer {
|
|
||||||
id: drawer
|
|
||||||
property bool needCloseButton: true
|
|
||||||
|
|
||||||
Connections {
|
|
||||||
target: PageController
|
|
||||||
|
|
||||||
function onForceCloseDrawer() {
|
|
||||||
visible = false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
edge: Qt.BottomEdge
|
|
||||||
|
|
||||||
clip: true
|
|
||||||
modal: true
|
|
||||||
dragMargin: -10
|
|
||||||
|
|
||||||
enter: Transition {
|
|
||||||
SmoothedAnimation {
|
|
||||||
velocity: 4
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
exit: Transition {
|
|
||||||
SmoothedAnimation {
|
|
||||||
velocity: 4
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
background: Rectangle {
|
|
||||||
anchors.fill: parent
|
|
||||||
anchors.bottomMargin: -radius
|
|
||||||
radius: 16
|
|
||||||
color: "#1C1D21"
|
|
||||||
|
|
||||||
border.color: "#2C2D30"
|
|
||||||
border.width: 1
|
|
||||||
|
|
||||||
Rectangle {
|
|
||||||
visible: GC.isMobile()
|
|
||||||
|
|
||||||
anchors.top: parent.top
|
|
||||||
anchors.horizontalCenter: parent.horizontalCenter
|
|
||||||
anchors.topMargin: 10
|
|
||||||
|
|
||||||
width: 20
|
|
||||||
height: 2
|
|
||||||
color: "#2C2D30"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Overlay.modal: Rectangle {
|
|
||||||
color: Qt.rgba(14/255, 14/255, 17/255, 0.8)
|
|
||||||
}
|
|
||||||
|
|
||||||
onAboutToShow: {
|
|
||||||
if (PageController.getInitialPageNavigationBarColor() !== 0xFF1C1D21) {
|
|
||||||
PageController.updateNavigationBarColor(0xFF1C1D21)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
onOpened: {
|
|
||||||
if (needCloseButton) {
|
|
||||||
PageController.drawerOpen()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
onClosed: {
|
|
||||||
if (needCloseButton) {
|
|
||||||
PageController.drawerClose()
|
|
||||||
}
|
|
||||||
|
|
||||||
var initialPageNavigationBarColor = PageController.getInitialPageNavigationBarColor()
|
|
||||||
if (initialPageNavigationBarColor !== 0xFF1C1D21) {
|
|
||||||
PageController.updateNavigationBarColor(initialPageNavigationBarColor)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,242 @@
|
|||||||
|
import QtQuick
|
||||||
|
import QtQuick.Controls
|
||||||
|
import QtQuick.Layouts
|
||||||
|
|
||||||
|
import "TextTypes"
|
||||||
|
|
||||||
|
Item {
|
||||||
|
id: root
|
||||||
|
|
||||||
|
readonly property string drawerExpanded: "expanded"
|
||||||
|
readonly property string drawerCollapsed: "collapsed"
|
||||||
|
|
||||||
|
readonly property bool isOpened: drawerContent.state === root.drawerExpanded || (drawerContent.state === root.drawerCollapsed && dragArea.drag.active === true)
|
||||||
|
readonly property bool isClosed: drawerContent.state === root.drawerCollapsed && dragArea.drag.active === false
|
||||||
|
|
||||||
|
readonly property bool isExpanded: drawerContent.state === root.drawerExpanded
|
||||||
|
readonly property bool isCollapsed: drawerContent.state === root.drawerCollapsed
|
||||||
|
|
||||||
|
property Component collapsedContent
|
||||||
|
property Component expandedContent
|
||||||
|
|
||||||
|
property string defaultColor: "#1C1D21"
|
||||||
|
property string borderColor: "#2C2D30"
|
||||||
|
|
||||||
|
property real expandedHeight
|
||||||
|
property real collapsedHeight: 0
|
||||||
|
|
||||||
|
signal entered
|
||||||
|
signal exited
|
||||||
|
signal pressed(bool pressed, bool entered)
|
||||||
|
|
||||||
|
signal aboutToHide
|
||||||
|
signal aboutToShow
|
||||||
|
signal close
|
||||||
|
signal open
|
||||||
|
signal closed
|
||||||
|
signal opened
|
||||||
|
|
||||||
|
Connections {
|
||||||
|
target: root
|
||||||
|
|
||||||
|
function onClose() {
|
||||||
|
if (isCollapsed) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
aboutToHide()
|
||||||
|
|
||||||
|
drawerContent.state = root.drawerCollapsed
|
||||||
|
closed()
|
||||||
|
}
|
||||||
|
|
||||||
|
function onOpen() {
|
||||||
|
if (isExpanded) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
aboutToShow()
|
||||||
|
|
||||||
|
drawerContent.state = root.drawerExpanded
|
||||||
|
opened()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Set once based on first implicit height change once all children are layed out */
|
||||||
|
Component.onCompleted: {
|
||||||
|
if (root.isCollapsed && root.collapsedHeight == 0) {
|
||||||
|
root.collapsedHeight = drawerContent.implicitHeight
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Rectangle {
|
||||||
|
id: background
|
||||||
|
|
||||||
|
anchors.fill: parent
|
||||||
|
color: root.isCollapsed ? "transparent" : Qt.rgba(14/255, 14/255, 17/255, 0.8)
|
||||||
|
|
||||||
|
Behavior on color {
|
||||||
|
PropertyAnimation { duration: 200 }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
MouseArea {
|
||||||
|
id: emptyArea
|
||||||
|
anchors.fill: parent
|
||||||
|
enabled: root.isExpanded
|
||||||
|
visible: enabled
|
||||||
|
onClicked: {
|
||||||
|
root.close()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
MouseArea {
|
||||||
|
id: dragArea
|
||||||
|
|
||||||
|
anchors.fill: drawerContentBackground
|
||||||
|
cursorShape: root.isCollapsed ? Qt.PointingHandCursor : Qt.ArrowCursor
|
||||||
|
hoverEnabled: true
|
||||||
|
|
||||||
|
enabled: drawerContent.implicitHeight > 0
|
||||||
|
|
||||||
|
drag.target: drawerContent
|
||||||
|
drag.axis: Drag.YAxis
|
||||||
|
drag.maximumY: root.height - root.collapsedHeight
|
||||||
|
drag.minimumY: root.height - root.expandedHeight
|
||||||
|
|
||||||
|
/** If drag area is released at any point other than min or max y, transition to the other state */
|
||||||
|
onReleased: {
|
||||||
|
if (root.isCollapsed && drawerContent.y < dragArea.drag.maximumY) {
|
||||||
|
root.open()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if (root.isExpanded && drawerContent.y > dragArea.drag.minimumY) {
|
||||||
|
root.close()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
onEntered: {
|
||||||
|
root.entered()
|
||||||
|
}
|
||||||
|
onExited: {
|
||||||
|
root.exited()
|
||||||
|
}
|
||||||
|
onPressedChanged: {
|
||||||
|
root.pressed(pressed, entered)
|
||||||
|
}
|
||||||
|
|
||||||
|
onClicked: {
|
||||||
|
if (root.isCollapsed) {
|
||||||
|
root.open()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Rectangle {
|
||||||
|
id: drawerContentBackground
|
||||||
|
|
||||||
|
anchors { left: drawerContent.left; right: drawerContent.right; top: drawerContent.top }
|
||||||
|
height: root.height
|
||||||
|
radius: 16
|
||||||
|
color: root.defaultColor
|
||||||
|
border.color: root.borderColor
|
||||||
|
border.width: 1
|
||||||
|
|
||||||
|
Rectangle {
|
||||||
|
width: parent.radius
|
||||||
|
height: parent.radius
|
||||||
|
anchors.bottom: parent.bottom
|
||||||
|
anchors.right: parent.right
|
||||||
|
anchors.left: parent.left
|
||||||
|
color: parent.color
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Item {
|
||||||
|
id: drawerContent
|
||||||
|
|
||||||
|
Drag.active: dragArea.drag.active
|
||||||
|
anchors.right: root.right
|
||||||
|
anchors.left: root.left
|
||||||
|
y: root.height - drawerContent.height
|
||||||
|
state: root.drawerCollapsed
|
||||||
|
|
||||||
|
implicitHeight: root.isCollapsed ? collapsedLoader.implicitHeight : expandedLoader.implicitHeight
|
||||||
|
|
||||||
|
onStateChanged: {
|
||||||
|
if (root.isCollapsed) {
|
||||||
|
var initialPageNavigationBarColor = PageController.getInitialPageNavigationBarColor()
|
||||||
|
if (initialPageNavigationBarColor !== 0xFF1C1D21) {
|
||||||
|
PageController.updateNavigationBarColor(initialPageNavigationBarColor)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if (root.isExpanded) {
|
||||||
|
if (PageController.getInitialPageNavigationBarColor() !== 0xFF1C1D21) {
|
||||||
|
PageController.updateNavigationBarColor(0xFF1C1D21)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
states: [
|
||||||
|
State {
|
||||||
|
name: root.drawerCollapsed
|
||||||
|
PropertyChanges {
|
||||||
|
target: drawerContent
|
||||||
|
y: root.height - root.collapsedHeight
|
||||||
|
}
|
||||||
|
},
|
||||||
|
State {
|
||||||
|
name: root.drawerExpanded
|
||||||
|
PropertyChanges {
|
||||||
|
target: drawerContent
|
||||||
|
y: dragArea.drag.minimumY
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
|
transitions: [
|
||||||
|
Transition {
|
||||||
|
from: root.drawerCollapsed
|
||||||
|
to: root.drawerExpanded
|
||||||
|
PropertyAnimation {
|
||||||
|
target: drawerContent
|
||||||
|
properties: "y"
|
||||||
|
duration: 200
|
||||||
|
}
|
||||||
|
},
|
||||||
|
Transition {
|
||||||
|
from: root.drawerExpanded
|
||||||
|
to: root.drawerCollapsed
|
||||||
|
PropertyAnimation {
|
||||||
|
target: drawerContent
|
||||||
|
properties: "y"
|
||||||
|
duration: 200
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
|
Loader {
|
||||||
|
id: collapsedLoader
|
||||||
|
|
||||||
|
visible: root.isCollapsed
|
||||||
|
sourceComponent: root.collapsedContent
|
||||||
|
|
||||||
|
anchors.right: parent.right
|
||||||
|
anchors.left: parent.left
|
||||||
|
}
|
||||||
|
|
||||||
|
Loader {
|
||||||
|
id: expandedLoader
|
||||||
|
|
||||||
|
visible: root.isExpanded
|
||||||
|
sourceComponent: root.expandedContent
|
||||||
|
|
||||||
|
anchors.right: parent.right
|
||||||
|
anchors.left: parent.left
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -36,19 +36,23 @@ Item {
|
|||||||
property int rootButtonTextBottomMargin: 16
|
property int rootButtonTextBottomMargin: 16
|
||||||
|
|
||||||
property real drawerHeight: 0.9
|
property real drawerHeight: 0.9
|
||||||
|
property Item drawerParent
|
||||||
property Component listView
|
property Component listView
|
||||||
|
|
||||||
property alias menuVisible: menu.visible
|
signal open
|
||||||
|
signal close
|
||||||
|
|
||||||
implicitWidth: rootButtonContent.implicitWidth
|
implicitWidth: rootButtonContent.implicitWidth
|
||||||
implicitHeight: rootButtonContent.implicitHeight
|
implicitHeight: rootButtonContent.implicitHeight
|
||||||
|
|
||||||
onMenuVisibleChanged: {
|
onOpen: {
|
||||||
if (menuVisible) {
|
menu.open()
|
||||||
rootButtonBackground.border.color = rootButtonPressedBorderColor
|
rootButtonBackground.border.color = rootButtonPressedBorderColor
|
||||||
} else {
|
}
|
||||||
rootButtonBackground.border.color = rootButtonDefaultBorderColor
|
|
||||||
}
|
onClose: {
|
||||||
|
menu.close()
|
||||||
|
rootButtonBackground.border.color = rootButtonDefaultBorderColor
|
||||||
}
|
}
|
||||||
|
|
||||||
onEnabledChanged: {
|
onEnabledChanged: {
|
||||||
@@ -133,21 +137,21 @@ Item {
|
|||||||
hoverEnabled: root.enabled ? true : false
|
hoverEnabled: root.enabled ? true : false
|
||||||
|
|
||||||
onEntered: {
|
onEntered: {
|
||||||
if (menu.visible === false) {
|
if (menu.isClosed) {
|
||||||
rootButtonBackground.border.color = rootButtonHoveredBorderColor
|
rootButtonBackground.border.color = rootButtonHoveredBorderColor
|
||||||
rootButtonBackground.color = rootButtonBackgroundHoveredColor
|
rootButtonBackground.color = rootButtonBackgroundHoveredColor
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
onExited: {
|
onExited: {
|
||||||
if (menu.visible === false) {
|
if (menu.isClosed) {
|
||||||
rootButtonBackground.border.color = rootButtonDefaultBorderColor
|
rootButtonBackground.border.color = rootButtonDefaultBorderColor
|
||||||
rootButtonBackground.color = rootButtonBackgroundColor
|
rootButtonBackground.color = rootButtonBackgroundColor
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
onPressed: {
|
onPressed: {
|
||||||
if (menu.visible === false) {
|
if (menu.isClosed) {
|
||||||
rootButtonBackground.color = pressed ? rootButtonBackgroundPressedColor : entered ? rootButtonHoveredBorderColor : rootButtonDefaultBorderColor
|
rootButtonBackground.color = pressed ? rootButtonBackgroundPressedColor : entered ? rootButtonHoveredBorderColor : rootButtonDefaultBorderColor
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -156,60 +160,68 @@ Item {
|
|||||||
if (rootButtonClickedFunction && typeof rootButtonClickedFunction === "function") {
|
if (rootButtonClickedFunction && typeof rootButtonClickedFunction === "function") {
|
||||||
rootButtonClickedFunction()
|
rootButtonClickedFunction()
|
||||||
} else {
|
} else {
|
||||||
menu.visible = true
|
menu.open()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
DrawerType {
|
DrawerType2 {
|
||||||
id: menu
|
id: menu
|
||||||
|
|
||||||
width: parent.width
|
parent: drawerParent
|
||||||
height: parent.height * drawerHeight
|
|
||||||
|
|
||||||
ColumnLayout {
|
anchors.fill: parent
|
||||||
id: header
|
expandedHeight: drawerParent.height * drawerHeight
|
||||||
|
|
||||||
anchors.top: parent.top
|
expandedContent: Item {
|
||||||
anchors.left: parent.left
|
id: container
|
||||||
anchors.right: parent.right
|
|
||||||
anchors.topMargin: 16
|
|
||||||
|
|
||||||
BackButtonType {
|
implicitHeight: menu.expandedHeight
|
||||||
backButtonImage: root.headerBackButtonImage
|
|
||||||
backButtonFunction: function() {
|
|
||||||
root.menuVisible = false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
FlickableType {
|
ColumnLayout {
|
||||||
anchors.top: header.bottom
|
id: header
|
||||||
anchors.topMargin: 16
|
|
||||||
contentHeight: col.implicitHeight
|
|
||||||
|
|
||||||
Column {
|
|
||||||
id: col
|
|
||||||
anchors.top: parent.top
|
anchors.top: parent.top
|
||||||
anchors.left: parent.left
|
anchors.left: parent.left
|
||||||
anchors.right: parent.right
|
anchors.right: parent.right
|
||||||
|
anchors.topMargin: 16
|
||||||
|
|
||||||
spacing: 16
|
BackButtonType {
|
||||||
|
backButtonImage: root.headerBackButtonImage
|
||||||
|
backButtonFunction: function() {
|
||||||
|
menu.close()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Header2Type {
|
FlickableType {
|
||||||
|
anchors.top: header.bottom
|
||||||
|
anchors.topMargin: 16
|
||||||
|
contentHeight: col.implicitHeight
|
||||||
|
|
||||||
|
Column {
|
||||||
|
id: col
|
||||||
|
anchors.top: parent.top
|
||||||
anchors.left: parent.left
|
anchors.left: parent.left
|
||||||
anchors.right: parent.right
|
anchors.right: parent.right
|
||||||
anchors.leftMargin: 16
|
|
||||||
anchors.rightMargin: 16
|
|
||||||
|
|
||||||
headerText: root.headerText
|
spacing: 16
|
||||||
|
|
||||||
width: parent.width
|
Header2Type {
|
||||||
}
|
anchors.left: parent.left
|
||||||
|
anchors.right: parent.right
|
||||||
|
anchors.leftMargin: 16
|
||||||
|
anchors.rightMargin: 16
|
||||||
|
|
||||||
Loader {
|
headerText: root.headerText
|
||||||
id: listViewLoader
|
|
||||||
sourceComponent: root.listView
|
width: parent.width
|
||||||
|
}
|
||||||
|
|
||||||
|
Loader {
|
||||||
|
id: listViewLoader
|
||||||
|
sourceComponent: root.listView
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,6 +7,8 @@ Item {
|
|||||||
|
|
||||||
property StackView stackView: StackView.view
|
property StackView stackView: StackView.view
|
||||||
|
|
||||||
|
property var defaultActiveFocusItem: null
|
||||||
|
|
||||||
// MouseArea {
|
// MouseArea {
|
||||||
// id: globalMouseArea
|
// id: globalMouseArea
|
||||||
// z: 99
|
// z: 99
|
||||||
@@ -19,4 +21,17 @@ Item {
|
|||||||
// mouse.accepted = false
|
// mouse.accepted = false
|
||||||
// }
|
// }
|
||||||
// }
|
// }
|
||||||
|
|
||||||
|
// Set a timer to set focus after a short delay
|
||||||
|
Timer {
|
||||||
|
id: timer
|
||||||
|
interval: 100 // Milliseconds
|
||||||
|
onTriggered: {
|
||||||
|
if (defaultActiveFocusItem) {
|
||||||
|
defaultActiveFocusItem.forceActiveFocus()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
repeat: false // Stop the timer after one trigger
|
||||||
|
running: true // Start the timer
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -66,7 +66,7 @@ Popup {
|
|||||||
borderWidth: 0
|
borderWidth: 0
|
||||||
|
|
||||||
text: qsTr("Close")
|
text: qsTr("Close")
|
||||||
onClicked: {
|
clickedFunc: function() {
|
||||||
root.close()
|
root.close()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -69,10 +69,13 @@ Item {
|
|||||||
|
|
||||||
TextField {
|
TextField {
|
||||||
id: textField
|
id: textField
|
||||||
|
activeFocusOnTab: false
|
||||||
|
|
||||||
enabled: root.textFieldEditable
|
enabled: root.textFieldEditable
|
||||||
color: root.enabled ? root.textFieldTextColor : root.textFieldTextDisabledColor
|
color: root.enabled ? root.textFieldTextColor : root.textFieldTextDisabledColor
|
||||||
|
|
||||||
|
inputMethodHints: Qt.ImhNoAutoUppercase | Qt.ImhSensitiveData | Qt.ImhNoPredictiveText
|
||||||
|
|
||||||
placeholderText: root.textFieldPlaceholderText
|
placeholderText: root.textFieldPlaceholderText
|
||||||
placeholderTextColor: "#494B50"
|
placeholderTextColor: "#494B50"
|
||||||
|
|
||||||
@@ -142,7 +145,7 @@ Item {
|
|||||||
Layout.preferredWidth: content.implicitHeight
|
Layout.preferredWidth: content.implicitHeight
|
||||||
squareLeftSide: true
|
squareLeftSide: true
|
||||||
|
|
||||||
onClicked: {
|
clickedFunc: function() {
|
||||||
if (root.clickedFunc && typeof root.clickedFunc === "function") {
|
if (root.clickedFunc && typeof root.clickedFunc === "function") {
|
||||||
root.clickedFunc()
|
root.clickedFunc()
|
||||||
}
|
}
|
||||||
@@ -186,4 +189,12 @@ Item {
|
|||||||
function getBackgroundBorderColor(noneFocusedColor) {
|
function getBackgroundBorderColor(noneFocusedColor) {
|
||||||
return textField.focus ? root.borderFocusedColor : noneFocusedColor
|
return textField.focus ? root.borderFocusedColor : noneFocusedColor
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Keys.onEnterPressed: {
|
||||||
|
KeyNavigation.tab.forceActiveFocus();
|
||||||
|
}
|
||||||
|
|
||||||
|
Keys.onReturnPressed: {
|
||||||
|
KeyNavigation.tab.forceActiveFocus();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+331
-433
@@ -18,498 +18,396 @@ import "../Components"
|
|||||||
PageType {
|
PageType {
|
||||||
id: root
|
id: root
|
||||||
|
|
||||||
property string defaultColor: "#1C1D21"
|
|
||||||
|
|
||||||
property string borderColor: "#2C2D30"
|
|
||||||
|
|
||||||
Connections {
|
Connections {
|
||||||
target: PageController
|
target: PageController
|
||||||
|
|
||||||
function onRestorePageHomeState(isContainerInstalled) {
|
function onRestorePageHomeState(isContainerInstalled) {
|
||||||
buttonContent.state = "expanded"
|
drawer.open()
|
||||||
if (isContainerInstalled) {
|
if (isContainerInstalled) {
|
||||||
containersDropDown.rootButtonClickedFunction()
|
containersDropDown.rootButtonClickedFunction()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function onForceCloseDrawer() {
|
|
||||||
buttonContent.state = "collapsed"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
MouseArea {
|
|
||||||
anchors.fill: parent
|
|
||||||
enabled: buttonContent.state === "expanded"
|
|
||||||
onClicked: {
|
|
||||||
buttonContent.state = "collapsed"
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Item {
|
Item {
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
anchors.bottomMargin: buttonContent.collapsedHeight
|
anchors.bottomMargin: drawer.collapsedHeight
|
||||||
|
|
||||||
ConnectButton {
|
ConnectButton {
|
||||||
|
id: connectButton
|
||||||
anchors.centerIn: parent
|
anchors.centerIn: parent
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
MouseArea {
|
BasicButtonType {
|
||||||
id: dragArea
|
anchors.horizontalCenter: parent.horizontalCenter
|
||||||
|
|
||||||
anchors.fill: buttonBackground
|
|
||||||
cursorShape: buttonContent.state === "collapsed" ? Qt.PointingHandCursor : Qt.ArrowCursor
|
|
||||||
hoverEnabled: true
|
|
||||||
|
|
||||||
drag.target: buttonContent
|
|
||||||
drag.axis: Drag.YAxis
|
|
||||||
drag.maximumY: root.height - buttonContent.collapsedHeight
|
|
||||||
drag.minimumY: root.height - root.height * 0.9
|
|
||||||
|
|
||||||
/** If drag area is released at any point other than min or max y, transition to the other state */
|
|
||||||
onReleased: {
|
|
||||||
if (buttonContent.state === "collapsed" && buttonContent.y < dragArea.drag.maximumY) {
|
|
||||||
buttonContent.state = "expanded"
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if (buttonContent.state === "expanded" && buttonContent.y > dragArea.drag.minimumY) {
|
|
||||||
buttonContent.state = "collapsed"
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
onEntered: {
|
|
||||||
collapsedButtonChevron.backgroundColor = collapsedButtonChevron.hoveredColor
|
|
||||||
collapsedButtonHeader.opacity = 0.8
|
|
||||||
}
|
|
||||||
onExited: {
|
|
||||||
collapsedButtonChevron.backgroundColor = collapsedButtonChevron.defaultColor
|
|
||||||
collapsedButtonHeader.opacity = 1
|
|
||||||
}
|
|
||||||
onPressedChanged: {
|
|
||||||
collapsedButtonChevron.backgroundColor = pressed ? collapsedButtonChevron.pressedColor : entered ? collapsedButtonChevron.hoveredColor : collapsedButtonChevron.defaultColor
|
|
||||||
collapsedButtonHeader.opacity = 0.7
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
onClicked: {
|
|
||||||
if (buttonContent.state === "collapsed") {
|
|
||||||
buttonContent.state = "expanded"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Rectangle {
|
|
||||||
id: buttonBackground
|
|
||||||
|
|
||||||
anchors { left: buttonContent.left; right: buttonContent.right; top: buttonContent.top }
|
|
||||||
height: root.height
|
|
||||||
radius: 16
|
|
||||||
color: root.defaultColor
|
|
||||||
border.color: root.borderColor
|
|
||||||
border.width: 1
|
|
||||||
|
|
||||||
Rectangle {
|
|
||||||
width: parent.radius
|
|
||||||
height: parent.radius
|
|
||||||
anchors.bottom: parent.bottom
|
anchors.bottom: parent.bottom
|
||||||
anchors.right: parent.right
|
anchors.bottomMargin: 34
|
||||||
anchors.left: parent.left
|
leftPadding: 16
|
||||||
color: parent.color
|
rightPadding: 16
|
||||||
|
|
||||||
|
implicitHeight: 36
|
||||||
|
|
||||||
|
defaultColor: "transparent"
|
||||||
|
hoveredColor: Qt.rgba(1, 1, 1, 0.08)
|
||||||
|
pressedColor: Qt.rgba(1, 1, 1, 0.12)
|
||||||
|
disabledColor: "#878B91"
|
||||||
|
textColor: "#878B91"
|
||||||
|
leftImageColor: "transparent"
|
||||||
|
borderWidth: 0
|
||||||
|
|
||||||
|
property bool isSplitTunnelingEnabled: SitesModel.isTunnelingEnabled ||
|
||||||
|
(ServersModel.isDefaultServerDefaultContainerHasSplitTunneling && ServersModel.getDefaultServerData("isServerFromApi"))
|
||||||
|
|
||||||
|
text: isSplitTunnelingEnabled ? qsTr("Split tunneling enabled") : qsTr("Split tunneling disabled")
|
||||||
|
|
||||||
|
imageSource: isSplitTunnelingEnabled ? "qrc:/images/controls/split-tunneling.svg" : ""
|
||||||
|
rightImageSource: "qrc:/images/controls/chevron-down.svg"
|
||||||
|
|
||||||
|
onClicked: {
|
||||||
|
homeSplitTunnelingDrawer.open()
|
||||||
|
}
|
||||||
|
|
||||||
|
HomeSplitTunnelingDrawer {
|
||||||
|
id: homeSplitTunnelingDrawer
|
||||||
|
|
||||||
|
parent: root
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ColumnLayout {
|
|
||||||
id: buttonContent
|
|
||||||
|
|
||||||
/** Initial height of button content */
|
DrawerType2 {
|
||||||
property int collapsedHeight: 0
|
id: drawer
|
||||||
/** True when expanded objects should be visible */
|
anchors.fill: parent
|
||||||
property bool expandedVisibility: buttonContent.state === "expanded" || (buttonContent.state === "collapsed" && dragArea.drag.active === true)
|
|
||||||
/** True when collapsed objects should be visible */
|
|
||||||
property bool collapsedVisibility: buttonContent.state === "collapsed" && dragArea.drag.active === false
|
|
||||||
|
|
||||||
Drag.active: dragArea.drag.active
|
collapsedContent: ColumnLayout {
|
||||||
anchors.right: root.right
|
DividerType {
|
||||||
anchors.left: root.left
|
Layout.topMargin: 10
|
||||||
y: root.height - buttonContent.height
|
Layout.fillWidth: false
|
||||||
|
Layout.preferredWidth: 20
|
||||||
Component.onCompleted: {
|
Layout.preferredHeight: 2
|
||||||
buttonContent.state = "collapsed"
|
Layout.alignment: Qt.AlignHCenter | Qt.AlignVCenter
|
||||||
}
|
|
||||||
|
|
||||||
/** Set once based on first implicit height change once all children are layed out */
|
|
||||||
onImplicitHeightChanged: {
|
|
||||||
if (buttonContent.state === "collapsed" && collapsedHeight == 0) {
|
|
||||||
collapsedHeight = implicitHeight
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
onStateChanged: {
|
|
||||||
if (buttonContent.state === "collapsed") {
|
|
||||||
var initialPageNavigationBarColor = PageController.getInitialPageNavigationBarColor()
|
|
||||||
if (initialPageNavigationBarColor !== 0xFF1C1D21) {
|
|
||||||
PageController.updateNavigationBarColor(initialPageNavigationBarColor)
|
|
||||||
}
|
|
||||||
PageController.drawerClose()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if (buttonContent.state === "expanded") {
|
|
||||||
if (PageController.getInitialPageNavigationBarColor() !== 0xFF1C1D21) {
|
|
||||||
PageController.updateNavigationBarColor(0xFF1C1D21)
|
|
||||||
}
|
|
||||||
PageController.drawerOpen()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Two states of buttonContent, great place to add any future animations for the drawer */
|
|
||||||
states: [
|
|
||||||
State {
|
|
||||||
name: "collapsed"
|
|
||||||
PropertyChanges {
|
|
||||||
target: buttonContent
|
|
||||||
y: root.height - collapsedHeight
|
|
||||||
}
|
|
||||||
},
|
|
||||||
State {
|
|
||||||
name: "expanded"
|
|
||||||
PropertyChanges {
|
|
||||||
target: buttonContent
|
|
||||||
y: dragArea.drag.minimumY
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
|
|
||||||
transitions: [
|
|
||||||
Transition {
|
|
||||||
from: "collapsed"
|
|
||||||
to: "expanded"
|
|
||||||
PropertyAnimation {
|
|
||||||
target: buttonContent
|
|
||||||
properties: "y"
|
|
||||||
duration: 200
|
|
||||||
}
|
|
||||||
},
|
|
||||||
Transition {
|
|
||||||
from: "expanded"
|
|
||||||
to: "collapsed"
|
|
||||||
PropertyAnimation {
|
|
||||||
target: buttonContent
|
|
||||||
properties: "y"
|
|
||||||
duration: 200
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
|
|
||||||
DividerType {
|
|
||||||
Layout.topMargin: 10
|
|
||||||
Layout.fillWidth: false
|
|
||||||
Layout.preferredWidth: 20
|
|
||||||
Layout.preferredHeight: 2
|
|
||||||
Layout.alignment: Qt.AlignHCenter | Qt.AlignVCenter
|
|
||||||
|
|
||||||
visible: (buttonContent.collapsedVisibility || buttonContent.expandedVisibility)
|
|
||||||
}
|
|
||||||
|
|
||||||
RowLayout {
|
|
||||||
Layout.topMargin: 14
|
|
||||||
Layout.leftMargin: 24
|
|
||||||
Layout.rightMargin: 24
|
|
||||||
Layout.alignment: Qt.AlignHCenter | Qt.AlignVCenter
|
|
||||||
visible: buttonContent.collapsedVisibility
|
|
||||||
|
|
||||||
spacing: 0
|
|
||||||
|
|
||||||
Header1TextType {
|
|
||||||
id: collapsedButtonHeader
|
|
||||||
Layout.maximumWidth: buttonContent.width - 48 - 18 - 12 // todo
|
|
||||||
|
|
||||||
maximumLineCount: 2
|
|
||||||
elide: Qt.ElideRight
|
|
||||||
|
|
||||||
text: ServersModel.defaultServerName
|
|
||||||
horizontalAlignment: Qt.AlignHCenter
|
|
||||||
|
|
||||||
Behavior on opacity {
|
|
||||||
PropertyAnimation { duration: 200 }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ImageButtonType {
|
|
||||||
id: collapsedButtonChevron
|
|
||||||
|
|
||||||
Layout.leftMargin: 8
|
|
||||||
|
|
||||||
hoverEnabled: false
|
|
||||||
image: "qrc:/images/controls/chevron-down.svg"
|
|
||||||
imageColor: "#d7d8db"
|
|
||||||
|
|
||||||
icon.width: 18
|
|
||||||
icon.height: 18
|
|
||||||
backgroundRadius: 16
|
|
||||||
horizontalPadding: 4
|
|
||||||
topPadding: 4
|
|
||||||
bottomPadding: 3
|
|
||||||
|
|
||||||
onClicked: {
|
|
||||||
if (buttonContent.state === "collapsed") {
|
|
||||||
buttonContent.state = "expanded"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
LabelTextType {
|
|
||||||
id: collapsedServerMenuDescription
|
|
||||||
Layout.bottomMargin: 10
|
|
||||||
Layout.alignment: Qt.AlignHCenter | Qt.AlignVCenter
|
|
||||||
visible: buttonContent.collapsedVisibility
|
|
||||||
text: ServersModel.defaultServerDescriptionCollapsed
|
|
||||||
}
|
|
||||||
|
|
||||||
GraphViewType {
|
|
||||||
id: graph1
|
|
||||||
Layout.preferredHeight: 50
|
|
||||||
Layout.fillWidth: true
|
|
||||||
visible: buttonContent.collapsedVisibility
|
|
||||||
}
|
|
||||||
|
|
||||||
ColumnLayout {
|
|
||||||
id: serversMenuHeader
|
|
||||||
|
|
||||||
Layout.alignment: Qt.AlignTop | Qt.AlignHCenter
|
|
||||||
Layout.fillWidth: true
|
|
||||||
visible: buttonContent.expandedVisibility
|
|
||||||
|
|
||||||
Header1TextType {
|
|
||||||
Layout.fillWidth: true
|
|
||||||
Layout.topMargin: 14
|
|
||||||
Layout.leftMargin: 16
|
|
||||||
Layout.rightMargin: 16
|
|
||||||
|
|
||||||
text: ServersModel.defaultServerName
|
|
||||||
horizontalAlignment: Qt.AlignHCenter
|
|
||||||
maximumLineCount: 2
|
|
||||||
elide: Qt.ElideRight
|
|
||||||
}
|
|
||||||
|
|
||||||
LabelTextType {
|
|
||||||
id: expandedServersMenuDescription
|
|
||||||
Layout.bottomMargin: 24
|
|
||||||
Layout.fillWidth: true
|
|
||||||
horizontalAlignment: Qt.AlignHCenter
|
|
||||||
verticalAlignment: Qt.AlignVCenter
|
|
||||||
text: ServersModel.defaultServerDescriptionExpanded
|
|
||||||
}
|
|
||||||
|
|
||||||
GraphViewType {
|
|
||||||
id: graph2
|
|
||||||
Layout.preferredHeight: 50
|
|
||||||
Layout.fillWidth: true
|
|
||||||
visible: buttonContent.expandedVisibility
|
|
||||||
}
|
}
|
||||||
|
|
||||||
RowLayout {
|
RowLayout {
|
||||||
|
Layout.topMargin: 14
|
||||||
|
Layout.leftMargin: 24
|
||||||
|
Layout.rightMargin: 24
|
||||||
Layout.alignment: Qt.AlignHCenter | Qt.AlignVCenter
|
Layout.alignment: Qt.AlignHCenter | Qt.AlignVCenter
|
||||||
spacing: 8
|
|
||||||
|
|
||||||
DropDownType {
|
spacing: 0
|
||||||
id: containersDropDown
|
|
||||||
|
|
||||||
rootButtonImageColor: "#0E0E11"
|
Connections {
|
||||||
rootButtonBackgroundColor: "#D7D8DB"
|
target: drawer
|
||||||
rootButtonBackgroundHoveredColor: Qt.rgba(215, 216, 219, 0.8)
|
function onEntered() {
|
||||||
rootButtonBackgroundPressedColor: Qt.rgba(215, 216, 219, 0.65)
|
collapsedButtonChevron.backgroundColor = collapsedButtonChevron.hoveredColor
|
||||||
rootButtonHoveredBorderColor: "transparent"
|
collapsedButtonHeader.opacity = 0.8
|
||||||
rootButtonDefaultBorderColor: "transparent"
|
|
||||||
rootButtonTextTopMargin: 8
|
|
||||||
rootButtonTextBottomMargin: 8
|
|
||||||
|
|
||||||
text: ServersModel.defaultContainerName
|
|
||||||
textColor: "#0E0E11"
|
|
||||||
headerText: qsTr("VPN protocol")
|
|
||||||
headerBackButtonImage: "qrc:/images/controls/arrow-left.svg"
|
|
||||||
|
|
||||||
rootButtonClickedFunction: function() {
|
|
||||||
ServersModel.currentlyProcessedIndex = serversMenuContent.currentIndex
|
|
||||||
containersDropDown.menuVisible = true
|
|
||||||
}
|
}
|
||||||
|
|
||||||
listView: HomeContainersListView {
|
function onExited() {
|
||||||
rootWidth: root.width
|
collapsedButtonChevron.backgroundColor = collapsedButtonChevron.defaultColor
|
||||||
|
collapsedButtonHeader.opacity = 1
|
||||||
|
}
|
||||||
|
|
||||||
|
function onPressed(pressed, entered) {
|
||||||
|
collapsedButtonChevron.backgroundColor = pressed ? collapsedButtonChevron.pressedColor : entered ? collapsedButtonChevron.hoveredColor : collapsedButtonChevron.defaultColor
|
||||||
|
collapsedButtonHeader.opacity = 0.7
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Header1TextType {
|
||||||
|
id: collapsedButtonHeader
|
||||||
|
Layout.maximumWidth: drawer.width - 48 - 18 - 12 // todo
|
||||||
|
|
||||||
|
maximumLineCount: 2
|
||||||
|
elide: Qt.ElideRight
|
||||||
|
|
||||||
|
text: ServersModel.defaultServerName
|
||||||
|
horizontalAlignment: Qt.AlignHCenter
|
||||||
|
|
||||||
|
Behavior on opacity {
|
||||||
|
PropertyAnimation { duration: 200 }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ImageButtonType {
|
||||||
|
id: collapsedButtonChevron
|
||||||
|
|
||||||
|
Layout.leftMargin: 8
|
||||||
|
|
||||||
|
hoverEnabled: false
|
||||||
|
image: "qrc:/images/controls/chevron-down.svg"
|
||||||
|
imageColor: "#d7d8db"
|
||||||
|
|
||||||
|
icon.width: 18
|
||||||
|
icon.height: 18
|
||||||
|
backgroundRadius: 16
|
||||||
|
horizontalPadding: 4
|
||||||
|
topPadding: 4
|
||||||
|
bottomPadding: 3
|
||||||
|
|
||||||
|
onClicked: {
|
||||||
|
if (drawer.isCollapsed) {
|
||||||
|
drawer.open()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
LabelTextType {
|
||||||
|
id: collapsedServerMenuDescription
|
||||||
|
Layout.bottomMargin: 10
|
||||||
|
Layout.alignment: Qt.AlignHCenter | Qt.AlignVCenter
|
||||||
|
text: ServersModel.defaultServerDescriptionCollapsed
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
GraphViewType {
|
||||||
|
id: graph1
|
||||||
|
Layout.preferredHeight: 50
|
||||||
|
Layout.fillWidth: true
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
expandedContent: Item {
|
||||||
|
id: serverMenuContainer
|
||||||
|
|
||||||
|
implicitHeight: root.height * 0.9
|
||||||
|
|
||||||
|
Component.onCompleted: {
|
||||||
|
drawer.expandedHeight = serverMenuContainer.implicitHeight
|
||||||
|
}
|
||||||
|
|
||||||
|
ColumnLayout {
|
||||||
|
id: serversMenuHeader
|
||||||
|
|
||||||
|
anchors.top: parent.top
|
||||||
|
anchors.right: parent.right
|
||||||
|
anchors.left: parent.left
|
||||||
|
|
||||||
|
|
||||||
|
Header1TextType {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
Layout.topMargin: 14
|
||||||
|
Layout.leftMargin: 16
|
||||||
|
Layout.rightMargin: 16
|
||||||
|
|
||||||
|
text: ServersModel.defaultServerName
|
||||||
|
horizontalAlignment: Qt.AlignHCenter
|
||||||
|
maximumLineCount: 2
|
||||||
|
elide: Qt.ElideRight
|
||||||
|
}
|
||||||
|
|
||||||
|
LabelTextType {
|
||||||
|
id: expandedServersMenuDescription
|
||||||
|
Layout.bottomMargin: ServersModel.isDefaultServerFromApi ? 69 : 24
|
||||||
|
Layout.fillWidth: true
|
||||||
|
horizontalAlignment: Qt.AlignHCenter
|
||||||
|
verticalAlignment: Qt.AlignVCenter
|
||||||
|
text: ServersModel.defaultServerDescriptionExpanded
|
||||||
|
}
|
||||||
|
|
||||||
|
GraphViewType {
|
||||||
|
id: graph2
|
||||||
|
Layout.preferredHeight: 50
|
||||||
|
Layout.fillWidth: true
|
||||||
|
}
|
||||||
|
|
||||||
|
RowLayout {
|
||||||
|
Layout.alignment: Qt.AlignHCenter | Qt.AlignVCenter
|
||||||
|
spacing: 8
|
||||||
|
|
||||||
|
visible: !ServersModel.isDefaultServerFromApi
|
||||||
|
onVisibleChanged: expandedServersMenuDescription.Layout
|
||||||
|
|
||||||
|
DropDownType {
|
||||||
|
id: containersDropDown
|
||||||
|
|
||||||
|
rootButtonImageColor: "#0E0E11"
|
||||||
|
rootButtonBackgroundColor: "#D7D8DB"
|
||||||
|
rootButtonBackgroundHoveredColor: Qt.rgba(215, 216, 219, 0.8)
|
||||||
|
rootButtonBackgroundPressedColor: Qt.rgba(215, 216, 219, 0.65)
|
||||||
|
rootButtonHoveredBorderColor: "transparent"
|
||||||
|
rootButtonDefaultBorderColor: "transparent"
|
||||||
|
rootButtonTextTopMargin: 8
|
||||||
|
rootButtonTextBottomMargin: 8
|
||||||
|
|
||||||
|
text: ServersModel.defaultServerDefaultContainerName
|
||||||
|
textColor: "#0E0E11"
|
||||||
|
headerText: qsTr("VPN protocol")
|
||||||
|
headerBackButtonImage: "qrc:/images/controls/arrow-left.svg"
|
||||||
|
|
||||||
|
rootButtonClickedFunction: function() {
|
||||||
|
containersDropDown.open()
|
||||||
|
}
|
||||||
|
|
||||||
|
drawerParent: root
|
||||||
|
|
||||||
|
listView: HomeContainersListView {
|
||||||
|
rootWidth: root.width
|
||||||
|
|
||||||
|
Connections {
|
||||||
|
target: ServersModel
|
||||||
|
|
||||||
|
function onDefaultServerIndexChanged() {
|
||||||
|
updateContainersModelFilters()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function updateContainersModelFilters() {
|
||||||
|
if (ServersModel.isDefaultServerHasWriteAccess()) {
|
||||||
|
proxyDefaultServerContainersModel.filters = ContainersModelFilters.getWriteAccessProtocolsListFilters()
|
||||||
|
} else {
|
||||||
|
proxyDefaultServerContainersModel.filters = ContainersModelFilters.getReadAccessProtocolsListFilters()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
model: SortFilterProxyModel {
|
||||||
|
id: proxyDefaultServerContainersModel
|
||||||
|
sourceModel: DefaultServerContainersModel
|
||||||
|
|
||||||
|
sorters: [
|
||||||
|
RoleSorter { roleName: "isInstalled"; sortOrder: Qt.DescendingOrder }
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
Component.onCompleted: updateContainersModelFilters()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Header2Type {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
Layout.topMargin: 48
|
||||||
|
Layout.leftMargin: 16
|
||||||
|
Layout.rightMargin: 16
|
||||||
|
|
||||||
|
headerText: qsTr("Servers")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Flickable {
|
||||||
|
id: serversContainer
|
||||||
|
|
||||||
|
anchors.top: serversMenuHeader.bottom
|
||||||
|
anchors.right: parent.right
|
||||||
|
anchors.left: parent.left
|
||||||
|
anchors.topMargin: 16
|
||||||
|
|
||||||
|
contentHeight: col.height + col.anchors.bottomMargin
|
||||||
|
implicitHeight: parent.height - serversMenuHeader.implicitHeight
|
||||||
|
clip: true
|
||||||
|
|
||||||
|
ScrollBar.vertical: ScrollBar {
|
||||||
|
id: scrollBar
|
||||||
|
policy: serversContainer.height >= serversContainer.contentHeight ? ScrollBar.AlwaysOff : ScrollBar.AlwaysOn
|
||||||
|
}
|
||||||
|
|
||||||
|
Keys.onUpPressed: scrollBar.decrease()
|
||||||
|
Keys.onDownPressed: scrollBar.increase()
|
||||||
|
|
||||||
|
Column {
|
||||||
|
id: col
|
||||||
|
anchors.top: parent.top
|
||||||
|
anchors.left: parent.left
|
||||||
|
anchors.right: parent.right
|
||||||
|
anchors.bottomMargin: 32
|
||||||
|
|
||||||
|
spacing: 16
|
||||||
|
|
||||||
|
ButtonGroup {
|
||||||
|
id: serversRadioButtonGroup
|
||||||
|
}
|
||||||
|
|
||||||
|
ListView {
|
||||||
|
id: serversMenuContent
|
||||||
|
width: parent.width
|
||||||
|
height: serversMenuContent.contentItem.height
|
||||||
|
|
||||||
|
model: ServersModel
|
||||||
|
currentIndex: ServersModel.defaultIndex
|
||||||
|
|
||||||
Connections {
|
Connections {
|
||||||
target: ServersModel
|
target: ServersModel
|
||||||
|
function onDefaultServerIndexChanged(serverIndex) {
|
||||||
function onCurrentlyProcessedServerIndexChanged() {
|
serversMenuContent.currentIndex = serverIndex
|
||||||
updateContainersModelFilters()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function updateContainersModelFilters() {
|
clip: true
|
||||||
if (ServersModel.isCurrentlyProcessedServerHasWriteAccess()) {
|
interactive: false
|
||||||
proxyContainersModel.filters = ContainersModelFilters.getWriteAccessProtocolsListFilters()
|
|
||||||
} else {
|
|
||||||
proxyContainersModel.filters = ContainersModelFilters.getReadAccessProtocolsListFilters()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
model: SortFilterProxyModel {
|
delegate: Item {
|
||||||
id: proxyContainersModel
|
id: menuContentDelegate
|
||||||
sourceModel: ContainersModel
|
|
||||||
}
|
|
||||||
|
|
||||||
Component.onCompleted: updateContainersModelFilters()
|
property variant delegateData: model
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Header2Type {
|
implicitWidth: serversMenuContent.width
|
||||||
Layout.fillWidth: true
|
implicitHeight: serverRadioButtonContent.implicitHeight
|
||||||
Layout.topMargin: 48
|
|
||||||
Layout.leftMargin: 16
|
|
||||||
Layout.rightMargin: 16
|
|
||||||
visible: buttonContent.expandedVisibility
|
|
||||||
|
|
||||||
headerText: qsTr("Servers")
|
ColumnLayout {
|
||||||
}
|
id: serverRadioButtonContent
|
||||||
}
|
|
||||||
|
|
||||||
Flickable {
|
anchors.fill: parent
|
||||||
id: serversContainer
|
anchors.rightMargin: 16
|
||||||
Layout.alignment: Qt.AlignTop | Qt.AlignHCenter
|
anchors.leftMargin: 16
|
||||||
Layout.fillWidth: true
|
|
||||||
Layout.topMargin: 16
|
|
||||||
contentHeight: col.implicitHeight
|
|
||||||
implicitHeight: root.height - (root.height * 0.1) - serversMenuHeader.implicitHeight - 52 //todo 52 is tabbar height
|
|
||||||
visible: buttonContent.expandedVisibility
|
|
||||||
clip: true
|
|
||||||
|
|
||||||
ScrollBar.vertical: ScrollBar {
|
spacing: 0
|
||||||
id: scrollBar
|
|
||||||
policy: serversContainer.height >= serversContainer.contentHeight ? ScrollBar.AlwaysOff : ScrollBar.AlwaysOn
|
|
||||||
}
|
|
||||||
|
|
||||||
Keys.onUpPressed: scrollBar.decrease()
|
RowLayout {
|
||||||
Keys.onDownPressed: scrollBar.increase()
|
VerticalRadioButton {
|
||||||
|
id: serverRadioButton
|
||||||
|
|
||||||
Column {
|
Layout.fillWidth: true
|
||||||
id: col
|
|
||||||
anchors.top: parent.top
|
|
||||||
anchors.left: parent.left
|
|
||||||
anchors.right: parent.right
|
|
||||||
|
|
||||||
spacing: 16
|
text: name
|
||||||
|
descriptionText: serverDescription
|
||||||
|
|
||||||
ButtonGroup {
|
checked: index === serversMenuContent.currentIndex
|
||||||
id: serversRadioButtonGroup
|
checkable: !ConnectionController.isConnected
|
||||||
}
|
|
||||||
|
|
||||||
ListView {
|
ButtonGroup.group: serversRadioButtonGroup
|
||||||
id: serversMenuContent
|
|
||||||
width: parent.width
|
|
||||||
height: serversMenuContent.contentItem.height
|
|
||||||
|
|
||||||
model: ServersModel
|
onClicked: {
|
||||||
currentIndex: ServersModel.defaultIndex
|
if (ConnectionController.isConnected) {
|
||||||
|
PageController.showNotificationMessage(qsTr("Unable change server while there is an active connection"))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
Connections {
|
serversMenuContent.currentIndex = index
|
||||||
target: ServersModel
|
|
||||||
function onDefaultServerIndexChanged(serverIndex) {
|
|
||||||
serversMenuContent.currentIndex = serverIndex
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
clip: true
|
ServersModel.defaultIndex = index
|
||||||
interactive: false
|
}
|
||||||
|
|
||||||
delegate: Item {
|
MouseArea {
|
||||||
id: menuContentDelegate
|
anchors.fill: serverRadioButton
|
||||||
|
cursorShape: Qt.PointingHandCursor
|
||||||
|
enabled: false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
property variant delegateData: model
|
ImageButtonType {
|
||||||
|
image: "qrc:/images/controls/settings.svg"
|
||||||
|
imageColor: "#D7D8DB"
|
||||||
|
|
||||||
implicitWidth: serversMenuContent.width
|
implicitWidth: 56
|
||||||
implicitHeight: serverRadioButtonContent.implicitHeight
|
implicitHeight: 56
|
||||||
|
|
||||||
ColumnLayout {
|
z: 1
|
||||||
id: serverRadioButtonContent
|
|
||||||
|
|
||||||
anchors.fill: parent
|
onClicked: function() {
|
||||||
anchors.rightMargin: 16
|
ServersModel.processedIndex = index
|
||||||
anchors.leftMargin: 16
|
PageController.goToPage(PageEnum.PageSettingsServerInfo)
|
||||||
|
drawer.close()
|
||||||
spacing: 0
|
}
|
||||||
|
}
|
||||||
RowLayout {
|
}
|
||||||
VerticalRadioButton {
|
|
||||||
id: serverRadioButton
|
|
||||||
|
|
||||||
|
DividerType {
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
|
Layout.leftMargin: 0
|
||||||
text: name
|
Layout.rightMargin: 0
|
||||||
descriptionText: {
|
|
||||||
var fullDescription = ""
|
|
||||||
if (hasWriteAccess) {
|
|
||||||
if (SettingsController.isAmneziaDnsEnabled()
|
|
||||||
&& ServersModel.isAmneziaDnsContainerInstalled(index)) {
|
|
||||||
fullDescription += "Amnezia DNS | "
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (containsAmneziaDns) {
|
|
||||||
fullDescription += "Amnezia DNS | "
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return fullDescription += serverDescription
|
|
||||||
}
|
|
||||||
|
|
||||||
checked: index === serversMenuContent.currentIndex
|
|
||||||
checkable: !ConnectionController.isConnected
|
|
||||||
|
|
||||||
ButtonGroup.group: serversRadioButtonGroup
|
|
||||||
|
|
||||||
onClicked: {
|
|
||||||
if (ConnectionController.isConnected) {
|
|
||||||
PageController.showNotificationMessage(qsTr("Unable change server while there is an active connection"))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
serversMenuContent.currentIndex = index
|
|
||||||
|
|
||||||
ServersModel.currentlyProcessedIndex = index
|
|
||||||
ServersModel.defaultIndex = index
|
|
||||||
}
|
|
||||||
|
|
||||||
MouseArea {
|
|
||||||
anchors.fill: serverRadioButton
|
|
||||||
cursorShape: Qt.PointingHandCursor
|
|
||||||
enabled: false
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ImageButtonType {
|
|
||||||
image: "qrc:/images/controls/settings.svg"
|
|
||||||
imageColor: "#D7D8DB"
|
|
||||||
|
|
||||||
implicitWidth: 56
|
|
||||||
implicitHeight: 56
|
|
||||||
|
|
||||||
z: 1
|
|
||||||
|
|
||||||
onClicked: function() {
|
|
||||||
ServersModel.currentlyProcessedIndex = index
|
|
||||||
PageController.goToPage(PageEnum.PageSettingsServerInfo)
|
|
||||||
buttonContent.state = "collapsed"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
DividerType {
|
|
||||||
Layout.fillWidth: true
|
|
||||||
Layout.leftMargin: 0
|
|
||||||
Layout.rightMargin: 0
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,9 +12,12 @@ import "../Controls2/TextTypes"
|
|||||||
import "../Config"
|
import "../Config"
|
||||||
import "../Components"
|
import "../Components"
|
||||||
|
|
||||||
|
|
||||||
PageType {
|
PageType {
|
||||||
id: root
|
id: root
|
||||||
|
|
||||||
|
defaultActiveFocusItem: listview.currentItem.portTextField.textField
|
||||||
|
|
||||||
ColumnLayout {
|
ColumnLayout {
|
||||||
id: backButton
|
id: backButton
|
||||||
|
|
||||||
@@ -41,9 +44,11 @@ PageType {
|
|||||||
anchors.left: parent.left
|
anchors.left: parent.left
|
||||||
anchors.right: parent.right
|
anchors.right: parent.right
|
||||||
|
|
||||||
enabled: ServersModel.isCurrentlyProcessedServerHasWriteAccess()
|
enabled: ServersModel.isProcessedServerHasWriteAccess()
|
||||||
|
|
||||||
ListView {
|
ListView {
|
||||||
|
|
||||||
|
|
||||||
id: listview
|
id: listview
|
||||||
|
|
||||||
width: parent.width
|
width: parent.width
|
||||||
@@ -55,9 +60,13 @@ PageType {
|
|||||||
model: AwgConfigModel
|
model: AwgConfigModel
|
||||||
|
|
||||||
delegate: Item {
|
delegate: Item {
|
||||||
|
id: _delegate
|
||||||
|
|
||||||
implicitWidth: listview.width
|
implicitWidth: listview.width
|
||||||
implicitHeight: col.implicitHeight
|
implicitHeight: col.implicitHeight
|
||||||
|
|
||||||
|
property alias portTextField:portTextField
|
||||||
|
|
||||||
ColumnLayout {
|
ColumnLayout {
|
||||||
id: col
|
id: col
|
||||||
|
|
||||||
@@ -93,6 +102,8 @@ PageType {
|
|||||||
}
|
}
|
||||||
|
|
||||||
checkEmptyText: true
|
checkEmptyText: true
|
||||||
|
|
||||||
|
KeyNavigation.tab: junkPacketCountTextField.textField
|
||||||
}
|
}
|
||||||
|
|
||||||
TextFieldWithHeaderType {
|
TextFieldWithHeaderType {
|
||||||
@@ -116,6 +127,8 @@ PageType {
|
|||||||
}
|
}
|
||||||
|
|
||||||
checkEmptyText: true
|
checkEmptyText: true
|
||||||
|
|
||||||
|
KeyNavigation.tab: junkPacketMinSizeTextField.textField
|
||||||
}
|
}
|
||||||
|
|
||||||
TextFieldWithHeaderType {
|
TextFieldWithHeaderType {
|
||||||
@@ -134,6 +147,8 @@ PageType {
|
|||||||
}
|
}
|
||||||
|
|
||||||
checkEmptyText: true
|
checkEmptyText: true
|
||||||
|
|
||||||
|
KeyNavigation.tab: junkPacketMaxSizeTextField.textField
|
||||||
}
|
}
|
||||||
|
|
||||||
TextFieldWithHeaderType {
|
TextFieldWithHeaderType {
|
||||||
@@ -152,6 +167,8 @@ PageType {
|
|||||||
}
|
}
|
||||||
|
|
||||||
checkEmptyText: true
|
checkEmptyText: true
|
||||||
|
|
||||||
|
KeyNavigation.tab: initPacketJunkSizeTextField.textField
|
||||||
}
|
}
|
||||||
|
|
||||||
TextFieldWithHeaderType {
|
TextFieldWithHeaderType {
|
||||||
@@ -170,6 +187,8 @@ PageType {
|
|||||||
}
|
}
|
||||||
|
|
||||||
checkEmptyText: true
|
checkEmptyText: true
|
||||||
|
|
||||||
|
KeyNavigation.tab: responsePacketJunkSizeTextField.textField
|
||||||
}
|
}
|
||||||
|
|
||||||
TextFieldWithHeaderType {
|
TextFieldWithHeaderType {
|
||||||
@@ -188,6 +207,8 @@ PageType {
|
|||||||
}
|
}
|
||||||
|
|
||||||
checkEmptyText: true
|
checkEmptyText: true
|
||||||
|
|
||||||
|
KeyNavigation.tab: initPacketMagicHeaderTextField.textField
|
||||||
}
|
}
|
||||||
|
|
||||||
TextFieldWithHeaderType {
|
TextFieldWithHeaderType {
|
||||||
@@ -206,6 +227,8 @@ PageType {
|
|||||||
}
|
}
|
||||||
|
|
||||||
checkEmptyText: true
|
checkEmptyText: true
|
||||||
|
|
||||||
|
KeyNavigation.tab: responsePacketMagicHeaderTextField.textField
|
||||||
}
|
}
|
||||||
|
|
||||||
TextFieldWithHeaderType {
|
TextFieldWithHeaderType {
|
||||||
@@ -224,6 +247,8 @@ PageType {
|
|||||||
}
|
}
|
||||||
|
|
||||||
checkEmptyText: true
|
checkEmptyText: true
|
||||||
|
|
||||||
|
KeyNavigation.tab: transportPacketMagicHeaderTextField.textField
|
||||||
}
|
}
|
||||||
|
|
||||||
TextFieldWithHeaderType {
|
TextFieldWithHeaderType {
|
||||||
@@ -242,6 +267,8 @@ PageType {
|
|||||||
}
|
}
|
||||||
|
|
||||||
checkEmptyText: true
|
checkEmptyText: true
|
||||||
|
|
||||||
|
KeyNavigation.tab: underloadPacketMagicHeaderTextField.textField
|
||||||
}
|
}
|
||||||
|
|
||||||
TextFieldWithHeaderType {
|
TextFieldWithHeaderType {
|
||||||
@@ -260,6 +287,8 @@ PageType {
|
|||||||
}
|
}
|
||||||
|
|
||||||
checkEmptyText: true
|
checkEmptyText: true
|
||||||
|
|
||||||
|
KeyNavigation.tab: saveRestartButton
|
||||||
}
|
}
|
||||||
|
|
||||||
BasicButtonType {
|
BasicButtonType {
|
||||||
@@ -275,24 +304,24 @@ PageType {
|
|||||||
text: qsTr("Remove AmneziaWG")
|
text: qsTr("Remove AmneziaWG")
|
||||||
|
|
||||||
onClicked: {
|
onClicked: {
|
||||||
questionDrawer.headerText = qsTr("Remove AmneziaWG from server?")
|
var headerText = qsTr("Remove AmneziaWG from server?")
|
||||||
questionDrawer.descriptionText = qsTr("All users with whom you shared a connection will no longer be able to connect to it.")
|
var descriptionText = qsTr("All users with whom you shared a connection will no longer be able to connect to it.")
|
||||||
questionDrawer.yesButtonText = qsTr("Continue")
|
var yesButtonText = qsTr("Continue")
|
||||||
questionDrawer.noButtonText = qsTr("Cancel")
|
var noButtonText = qsTr("Cancel")
|
||||||
|
|
||||||
questionDrawer.yesButtonFunction = function() {
|
var yesButtonFunction = function() {
|
||||||
questionDrawer.visible = false
|
|
||||||
PageController.goToPage(PageEnum.PageDeinstalling)
|
PageController.goToPage(PageEnum.PageDeinstalling)
|
||||||
InstallController.removeCurrentlyProcessedContainer()
|
InstallController.removeCurrentlyProcessedContainer()
|
||||||
}
|
}
|
||||||
questionDrawer.noButtonFunction = function() {
|
var noButtonFunction = function() {
|
||||||
questionDrawer.visible = false
|
|
||||||
}
|
}
|
||||||
questionDrawer.visible = true
|
showQuestionDrawer(headerText, descriptionText, yesButtonText, noButtonText, yesButtonFunction, noButtonFunction)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
BasicButtonType {
|
BasicButtonType {
|
||||||
|
id: saveRestartButton
|
||||||
|
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
Layout.topMargin: 24
|
Layout.topMargin: 24
|
||||||
Layout.bottomMargin: 24
|
Layout.bottomMargin: 24
|
||||||
@@ -310,7 +339,7 @@ PageType {
|
|||||||
|
|
||||||
text: qsTr("Save and Restart Amnezia")
|
text: qsTr("Save and Restart Amnezia")
|
||||||
|
|
||||||
onClicked: {
|
clickedFunc: function() {
|
||||||
forceActiveFocus()
|
forceActiveFocus()
|
||||||
PageController.goToPage(PageEnum.PageSetupWizardInstalling);
|
PageController.goToPage(PageEnum.PageSetupWizardInstalling);
|
||||||
InstallController.updateContainer(AwgConfigModel.getConfig())
|
InstallController.updateContainer(AwgConfigModel.getConfig())
|
||||||
@@ -318,11 +347,8 @@ PageType {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
QuestionDrawer {
|
}
|
||||||
id: questionDrawer
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,6 +15,8 @@ import "../Components"
|
|||||||
PageType {
|
PageType {
|
||||||
id: root
|
id: root
|
||||||
|
|
||||||
|
defaultActiveFocusItem: listview.currentItem.trafficFromField.textField
|
||||||
|
|
||||||
ColumnLayout {
|
ColumnLayout {
|
||||||
id: backButton
|
id: backButton
|
||||||
|
|
||||||
@@ -41,7 +43,7 @@ PageType {
|
|||||||
anchors.left: parent.left
|
anchors.left: parent.left
|
||||||
anchors.right: parent.right
|
anchors.right: parent.right
|
||||||
|
|
||||||
enabled: ServersModel.isCurrentlyProcessedServerHasWriteAccess()
|
enabled: ServersModel.isProcessedServerHasWriteAccess()
|
||||||
|
|
||||||
ListView {
|
ListView {
|
||||||
id: listview
|
id: listview
|
||||||
@@ -58,6 +60,8 @@ PageType {
|
|||||||
implicitWidth: listview.width
|
implicitWidth: listview.width
|
||||||
implicitHeight: col.implicitHeight
|
implicitHeight: col.implicitHeight
|
||||||
|
|
||||||
|
property alias trafficFromField: trafficFromField
|
||||||
|
|
||||||
ColumnLayout {
|
ColumnLayout {
|
||||||
id: col
|
id: col
|
||||||
|
|
||||||
@@ -77,6 +81,8 @@ PageType {
|
|||||||
}
|
}
|
||||||
|
|
||||||
TextFieldWithHeaderType {
|
TextFieldWithHeaderType {
|
||||||
|
id: trafficFromField
|
||||||
|
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
Layout.topMargin: 32
|
Layout.topMargin: 32
|
||||||
|
|
||||||
@@ -96,9 +102,13 @@ PageType {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
KeyNavigation.tab: portTextField.textField
|
||||||
}
|
}
|
||||||
|
|
||||||
TextFieldWithHeaderType {
|
TextFieldWithHeaderType {
|
||||||
|
id: portTextField
|
||||||
|
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
Layout.topMargin: 16
|
Layout.topMargin: 16
|
||||||
|
|
||||||
@@ -112,6 +122,8 @@ PageType {
|
|||||||
port = textFieldText
|
port = textFieldText
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
KeyNavigation.tab: saveRestartButton
|
||||||
}
|
}
|
||||||
|
|
||||||
DropDownType {
|
DropDownType {
|
||||||
@@ -122,6 +134,8 @@ PageType {
|
|||||||
descriptionText: qsTr("Cipher")
|
descriptionText: qsTr("Cipher")
|
||||||
headerText: qsTr("Cipher")
|
headerText: qsTr("Cipher")
|
||||||
|
|
||||||
|
drawerParent: root
|
||||||
|
|
||||||
listView: ListViewWithRadioButtonType {
|
listView: ListViewWithRadioButtonType {
|
||||||
id: cipherListView
|
id: cipherListView
|
||||||
|
|
||||||
@@ -138,7 +152,7 @@ PageType {
|
|||||||
clickedFunction: function() {
|
clickedFunction: function() {
|
||||||
cipherDropDown.text = selectedText
|
cipherDropDown.text = selectedText
|
||||||
cipher = cipherDropDown.text
|
cipher = cipherDropDown.text
|
||||||
cipherDropDown.menuVisible = false
|
cipherDropDown.close()
|
||||||
}
|
}
|
||||||
|
|
||||||
Component.onCompleted: {
|
Component.onCompleted: {
|
||||||
@@ -154,13 +168,15 @@ PageType {
|
|||||||
}
|
}
|
||||||
|
|
||||||
BasicButtonType {
|
BasicButtonType {
|
||||||
|
id: saveRestartButton
|
||||||
|
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
Layout.topMargin: 24
|
Layout.topMargin: 24
|
||||||
Layout.bottomMargin: 24
|
Layout.bottomMargin: 24
|
||||||
|
|
||||||
text: qsTr("Save and Restart Amnezia")
|
text: qsTr("Save and Restart Amnezia")
|
||||||
|
|
||||||
onClicked: {
|
clickedFunc: function() {
|
||||||
forceActiveFocus()
|
forceActiveFocus()
|
||||||
PageController.goToPage(PageEnum.PageSetupWizardInstalling);
|
PageController.goToPage(PageEnum.PageSetupWizardInstalling);
|
||||||
InstallController.updateContainer(CloakConfigModel.getConfig())
|
InstallController.updateContainer(CloakConfigModel.getConfig())
|
||||||
|
|||||||
@@ -16,6 +16,8 @@ import "../Components"
|
|||||||
PageType {
|
PageType {
|
||||||
id: root
|
id: root
|
||||||
|
|
||||||
|
defaultActiveFocusItem: listview.currentItem.vpnAddressSubnetTextField.textField
|
||||||
|
|
||||||
ColumnLayout {
|
ColumnLayout {
|
||||||
id: backButton
|
id: backButton
|
||||||
|
|
||||||
@@ -42,7 +44,7 @@ PageType {
|
|||||||
anchors.left: parent.left
|
anchors.left: parent.left
|
||||||
anchors.right: parent.right
|
anchors.right: parent.right
|
||||||
|
|
||||||
enabled: ServersModel.isCurrentlyProcessedServerHasWriteAccess()
|
enabled: ServersModel.isProcessedServerHasWriteAccess()
|
||||||
|
|
||||||
ListView {
|
ListView {
|
||||||
id: listview
|
id: listview
|
||||||
@@ -53,12 +55,14 @@ PageType {
|
|||||||
clip: true
|
clip: true
|
||||||
interactive: false
|
interactive: false
|
||||||
|
|
||||||
model: OpenVpnConfigModel
|
model: OpenVpnConfigModel
|
||||||
|
|
||||||
delegate: Item {
|
delegate: Item {
|
||||||
implicitWidth: listview.width
|
implicitWidth: listview.width
|
||||||
implicitHeight: col.implicitHeight
|
implicitHeight: col.implicitHeight
|
||||||
|
|
||||||
|
property alias vpnAddressSubnetTextField: vpnAddressSubnetTextField
|
||||||
|
|
||||||
ColumnLayout {
|
ColumnLayout {
|
||||||
id: col
|
id: col
|
||||||
|
|
||||||
@@ -78,6 +82,8 @@ PageType {
|
|||||||
}
|
}
|
||||||
|
|
||||||
TextFieldWithHeaderType {
|
TextFieldWithHeaderType {
|
||||||
|
id: vpnAddressSubnetTextField
|
||||||
|
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
Layout.topMargin: 32
|
Layout.topMargin: 32
|
||||||
|
|
||||||
@@ -89,6 +95,8 @@ PageType {
|
|||||||
subnetAddress = textFieldText
|
subnetAddress = textFieldText
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
KeyNavigation.tab: portTextField.enabled ? portTextField.textField : saveRestartButton
|
||||||
}
|
}
|
||||||
|
|
||||||
ParagraphTextType {
|
ParagraphTextType {
|
||||||
@@ -119,6 +127,9 @@ PageType {
|
|||||||
}
|
}
|
||||||
|
|
||||||
TextFieldWithHeaderType {
|
TextFieldWithHeaderType {
|
||||||
|
id: portTextField
|
||||||
|
|
||||||
|
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
Layout.topMargin: 40
|
Layout.topMargin: 40
|
||||||
|
|
||||||
@@ -134,6 +145,8 @@ PageType {
|
|||||||
port = textFieldText
|
port = textFieldText
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
KeyNavigation.tab: saveRestartButton
|
||||||
}
|
}
|
||||||
|
|
||||||
SwitcherType {
|
SwitcherType {
|
||||||
@@ -162,6 +175,8 @@ PageType {
|
|||||||
descriptionText: qsTr("Hash")
|
descriptionText: qsTr("Hash")
|
||||||
headerText: qsTr("Hash")
|
headerText: qsTr("Hash")
|
||||||
|
|
||||||
|
drawerParent: root
|
||||||
|
|
||||||
listView: ListViewWithRadioButtonType {
|
listView: ListViewWithRadioButtonType {
|
||||||
id: hashListView
|
id: hashListView
|
||||||
|
|
||||||
@@ -183,7 +198,7 @@ PageType {
|
|||||||
clickedFunction: function() {
|
clickedFunction: function() {
|
||||||
hashDropDown.text = selectedText
|
hashDropDown.text = selectedText
|
||||||
hash = hashDropDown.text
|
hash = hashDropDown.text
|
||||||
hashDropDown.menuVisible = false
|
hashDropDown.close()
|
||||||
}
|
}
|
||||||
|
|
||||||
Component.onCompleted: {
|
Component.onCompleted: {
|
||||||
@@ -208,6 +223,8 @@ PageType {
|
|||||||
descriptionText: qsTr("Cipher")
|
descriptionText: qsTr("Cipher")
|
||||||
headerText: qsTr("Cipher")
|
headerText: qsTr("Cipher")
|
||||||
|
|
||||||
|
drawerParent: root
|
||||||
|
|
||||||
listView: ListViewWithRadioButtonType {
|
listView: ListViewWithRadioButtonType {
|
||||||
id: cipherListView
|
id: cipherListView
|
||||||
|
|
||||||
@@ -229,7 +246,7 @@ PageType {
|
|||||||
clickedFunction: function() {
|
clickedFunction: function() {
|
||||||
cipherDropDown.text = selectedText
|
cipherDropDown.text = selectedText
|
||||||
cipher = cipherDropDown.text
|
cipher = cipherDropDown.text
|
||||||
cipherDropDown.menuVisible = false
|
cipherDropDown.close()
|
||||||
}
|
}
|
||||||
|
|
||||||
Component.onCompleted: {
|
Component.onCompleted: {
|
||||||
@@ -363,32 +380,33 @@ PageType {
|
|||||||
|
|
||||||
text: qsTr("Remove OpenVPN")
|
text: qsTr("Remove OpenVPN")
|
||||||
|
|
||||||
onClicked: {
|
clickedFunc: function() {
|
||||||
questionDrawer.headerText = qsTr("Remove OpenVpn from server?")
|
var headerText = qsTr("Remove OpenVpn from server?")
|
||||||
questionDrawer.descriptionText = qsTr("All users with whom you shared a connection will no longer be able to connect to it.")
|
var descriptionText = qsTr("All users with whom you shared a connection will no longer be able to connect to it.")
|
||||||
questionDrawer.yesButtonText = qsTr("Continue")
|
var yesButtonText = qsTr("Continue")
|
||||||
questionDrawer.noButtonText = qsTr("Cancel")
|
var noButtonText = qsTr("Cancel")
|
||||||
|
|
||||||
questionDrawer.yesButtonFunction = function() {
|
var yesButtonFunction = function() {
|
||||||
questionDrawer.visible = false
|
|
||||||
PageController.goToPage(PageEnum.PageDeinstalling)
|
PageController.goToPage(PageEnum.PageDeinstalling)
|
||||||
InstallController.removeCurrentlyProcessedContainer()
|
InstallController.removeCurrentlyProcessedContainer()
|
||||||
}
|
}
|
||||||
questionDrawer.noButtonFunction = function() {
|
var noButtonFunction = function() {
|
||||||
questionDrawer.visible = false
|
|
||||||
}
|
}
|
||||||
questionDrawer.visible = true
|
|
||||||
|
showQuestionDrawer(headerText, descriptionText, yesButtonText, noButtonText, yesButtonFunction, noButtonFunction)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
BasicButtonType {
|
BasicButtonType {
|
||||||
|
id: saveRestartButton
|
||||||
|
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
Layout.topMargin: 24
|
Layout.topMargin: 24
|
||||||
Layout.bottomMargin: 24
|
Layout.bottomMargin: 24
|
||||||
|
|
||||||
text: qsTr("Save and Restart Amnezia")
|
text: qsTr("Save and Restart Amnezia")
|
||||||
|
|
||||||
onClicked: {
|
clickedFunc: function() {
|
||||||
forceActiveFocus()
|
forceActiveFocus()
|
||||||
PageController.goToPage(PageEnum.PageSetupWizardInstalling);
|
PageController.goToPage(PageEnum.PageSetupWizardInstalling);
|
||||||
InstallController.updateContainer(OpenVpnConfigModel.getConfig())
|
InstallController.updateContainer(OpenVpnConfigModel.getConfig())
|
||||||
@@ -398,9 +416,5 @@ PageType {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
QuestionDrawer {
|
|
||||||
id: questionDrawer
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -90,71 +90,77 @@ PageType {
|
|||||||
|
|
||||||
DividerType {}
|
DividerType {}
|
||||||
|
|
||||||
DrawerType {
|
DrawerType2 {
|
||||||
id: configContentDrawer
|
id: configContentDrawer
|
||||||
|
|
||||||
width: parent.width
|
expandedHeight: root.height * 0.9
|
||||||
height: parent.height * 0.9
|
|
||||||
|
|
||||||
BackButtonType {
|
parent: root
|
||||||
id: backButton
|
anchors.fill: parent
|
||||||
|
|
||||||
anchors.top: parent.top
|
expandedContent: Item {
|
||||||
anchors.left: parent.left
|
implicitHeight: configContentDrawer.expandedHeight
|
||||||
anchors.right: parent.right
|
|
||||||
anchors.topMargin: 16
|
|
||||||
|
|
||||||
backButtonFunction: function() {
|
BackButtonType {
|
||||||
configContentDrawer.visible = false
|
id: backButton
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
FlickableType {
|
anchors.top: parent.top
|
||||||
anchors.top: backButton.bottom
|
anchors.left: parent.left
|
||||||
anchors.left: parent.left
|
anchors.right: parent.right
|
||||||
anchors.right: parent.right
|
anchors.topMargin: 16
|
||||||
anchors.bottom: parent.bottom
|
|
||||||
contentHeight: configContent.implicitHeight + configContent.anchors.topMargin + configContent.anchors.bottomMargin
|
|
||||||
|
|
||||||
ColumnLayout {
|
backButtonFunction: function() {
|
||||||
id: configContent
|
configContentDrawer.close()
|
||||||
|
|
||||||
anchors.fill: parent
|
|
||||||
anchors.rightMargin: 16
|
|
||||||
anchors.leftMargin: 16
|
|
||||||
|
|
||||||
Header2Type {
|
|
||||||
Layout.fillWidth: true
|
|
||||||
Layout.topMargin: 16
|
|
||||||
|
|
||||||
headerText: qsTr("Connection options %1").arg(protocolName)
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
TextArea {
|
FlickableType {
|
||||||
id: configText
|
anchors.top: backButton.bottom
|
||||||
|
anchors.left: parent.left
|
||||||
|
anchors.right: parent.right
|
||||||
|
anchors.bottom: parent.bottom
|
||||||
|
contentHeight: configContent.implicitHeight + configContent.anchors.topMargin + configContent.anchors.bottomMargin
|
||||||
|
|
||||||
Layout.fillWidth: true
|
ColumnLayout {
|
||||||
Layout.topMargin: 16
|
id: configContent
|
||||||
Layout.bottomMargin: 16
|
|
||||||
|
|
||||||
padding: 0
|
anchors.fill: parent
|
||||||
leftPadding: 0
|
anchors.rightMargin: 16
|
||||||
height: 24
|
anchors.leftMargin: 16
|
||||||
|
|
||||||
color: "#D7D8DB"
|
Header2Type {
|
||||||
selectionColor: "#633303"
|
Layout.fillWidth: true
|
||||||
selectedTextColor: "#D7D8DB"
|
Layout.topMargin: 16
|
||||||
|
|
||||||
font.pixelSize: 16
|
headerText: qsTr("Connection options %1").arg(protocolName)
|
||||||
font.weight: Font.Medium
|
}
|
||||||
font.family: "PT Root UI VF"
|
|
||||||
|
|
||||||
text: rawConfig
|
TextArea {
|
||||||
|
id: configText
|
||||||
|
|
||||||
wrapMode: Text.Wrap
|
Layout.fillWidth: true
|
||||||
|
Layout.topMargin: 16
|
||||||
|
Layout.bottomMargin: 16
|
||||||
|
|
||||||
background: Rectangle {
|
padding: 0
|
||||||
color: "transparent"
|
leftPadding: 0
|
||||||
|
height: 24
|
||||||
|
|
||||||
|
color: "#D7D8DB"
|
||||||
|
selectionColor: "#633303"
|
||||||
|
selectedTextColor: "#D7D8DB"
|
||||||
|
|
||||||
|
font.pixelSize: 16
|
||||||
|
font.weight: Font.Medium
|
||||||
|
font.family: "PT Root UI VF"
|
||||||
|
|
||||||
|
text: rawConfig
|
||||||
|
|
||||||
|
wrapMode: Text.Wrap
|
||||||
|
|
||||||
|
background: Rectangle {
|
||||||
|
color: "transparent"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -169,26 +175,25 @@ PageType {
|
|||||||
|
|
||||||
width: parent.width
|
width: parent.width
|
||||||
|
|
||||||
visible: ServersModel.isCurrentlyProcessedServerHasWriteAccess()
|
visible: ServersModel.isProcessedServerHasWriteAccess()
|
||||||
|
|
||||||
text: qsTr("Remove ") + ContainersModel.getCurrentlyProcessedContainerName()
|
text: qsTr("Remove ") + ContainersModel.getCurrentlyProcessedContainerName()
|
||||||
textColor: "#EB5757"
|
textColor: "#EB5757"
|
||||||
|
|
||||||
clickedFunction: function() {
|
clickedFunction: function() {
|
||||||
questionDrawer.headerText = qsTr("Remove %1 from server?").arg(ContainersModel.getCurrentlyProcessedContainerName())
|
var headerText = qsTr("Remove %1 from server?").arg(ContainersModel.getCurrentlyProcessedContainerName())
|
||||||
questionDrawer.descriptionText = qsTr("All users with whom you shared a connection will no longer be able to connect to it.")
|
var descriptionText = qsTr("All users with whom you shared a connection will no longer be able to connect to it.")
|
||||||
questionDrawer.yesButtonText = qsTr("Continue")
|
var yesButtonText = qsTr("Continue")
|
||||||
questionDrawer.noButtonText = qsTr("Cancel")
|
var noButtonText = qsTr("Cancel")
|
||||||
|
|
||||||
questionDrawer.yesButtonFunction = function() {
|
var yesButtonFunction = function() {
|
||||||
questionDrawer.visible = false
|
|
||||||
PageController.goToPage(PageEnum.PageDeinstalling)
|
PageController.goToPage(PageEnum.PageDeinstalling)
|
||||||
InstallController.removeCurrentlyProcessedContainer()
|
InstallController.removeCurrentlyProcessedContainer()
|
||||||
}
|
}
|
||||||
questionDrawer.noButtonFunction = function() {
|
var noButtonFunction = function() {
|
||||||
questionDrawer.visible = false
|
|
||||||
}
|
}
|
||||||
questionDrawer.visible = true
|
|
||||||
|
showQuestionDrawer(headerText, descriptionText, yesButtonText, noButtonText, yesButtonFunction, noButtonFunction)
|
||||||
}
|
}
|
||||||
|
|
||||||
MouseArea {
|
MouseArea {
|
||||||
@@ -200,9 +205,5 @@ PageType {
|
|||||||
|
|
||||||
DividerType {}
|
DividerType {}
|
||||||
}
|
}
|
||||||
|
|
||||||
QuestionDrawer {
|
|
||||||
id: questionDrawer
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,6 +15,8 @@ import "../Components"
|
|||||||
PageType {
|
PageType {
|
||||||
id: root
|
id: root
|
||||||
|
|
||||||
|
defaultActiveFocusItem: listview.currentItem.portTextField.textField
|
||||||
|
|
||||||
ColumnLayout {
|
ColumnLayout {
|
||||||
id: backButton
|
id: backButton
|
||||||
|
|
||||||
@@ -41,7 +43,7 @@ PageType {
|
|||||||
anchors.left: parent.left
|
anchors.left: parent.left
|
||||||
anchors.right: parent.right
|
anchors.right: parent.right
|
||||||
|
|
||||||
enabled: ServersModel.isCurrentlyProcessedServerHasWriteAccess()
|
enabled: ServersModel.isProcessedServerHasWriteAccess()
|
||||||
|
|
||||||
ListView {
|
ListView {
|
||||||
id: listview
|
id: listview
|
||||||
@@ -58,6 +60,8 @@ PageType {
|
|||||||
implicitWidth: listview.width
|
implicitWidth: listview.width
|
||||||
implicitHeight: col.implicitHeight
|
implicitHeight: col.implicitHeight
|
||||||
|
|
||||||
|
property alias portTextField: portTextField
|
||||||
|
|
||||||
ColumnLayout {
|
ColumnLayout {
|
||||||
id: col
|
id: col
|
||||||
|
|
||||||
@@ -77,6 +81,8 @@ PageType {
|
|||||||
}
|
}
|
||||||
|
|
||||||
TextFieldWithHeaderType {
|
TextFieldWithHeaderType {
|
||||||
|
id: portTextField
|
||||||
|
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
Layout.topMargin: 40
|
Layout.topMargin: 40
|
||||||
|
|
||||||
@@ -90,6 +96,8 @@ PageType {
|
|||||||
port = textFieldText
|
port = textFieldText
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
KeyNavigation.tab: saveRestartButton
|
||||||
}
|
}
|
||||||
|
|
||||||
DropDownType {
|
DropDownType {
|
||||||
@@ -100,6 +108,8 @@ PageType {
|
|||||||
descriptionText: qsTr("Cipher")
|
descriptionText: qsTr("Cipher")
|
||||||
headerText: qsTr("Cipher")
|
headerText: qsTr("Cipher")
|
||||||
|
|
||||||
|
drawerParent: root
|
||||||
|
|
||||||
listView: ListViewWithRadioButtonType {
|
listView: ListViewWithRadioButtonType {
|
||||||
id: cipherListView
|
id: cipherListView
|
||||||
|
|
||||||
@@ -116,7 +126,7 @@ PageType {
|
|||||||
clickedFunction: function() {
|
clickedFunction: function() {
|
||||||
cipherDropDown.text = selectedText
|
cipherDropDown.text = selectedText
|
||||||
cipher = cipherDropDown.text
|
cipher = cipherDropDown.text
|
||||||
cipherDropDown.menuVisible = false
|
cipherDropDown.close()
|
||||||
}
|
}
|
||||||
|
|
||||||
Component.onCompleted: {
|
Component.onCompleted: {
|
||||||
@@ -132,13 +142,15 @@ PageType {
|
|||||||
}
|
}
|
||||||
|
|
||||||
BasicButtonType {
|
BasicButtonType {
|
||||||
|
id: saveRestartButton
|
||||||
|
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
Layout.topMargin: 24
|
Layout.topMargin: 24
|
||||||
Layout.bottomMargin: 24
|
Layout.bottomMargin: 24
|
||||||
|
|
||||||
text: qsTr("Save and Restart Amnezia")
|
text: qsTr("Save and Restart Amnezia")
|
||||||
|
|
||||||
onClicked: {
|
clickedFunc: function() {
|
||||||
forceActiveFocus()
|
forceActiveFocus()
|
||||||
PageController.goToPage(PageEnum.PageSetupWizardInstalling);
|
PageController.goToPage(PageEnum.PageSetupWizardInstalling);
|
||||||
InstallController.updateContainer(ShadowSocksConfigModel.getConfig())
|
InstallController.updateContainer(ShadowSocksConfigModel.getConfig())
|
||||||
|
|||||||
@@ -63,19 +63,18 @@ PageType {
|
|||||||
textColor: "#EB5757"
|
textColor: "#EB5757"
|
||||||
|
|
||||||
clickedFunction: function() {
|
clickedFunction: function() {
|
||||||
questionDrawer.headerText = qsTr("Remove %1 from server?").arg(ContainersModel.getCurrentlyProcessedContainerName())
|
var headerText = qsTr("Remove %1 from server?").arg(ContainersModel.getCurrentlyProcessedContainerName())
|
||||||
questionDrawer.yesButtonText = qsTr("Continue")
|
var yesButtonText = qsTr("Continue")
|
||||||
questionDrawer.noButtonText = qsTr("Cancel")
|
var noButtonText = qsTr("Cancel")
|
||||||
|
|
||||||
questionDrawer.yesButtonFunction = function() {
|
var yesButtonFunction = function() {
|
||||||
questionDrawer.visible = false
|
|
||||||
PageController.goToPage(PageEnum.PageDeinstalling)
|
PageController.goToPage(PageEnum.PageDeinstalling)
|
||||||
InstallController.removeCurrentlyProcessedContainer()
|
InstallController.removeCurrentlyProcessedContainer()
|
||||||
}
|
}
|
||||||
questionDrawer.noButtonFunction = function() {
|
var noButtonFunction = function() {
|
||||||
questionDrawer.visible = false
|
|
||||||
}
|
}
|
||||||
questionDrawer.visible = true
|
|
||||||
|
showQuestionDrawer(headerText, "", yesButtonText, noButtonText, yesButtonFunction, noButtonFunction)
|
||||||
}
|
}
|
||||||
|
|
||||||
MouseArea {
|
MouseArea {
|
||||||
@@ -86,10 +85,6 @@ PageType {
|
|||||||
}
|
}
|
||||||
|
|
||||||
DividerType {}
|
DividerType {}
|
||||||
|
|
||||||
QuestionDrawer {
|
|
||||||
id: questionDrawer
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -49,7 +49,7 @@ PageType {
|
|||||||
anchors.left: parent.left
|
anchors.left: parent.left
|
||||||
anchors.right: parent.right
|
anchors.right: parent.right
|
||||||
|
|
||||||
enabled: ServersModel.isCurrentlyProcessedServerHasWriteAccess()
|
enabled: ServersModel.isProcessedServerHasWriteAccess()
|
||||||
|
|
||||||
ListView {
|
ListView {
|
||||||
id: listview
|
id: listview
|
||||||
@@ -88,7 +88,7 @@ PageType {
|
|||||||
Layout.topMargin: 32
|
Layout.topMargin: 32
|
||||||
|
|
||||||
text: qsTr("Host")
|
text: qsTr("Host")
|
||||||
descriptionText: ServersModel.getCurrentlyProcessedServerHostName()
|
descriptionText: ServersModel.getProcessedServerData("HostName")
|
||||||
|
|
||||||
descriptionOnTop: true
|
descriptionOnTop: true
|
||||||
|
|
||||||
@@ -170,7 +170,7 @@ PageType {
|
|||||||
|
|
||||||
text: qsTr("Mount folder on device")
|
text: qsTr("Mount folder on device")
|
||||||
|
|
||||||
onClicked: {
|
clickedFunc: function() {
|
||||||
PageController.showBusyIndicator(true)
|
PageController.showBusyIndicator(true)
|
||||||
InstallController.mountSftpDrive(port, password, username)
|
InstallController.mountSftpDrive(port, password, username)
|
||||||
PageController.showBusyIndicator(false)
|
PageController.showBusyIndicator(false)
|
||||||
@@ -229,7 +229,7 @@ PageType {
|
|||||||
|
|
||||||
text: qsTr("Detailed instructions")
|
text: qsTr("Detailed instructions")
|
||||||
|
|
||||||
onClicked: {
|
clickedFunc: function() {
|
||||||
// Qt.openUrlExternally("https://github.com/amnezia-vpn/desktop-client/releases/latest")
|
// Qt.openUrlExternally("https://github.com/amnezia-vpn/desktop-client/releases/latest")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -247,29 +247,24 @@ PageType {
|
|||||||
|
|
||||||
text: qsTr("Remove SFTP and all data stored there")
|
text: qsTr("Remove SFTP and all data stored there")
|
||||||
|
|
||||||
onClicked: {
|
clickedFunc: function() {
|
||||||
questionDrawer.headerText = qsTr("Remove SFTP and all data stored there?")
|
var headerText = qsTr("Remove SFTP and all data stored there?")
|
||||||
questionDrawer.yesButtonText = qsTr("Continue")
|
var yesButtonText = qsTr("Continue")
|
||||||
questionDrawer.noButtonText = qsTr("Cancel")
|
var noButtonText = qsTr("Cancel")
|
||||||
|
|
||||||
questionDrawer.yesButtonFunction = function() {
|
var yesButtonFunction = function() {
|
||||||
questionDrawer.visible = false
|
|
||||||
PageController.goToPage(PageEnum.PageDeinstalling)
|
PageController.goToPage(PageEnum.PageDeinstalling)
|
||||||
InstallController.removeCurrentlyProcessedContainer()
|
InstallController.removeCurrentlyProcessedContainer()
|
||||||
}
|
}
|
||||||
questionDrawer.noButtonFunction = function() {
|
var noButtonFunction = function() {
|
||||||
questionDrawer.visible = false
|
|
||||||
}
|
}
|
||||||
questionDrawer.visible = true
|
|
||||||
|
showQuestionDrawer(headerText, "", yesButtonText, noButtonText, yesButtonFunction, noButtonFunction)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
QuestionDrawer {
|
|
||||||
id: questionDrawer
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -125,26 +125,21 @@ PageType {
|
|||||||
|
|
||||||
text: qsTr("Remove website")
|
text: qsTr("Remove website")
|
||||||
|
|
||||||
onClicked: {
|
clickedFunc: function() {
|
||||||
questionDrawer.headerText = qsTr("The site with all data will be removed from the tor network.")
|
var headerText = qsTr("The site with all data will be removed from the tor network.")
|
||||||
questionDrawer.yesButtonText = qsTr("Continue")
|
var yesButtonText = qsTr("Continue")
|
||||||
questionDrawer.noButtonText = qsTr("Cancel")
|
var noButtonText = qsTr("Cancel")
|
||||||
|
|
||||||
questionDrawer.yesButtonFunction = function() {
|
var yesButtonFunction = function() {
|
||||||
questionDrawer.visible = false
|
|
||||||
PageController.goToPage(PageEnum.PageDeinstalling)
|
PageController.goToPage(PageEnum.PageDeinstalling)
|
||||||
InstallController.removeCurrentlyProcessedContainer()
|
InstallController.removeCurrentlyProcessedContainer()
|
||||||
}
|
}
|
||||||
questionDrawer.noButtonFunction = function() {
|
var noButtonFunction = function() {
|
||||||
questionDrawer.visible = false
|
|
||||||
}
|
}
|
||||||
questionDrawer.visible = true
|
|
||||||
|
showQuestionDrawer(headerText, "", yesButtonText, noButtonText, yesButtonFunction, noButtonFunction)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
QuestionDrawer {
|
|
||||||
id: questionDrawer
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -81,7 +81,7 @@ PageType {
|
|||||||
|
|
||||||
text: qsTr("Card on Patreon")
|
text: qsTr("Card on Patreon")
|
||||||
|
|
||||||
onClicked: function() {
|
clickedFunc: function() {
|
||||||
Qt.openUrlExternally(qsTr("https://www.patreon.com/amneziavpn"))
|
Qt.openUrlExternally(qsTr("https://www.patreon.com/amneziavpn"))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -101,7 +101,9 @@ PageType {
|
|||||||
|
|
||||||
text: qsTr("Show other methods on Github")
|
text: qsTr("Show other methods on Github")
|
||||||
|
|
||||||
onClicked: Qt.openUrlExternally(qsTr("https://github.com/amnezia-vpn/amnezia-client#donate"))
|
clickedFunc: function() {
|
||||||
|
Qt.openUrlExternally(qsTr("https://github.com/amnezia-vpn/amnezia-client#donate"))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ParagraphTextType {
|
ParagraphTextType {
|
||||||
@@ -173,7 +175,7 @@ PageType {
|
|||||||
|
|
||||||
horizontalAlignment: Text.AlignHCenter
|
horizontalAlignment: Text.AlignHCenter
|
||||||
|
|
||||||
text: SettingsController.getAppVersion()
|
text: qsTr("Software version: %1").arg(SettingsController.getAppVersion())
|
||||||
color: "#878B91"
|
color: "#878B91"
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -191,7 +193,7 @@ PageType {
|
|||||||
|
|
||||||
text: qsTr("Check for updates")
|
text: qsTr("Check for updates")
|
||||||
|
|
||||||
onClicked: {
|
clickedFunc: function() {
|
||||||
Qt.openUrlExternally("https://github.com/amnezia-vpn/desktop-client/releases/latest")
|
Qt.openUrlExternally("https://github.com/amnezia-vpn/desktop-client/releases/latest")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -84,6 +84,27 @@ PageType {
|
|||||||
visible: !GC.isMobile()
|
visible: !GC.isMobile()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SwitcherType {
|
||||||
|
visible: !GC.isMobile()
|
||||||
|
|
||||||
|
Layout.fillWidth: true
|
||||||
|
Layout.margins: 16
|
||||||
|
|
||||||
|
text: qsTr("Auto connect")
|
||||||
|
descriptionText: qsTr("Connect to VPN on app start")
|
||||||
|
|
||||||
|
checked: SettingsController.isAutoConnectEnabled()
|
||||||
|
onCheckedChanged: {
|
||||||
|
if (checked !== SettingsController.isAutoConnectEnabled()) {
|
||||||
|
SettingsController.toggleAutoConnect(checked)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
DividerType {
|
||||||
|
visible: !GC.isMobile()
|
||||||
|
}
|
||||||
|
|
||||||
SwitcherType {
|
SwitcherType {
|
||||||
visible: !GC.isMobile()
|
visible: !GC.isMobile()
|
||||||
|
|
||||||
@@ -117,10 +138,6 @@ PageType {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
SelectLanguageDrawer {
|
|
||||||
id: selectLanguageDrawer
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
DividerType {}
|
DividerType {}
|
||||||
|
|
||||||
@@ -143,30 +160,33 @@ PageType {
|
|||||||
|
|
||||||
text: qsTr("Reset settings and remove all data from the application")
|
text: qsTr("Reset settings and remove all data from the application")
|
||||||
rightImageSource: "qrc:/images/controls/chevron-right.svg"
|
rightImageSource: "qrc:/images/controls/chevron-right.svg"
|
||||||
|
textColor: "#EB5757"
|
||||||
|
|
||||||
clickedFunction: function() {
|
clickedFunction: function() {
|
||||||
questionDrawer.headerText = qsTr("Reset settings and remove all data from the application?")
|
var headerText = qsTr("Reset settings and remove all data from the application?")
|
||||||
questionDrawer.descriptionText = qsTr("All settings will be reset to default. All installed AmneziaVPN services will still remain on the server.")
|
var descriptionText = qsTr("All settings will be reset to default. All installed AmneziaVPN services will still remain on the server.")
|
||||||
questionDrawer.yesButtonText = qsTr("Continue")
|
var yesButtonText = qsTr("Continue")
|
||||||
questionDrawer.noButtonText = qsTr("Cancel")
|
var noButtonText = qsTr("Cancel")
|
||||||
|
|
||||||
questionDrawer.yesButtonFunction = function() {
|
var yesButtonFunction = function() {
|
||||||
questionDrawer.visible = false
|
|
||||||
SettingsController.clearSettings()
|
SettingsController.clearSettings()
|
||||||
PageController.replaceStartPage()
|
PageController.replaceStartPage()
|
||||||
}
|
}
|
||||||
questionDrawer.noButtonFunction = function() {
|
var noButtonFunction = function() {
|
||||||
questionDrawer.visible = false
|
|
||||||
}
|
}
|
||||||
questionDrawer.visible = true
|
|
||||||
|
showQuestionDrawer(headerText, descriptionText, yesButtonText, noButtonText, yesButtonFunction, noButtonFunction)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
DividerType {}
|
DividerType {}
|
||||||
|
|
||||||
QuestionDrawer {
|
|
||||||
id: questionDrawer
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SelectLanguageDrawer {
|
||||||
|
id: selectLanguageDrawer
|
||||||
|
|
||||||
|
width: root.width
|
||||||
|
height: root.height
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -88,7 +88,7 @@ PageType {
|
|||||||
|
|
||||||
text: qsTr("Make a backup")
|
text: qsTr("Make a backup")
|
||||||
|
|
||||||
onClicked: {
|
clickedFunc: function() {
|
||||||
var fileName = ""
|
var fileName = ""
|
||||||
if (GC.isMobile()) {
|
if (GC.isMobile()) {
|
||||||
fileName = "AmneziaVPN.backup"
|
fileName = "AmneziaVPN.backup"
|
||||||
@@ -121,7 +121,7 @@ PageType {
|
|||||||
|
|
||||||
text: qsTr("Restore from backup")
|
text: qsTr("Restore from backup")
|
||||||
|
|
||||||
onClicked: {
|
clickedFunc: function() {
|
||||||
var filePath = SystemController.getFileName(qsTr("Open backup file"),
|
var filePath = SystemController.getFileName(qsTr("Open backup file"),
|
||||||
qsTr("Backup files (*.backup)"))
|
qsTr("Backup files (*.backup)"))
|
||||||
if (filePath !== "") {
|
if (filePath !== "") {
|
||||||
@@ -133,24 +133,19 @@ PageType {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function restoreBackup(filePath) {
|
function restoreBackup(filePath) {
|
||||||
questionDrawer.headerText = qsTr("Import settings from a backup file?")
|
var headerText = qsTr("Import settings from a backup file?")
|
||||||
questionDrawer.descriptionText = qsTr("All current settings will be reset");
|
var descriptionText = qsTr("All current settings will be reset");
|
||||||
questionDrawer.yesButtonText = qsTr("Continue")
|
var yesButtonText = qsTr("Continue")
|
||||||
questionDrawer.noButtonText = qsTr("Cancel")
|
var noButtonText = qsTr("Cancel")
|
||||||
|
|
||||||
questionDrawer.yesButtonFunction = function() {
|
var yesButtonFunction = function() {
|
||||||
questionDrawer.visible = false
|
|
||||||
PageController.showBusyIndicator(true)
|
PageController.showBusyIndicator(true)
|
||||||
SettingsController.restoreAppConfig(filePath)
|
SettingsController.restoreAppConfig(filePath)
|
||||||
PageController.showBusyIndicator(false)
|
PageController.showBusyIndicator(false)
|
||||||
}
|
}
|
||||||
questionDrawer.noButtonFunction = function() {
|
var noButtonFunction = function() {
|
||||||
questionDrawer.visible = false
|
|
||||||
}
|
}
|
||||||
questionDrawer.visible = true
|
|
||||||
}
|
|
||||||
|
|
||||||
QuestionDrawer {
|
showQuestionDrawer(headerText, descriptionText, yesButtonText, noButtonText, yesButtonFunction, noButtonFunction)
|
||||||
id: questionDrawer
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -41,27 +41,6 @@ PageType {
|
|||||||
headerText: qsTr("Connection")
|
headerText: qsTr("Connection")
|
||||||
}
|
}
|
||||||
|
|
||||||
SwitcherType {
|
|
||||||
visible: !GC.isMobile()
|
|
||||||
|
|
||||||
Layout.fillWidth: true
|
|
||||||
Layout.margins: 16
|
|
||||||
|
|
||||||
text: qsTr("Auto connect")
|
|
||||||
descriptionText: qsTr("Connect to VPN on app start")
|
|
||||||
|
|
||||||
checked: SettingsController.isAutoConnectEnabled()
|
|
||||||
onCheckedChanged: {
|
|
||||||
if (checked !== SettingsController.isAutoConnectEnabled()) {
|
|
||||||
SettingsController.toggleAutoConnect(checked)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
DividerType {
|
|
||||||
visible: !GC.isMobile()
|
|
||||||
}
|
|
||||||
|
|
||||||
SwitcherType {
|
SwitcherType {
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
Layout.margins: 16
|
Layout.margins: 16
|
||||||
|
|||||||
@@ -13,6 +13,8 @@ import "../Components"
|
|||||||
PageType {
|
PageType {
|
||||||
id: root
|
id: root
|
||||||
|
|
||||||
|
defaultActiveFocusItem: primaryDns.textField
|
||||||
|
|
||||||
BackButtonType {
|
BackButtonType {
|
||||||
id: backButton
|
id: backButton
|
||||||
|
|
||||||
@@ -28,10 +30,12 @@ PageType {
|
|||||||
anchors.bottom: parent.bottom
|
anchors.bottom: parent.bottom
|
||||||
contentHeight: content.height
|
contentHeight: content.height
|
||||||
|
|
||||||
enabled: !ServersModel.isDefaultServerFromApi()
|
property var isServerFromApi: ServersModel.getDefaultServerData("isServerFromApi")
|
||||||
|
|
||||||
|
enabled: !isServerFromApi
|
||||||
|
|
||||||
Component.onCompleted: {
|
Component.onCompleted: {
|
||||||
if (ServersModel.isDefaultServerFromApi()) {
|
if (isServerFromApi) {
|
||||||
PageController.showNotificationMessage(qsTr("Default server does not support custom dns"))
|
PageController.showNotificationMessage(qsTr("Default server does not support custom dns"))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -68,6 +72,8 @@ PageType {
|
|||||||
textField.validator: RegularExpressionValidator {
|
textField.validator: RegularExpressionValidator {
|
||||||
regularExpression: InstallController.ipAddressRegExp()
|
regularExpression: InstallController.ipAddressRegExp()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
KeyNavigation.tab: secondaryDns.textField
|
||||||
}
|
}
|
||||||
|
|
||||||
TextFieldWithHeaderType {
|
TextFieldWithHeaderType {
|
||||||
@@ -80,6 +86,8 @@ PageType {
|
|||||||
textField.validator: RegularExpressionValidator {
|
textField.validator: RegularExpressionValidator {
|
||||||
regularExpression: InstallController.ipAddressRegExp()
|
regularExpression: InstallController.ipAddressRegExp()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
KeyNavigation.tab: saveButton
|
||||||
}
|
}
|
||||||
|
|
||||||
BasicButtonType {
|
BasicButtonType {
|
||||||
@@ -94,32 +102,33 @@ PageType {
|
|||||||
|
|
||||||
text: qsTr("Restore default")
|
text: qsTr("Restore default")
|
||||||
|
|
||||||
onClicked: function() {
|
clickedFunc: function() {
|
||||||
questionDrawer.headerText = qsTr("Restore default DNS settings?")
|
var headerText = qsTr("Restore default DNS settings?")
|
||||||
questionDrawer.yesButtonText = qsTr("Continue")
|
var yesButtonText = qsTr("Continue")
|
||||||
questionDrawer.noButtonText = qsTr("Cancel")
|
var noButtonText = qsTr("Cancel")
|
||||||
|
|
||||||
questionDrawer.yesButtonFunction = function() {
|
var yesButtonFunction = function() {
|
||||||
questionDrawer.visible = false
|
|
||||||
SettingsController.primaryDns = "1.1.1.1"
|
SettingsController.primaryDns = "1.1.1.1"
|
||||||
primaryDns.textFieldText = SettingsController.primaryDns
|
primaryDns.textFieldText = SettingsController.primaryDns
|
||||||
SettingsController.secondaryDns = "1.0.0.1"
|
SettingsController.secondaryDns = "1.0.0.1"
|
||||||
secondaryDns.textFieldText = SettingsController.secondaryDns
|
secondaryDns.textFieldText = SettingsController.secondaryDns
|
||||||
PageController.showNotificationMessage(qsTr("Settings have been reset"))
|
PageController.showNotificationMessage(qsTr("Settings have been reset"))
|
||||||
}
|
}
|
||||||
questionDrawer.noButtonFunction = function() {
|
var noButtonFunction = function() {
|
||||||
questionDrawer.visible = false
|
|
||||||
}
|
}
|
||||||
questionDrawer.visible = true
|
|
||||||
|
showQuestionDrawer(headerText, "", yesButtonText, noButtonText, yesButtonFunction, noButtonFunction)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
BasicButtonType {
|
BasicButtonType {
|
||||||
|
id: saveButton
|
||||||
|
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
|
|
||||||
text: qsTr("Save")
|
text: qsTr("Save")
|
||||||
|
|
||||||
onClicked: function() {
|
clickedFunc: function() {
|
||||||
if (primaryDns.textFieldText !== SettingsController.primaryDns) {
|
if (primaryDns.textFieldText !== SettingsController.primaryDns) {
|
||||||
SettingsController.primaryDns = primaryDns.textFieldText
|
SettingsController.primaryDns = primaryDns.textFieldText
|
||||||
}
|
}
|
||||||
@@ -130,8 +139,6 @@ PageType {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
QuestionDrawer {
|
|
||||||
id: questionDrawer
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -143,21 +143,20 @@ PageType {
|
|||||||
image: "qrc:/images/controls/delete.svg"
|
image: "qrc:/images/controls/delete.svg"
|
||||||
|
|
||||||
onClicked: function() {
|
onClicked: function() {
|
||||||
questionDrawer.headerText = qsTr("Clear logs?")
|
var headerText = qsTr("Clear logs?")
|
||||||
questionDrawer.yesButtonText = qsTr("Continue")
|
var yesButtonText = qsTr("Continue")
|
||||||
questionDrawer.noButtonText = qsTr("Cancel")
|
var noButtonText = qsTr("Cancel")
|
||||||
|
|
||||||
questionDrawer.yesButtonFunction = function() {
|
var yesButtonFunction = function() {
|
||||||
questionDrawer.visible = false
|
|
||||||
PageController.showBusyIndicator(true)
|
PageController.showBusyIndicator(true)
|
||||||
SettingsController.clearLogs()
|
SettingsController.clearLogs()
|
||||||
PageController.showBusyIndicator(false)
|
PageController.showBusyIndicator(false)
|
||||||
PageController.showNotificationMessage(qsTr("Logs have been cleaned up"))
|
PageController.showNotificationMessage(qsTr("Logs have been cleaned up"))
|
||||||
}
|
}
|
||||||
questionDrawer.noButtonFunction = function() {
|
var noButtonFunction = function() {
|
||||||
questionDrawer.visible = false
|
|
||||||
}
|
}
|
||||||
questionDrawer.visible = true
|
|
||||||
|
showQuestionDrawer(headerText, "", yesButtonText, noButtonText, yesButtonFunction, noButtonFunction)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -170,10 +169,6 @@ PageType {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
QuestionDrawer {
|
|
||||||
id: questionDrawer
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ PageType {
|
|||||||
PageController.showErrorMessage(message)
|
PageController.showErrorMessage(message)
|
||||||
}
|
}
|
||||||
|
|
||||||
function onRemoveCurrentlyProcessedServerFinished(finishedMessage) {
|
function onRemoveProcessedServerFinished(finishedMessage) {
|
||||||
if (!ServersModel.getServersCount()) {
|
if (!ServersModel.getServersCount()) {
|
||||||
PageController.replaceStartPage()
|
PageController.replaceStartPage()
|
||||||
} else {
|
} else {
|
||||||
@@ -38,7 +38,7 @@ PageType {
|
|||||||
PageController.showNotificationMessage(finishedMessage)
|
PageController.showNotificationMessage(finishedMessage)
|
||||||
}
|
}
|
||||||
|
|
||||||
function onRebootCurrentlyProcessedServerFinished(finishedMessage) {
|
function onRebootProcessedServerFinished(finishedMessage) {
|
||||||
PageController.showNotificationMessage(finishedMessage)
|
PageController.showNotificationMessage(finishedMessage)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -64,8 +64,8 @@ PageType {
|
|||||||
Connections {
|
Connections {
|
||||||
target: ServersModel
|
target: ServersModel
|
||||||
|
|
||||||
function onCurrentlyProcessedServerIndexChanged() {
|
function onProcessedServerIndexChanged() {
|
||||||
content.isServerWithWriteAccess = ServersModel.isCurrentlyProcessedServerHasWriteAccess()
|
content.isServerWithWriteAccess = ServersModel.isProcessedServerHasWriteAccess()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -82,7 +82,7 @@ PageType {
|
|||||||
anchors.left: parent.left
|
anchors.left: parent.left
|
||||||
anchors.right: parent.right
|
anchors.right: parent.right
|
||||||
|
|
||||||
property bool isServerWithWriteAccess: ServersModel.isCurrentlyProcessedServerHasWriteAccess()
|
property bool isServerWithWriteAccess: ServersModel.isProcessedServerHasWriteAccess()
|
||||||
|
|
||||||
LabelWithButtonType {
|
LabelWithButtonType {
|
||||||
visible: content.isServerWithWriteAccess
|
visible: content.isServerWithWriteAccess
|
||||||
@@ -92,21 +92,20 @@ PageType {
|
|||||||
descriptionText: qsTr("May be needed when changing other settings")
|
descriptionText: qsTr("May be needed when changing other settings")
|
||||||
|
|
||||||
clickedFunction: function() {
|
clickedFunction: function() {
|
||||||
questionDrawer.headerText = qsTr("Clear cached profiles?")
|
var headerText = qsTr("Clear cached profiles?")
|
||||||
questionDrawer.descriptionText = qsTr("")
|
var descriptionText = qsTr("")
|
||||||
questionDrawer.yesButtonText = qsTr("Continue")
|
var yesButtonText = qsTr("Continue")
|
||||||
questionDrawer.noButtonText = qsTr("Cancel")
|
var noButtonText = qsTr("Cancel")
|
||||||
|
|
||||||
questionDrawer.yesButtonFunction = function() {
|
var yesButtonFunction = function() {
|
||||||
questionDrawer.visible = false
|
|
||||||
PageController.showBusyIndicator(true)
|
PageController.showBusyIndicator(true)
|
||||||
SettingsController.clearCachedProfiles()
|
SettingsController.clearCachedProfiles()
|
||||||
PageController.showBusyIndicator(false)
|
PageController.showBusyIndicator(false)
|
||||||
}
|
}
|
||||||
questionDrawer.noButtonFunction = function() {
|
var noButtonFunction = function() {
|
||||||
questionDrawer.visible = false
|
|
||||||
}
|
}
|
||||||
questionDrawer.visible = true
|
|
||||||
|
showQuestionDrawer(headerText, descriptionText, yesButtonText, noButtonText, yesButtonFunction, noButtonFunction)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -140,24 +139,23 @@ PageType {
|
|||||||
textColor: "#EB5757"
|
textColor: "#EB5757"
|
||||||
|
|
||||||
clickedFunction: function() {
|
clickedFunction: function() {
|
||||||
questionDrawer.headerText = qsTr("Do you want to reboot the server?")
|
var headerText = qsTr("Do you want to reboot the server?")
|
||||||
questionDrawer.descriptionText = qsTr("The reboot process may take approximately 30 seconds. Are you sure you wish to proceed?")
|
var descriptionText = qsTr("The reboot process may take approximately 30 seconds. Are you sure you wish to proceed?")
|
||||||
questionDrawer.yesButtonText = qsTr("Continue")
|
var yesButtonText = qsTr("Continue")
|
||||||
questionDrawer.noButtonText = qsTr("Cancel")
|
var noButtonText = qsTr("Cancel")
|
||||||
|
|
||||||
questionDrawer.yesButtonFunction = function() {
|
var yesButtonFunction = function() {
|
||||||
questionDrawer.visible = false
|
|
||||||
PageController.showBusyIndicator(true)
|
PageController.showBusyIndicator(true)
|
||||||
if (ServersModel.isDefaultServerCurrentlyProcessed() && ConnectionController.isConnected) {
|
if (ServersModel.isDefaultServerCurrentlyProcessed() && ConnectionController.isConnected) {
|
||||||
ConnectionController.closeConnection()
|
ConnectionController.closeConnection()
|
||||||
}
|
}
|
||||||
InstallController.rebootCurrentlyProcessedServer()
|
InstallController.rebootProcessedServer()
|
||||||
PageController.showBusyIndicator(false)
|
PageController.showBusyIndicator(false)
|
||||||
}
|
}
|
||||||
questionDrawer.noButtonFunction = function() {
|
var noButtonFunction = function() {
|
||||||
questionDrawer.visible = false
|
|
||||||
}
|
}
|
||||||
questionDrawer.visible = true
|
|
||||||
|
showQuestionDrawer(headerText, descriptionText, yesButtonText, noButtonText, yesButtonFunction, noButtonFunction)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -172,24 +170,23 @@ PageType {
|
|||||||
textColor: "#EB5757"
|
textColor: "#EB5757"
|
||||||
|
|
||||||
clickedFunction: function() {
|
clickedFunction: function() {
|
||||||
questionDrawer.headerText = qsTr("Do you want to remove the server from application?")
|
var headerText = qsTr("Do you want to remove the server from application?")
|
||||||
questionDrawer.descriptionText = qsTr("All installed AmneziaVPN services will still remain on the server.")
|
var descriptionText = qsTr("All installed AmneziaVPN services will still remain on the server.")
|
||||||
questionDrawer.yesButtonText = qsTr("Continue")
|
var yesButtonText = qsTr("Continue")
|
||||||
questionDrawer.noButtonText = qsTr("Cancel")
|
var noButtonText = qsTr("Cancel")
|
||||||
|
|
||||||
questionDrawer.yesButtonFunction = function() {
|
var yesButtonFunction = function() {
|
||||||
questionDrawer.visible = false
|
|
||||||
PageController.showBusyIndicator(true)
|
PageController.showBusyIndicator(true)
|
||||||
if (ServersModel.isDefaultServerCurrentlyProcessed() && ConnectionController.isConnected) {
|
if (ServersModel.isDefaultServerCurrentlyProcessed() && ConnectionController.isConnected) {
|
||||||
ConnectionController.closeConnection()
|
ConnectionController.closeConnection()
|
||||||
}
|
}
|
||||||
InstallController.removeCurrentlyProcessedServer()
|
InstallController.removeProcessedServer()
|
||||||
PageController.showBusyIndicator(false)
|
PageController.showBusyIndicator(false)
|
||||||
}
|
}
|
||||||
questionDrawer.noButtonFunction = function() {
|
var noButtonFunction = function() {
|
||||||
questionDrawer.visible = false
|
|
||||||
}
|
}
|
||||||
questionDrawer.visible = true
|
|
||||||
|
showQuestionDrawer(headerText, descriptionText, yesButtonText, noButtonText, yesButtonFunction, noButtonFunction)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -203,23 +200,22 @@ PageType {
|
|||||||
textColor: "#EB5757"
|
textColor: "#EB5757"
|
||||||
|
|
||||||
clickedFunction: function() {
|
clickedFunction: function() {
|
||||||
questionDrawer.headerText = qsTr("Do you want to clear server from Amnezia software?")
|
var headerText = qsTr("Do you want to clear server from Amnezia software?")
|
||||||
questionDrawer.descriptionText = qsTr("All containers will be deleted on the server. This means that configuration files, keys and certificates will be deleted.")
|
var descriptionText = qsTr("All containers will be deleted on the server. This means that configuration files, keys and certificates will be deleted.")
|
||||||
questionDrawer.yesButtonText = qsTr("Continue")
|
var yesButtonText = qsTr("Continue")
|
||||||
questionDrawer.noButtonText = qsTr("Cancel")
|
var noButtonText = qsTr("Cancel")
|
||||||
|
|
||||||
questionDrawer.yesButtonFunction = function() {
|
var yesButtonFunction = function() {
|
||||||
questionDrawer.visible = false
|
|
||||||
PageController.goToPage(PageEnum.PageDeinstalling)
|
PageController.goToPage(PageEnum.PageDeinstalling)
|
||||||
if (ServersModel.isDefaultServerCurrentlyProcessed() && ConnectionController.isConnected) {
|
if (ServersModel.isDefaultServerCurrentlyProcessed() && ConnectionController.isConnected) {
|
||||||
ConnectionController.closeConnection()
|
ConnectionController.closeConnection()
|
||||||
}
|
}
|
||||||
InstallController.removeAllContainers()
|
InstallController.removeAllContainers()
|
||||||
}
|
}
|
||||||
questionDrawer.noButtonFunction = function() {
|
var noButtonFunction = function() {
|
||||||
questionDrawer.visible = false
|
|
||||||
}
|
}
|
||||||
questionDrawer.visible = true
|
|
||||||
|
showQuestionDrawer(headerText, descriptionText, yesButtonText, noButtonText, yesButtonFunction, noButtonFunction)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -228,37 +224,32 @@ PageType {
|
|||||||
}
|
}
|
||||||
|
|
||||||
LabelWithButtonType {
|
LabelWithButtonType {
|
||||||
visible: ServersModel.isCurrentlyProcessedServerFromApi()
|
visible: ServersModel.getProcessedServerData("isServerFromApi")
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
|
|
||||||
text: qsTr("Reset API config")
|
text: qsTr("Reset API config")
|
||||||
textColor: "#EB5757"
|
textColor: "#EB5757"
|
||||||
|
|
||||||
clickedFunction: function() {
|
clickedFunction: function() {
|
||||||
questionDrawer.headerText = qsTr("Do you want to reset API config?")
|
var headerText = qsTr("Do you want to reset API config?")
|
||||||
questionDrawer.descriptionText = ""
|
var descriptionText = ""
|
||||||
questionDrawer.yesButtonText = qsTr("Continue")
|
var yesButtonText = qsTr("Continue")
|
||||||
questionDrawer.noButtonText = qsTr("Cancel")
|
var noButtonText = qsTr("Cancel")
|
||||||
|
|
||||||
questionDrawer.yesButtonFunction = function() {
|
var yesButtonFunction = function() {
|
||||||
questionDrawer.visible = false
|
|
||||||
PageController.showBusyIndicator(true)
|
PageController.showBusyIndicator(true)
|
||||||
ApiController.clearApiConfig()
|
ApiController.clearApiConfig()
|
||||||
PageController.showBusyIndicator(false)
|
PageController.showBusyIndicator(false)
|
||||||
}
|
}
|
||||||
questionDrawer.noButtonFunction = function() {
|
var noButtonFunction = function() {
|
||||||
questionDrawer.visible = false
|
|
||||||
}
|
}
|
||||||
questionDrawer.visible = true
|
|
||||||
|
showQuestionDrawer(headerText, descriptionText, yesButtonText, noButtonText, yesButtonFunction, noButtonFunction)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
DividerType {
|
DividerType {
|
||||||
visible: ServersModel.isCurrentlyProcessedServerFromApi()
|
visible: ServersModel.getProcessedServerData("isServerFromApi")
|
||||||
}
|
|
||||||
|
|
||||||
QuestionDrawer {
|
|
||||||
id: questionDrawer
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -63,7 +63,7 @@ PageType {
|
|||||||
|
|
||||||
headerText: name
|
headerText: name
|
||||||
descriptionText: {
|
descriptionText: {
|
||||||
if (ServersModel.isCurrentlyProcessedServerHasWriteAccess()) {
|
if (ServersModel.isProcessedServerHasWriteAccess()) {
|
||||||
return credentialsLogin + " · " + hostName
|
return credentialsLogin + " · " + hostName
|
||||||
} else {
|
} else {
|
||||||
return hostName
|
return hostName
|
||||||
@@ -71,30 +71,33 @@ PageType {
|
|||||||
}
|
}
|
||||||
|
|
||||||
actionButtonFunction: function() {
|
actionButtonFunction: function() {
|
||||||
serverNameEditDrawer.visible = true
|
serverNameEditDrawer.open()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
DrawerType {
|
DrawerType2 {
|
||||||
id: serverNameEditDrawer
|
id: serverNameEditDrawer
|
||||||
|
|
||||||
width: root.width
|
parent: root
|
||||||
height: root.height * 0.35
|
|
||||||
|
|
||||||
onVisibleChanged: {
|
anchors.fill: parent
|
||||||
if (serverNameEditDrawer.visible) {
|
expandedHeight: root.height * 0.35
|
||||||
serverName.textField.forceActiveFocus()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ColumnLayout {
|
expandedContent: ColumnLayout {
|
||||||
anchors.top: parent.top
|
anchors.top: parent.top
|
||||||
anchors.left: parent.left
|
anchors.left: parent.left
|
||||||
anchors.right: parent.right
|
anchors.right: parent.right
|
||||||
anchors.topMargin: 16
|
anchors.topMargin: 32
|
||||||
anchors.leftMargin: 16
|
anchors.leftMargin: 16
|
||||||
anchors.rightMargin: 16
|
anchors.rightMargin: 16
|
||||||
|
|
||||||
|
Connections {
|
||||||
|
target: serverNameEditDrawer
|
||||||
|
function onOpened() {
|
||||||
|
serverName.textField.forceActiveFocus()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
TextFieldWithHeaderType {
|
TextFieldWithHeaderType {
|
||||||
id: serverName
|
id: serverName
|
||||||
|
|
||||||
@@ -103,14 +106,18 @@ PageType {
|
|||||||
textFieldText: name
|
textFieldText: name
|
||||||
textField.maximumLength: 30
|
textField.maximumLength: 30
|
||||||
checkEmptyText: true
|
checkEmptyText: true
|
||||||
|
|
||||||
|
KeyNavigation.tab: saveButton
|
||||||
}
|
}
|
||||||
|
|
||||||
BasicButtonType {
|
BasicButtonType {
|
||||||
|
id: saveButton
|
||||||
|
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
|
|
||||||
text: qsTr("Save")
|
text: qsTr("Save")
|
||||||
|
|
||||||
onClicked: {
|
clickedFunc: function() {
|
||||||
if (serverName.textFieldText === "") {
|
if (serverName.textFieldText === "") {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -118,7 +125,13 @@ PageType {
|
|||||||
if (serverName.textFieldText !== name) {
|
if (serverName.textFieldText !== name) {
|
||||||
name = serverName.textFieldText
|
name = serverName.textFieldText
|
||||||
}
|
}
|
||||||
serverNameEditDrawer.visible = false
|
serverNameEditDrawer.close()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Component.onCompleted: {
|
||||||
|
if (header.itemAt(0)) {
|
||||||
|
defaultActiveFocusItem = serverName.textField
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -107,26 +107,25 @@ PageType {
|
|||||||
|
|
||||||
width: parent.width
|
width: parent.width
|
||||||
|
|
||||||
visible: ServersModel.isCurrentlyProcessedServerHasWriteAccess()
|
visible: ServersModel.isProcessedServerHasWriteAccess()
|
||||||
|
|
||||||
text: qsTr("Remove ") + ContainersModel.getCurrentlyProcessedContainerName()
|
text: qsTr("Remove ") + ContainersModel.getCurrentlyProcessedContainerName()
|
||||||
textColor: "#EB5757"
|
textColor: "#EB5757"
|
||||||
|
|
||||||
clickedFunction: function() {
|
clickedFunction: function() {
|
||||||
questionDrawer.headerText = qsTr("Remove %1 from server?").arg(ContainersModel.getCurrentlyProcessedContainerName())
|
var headerText = qsTr("Remove %1 from server?").arg(ContainersModel.getCurrentlyProcessedContainerName())
|
||||||
questionDrawer.descriptionText = qsTr("All users with whom you shared a connection will no longer be able to connect to it.")
|
var descriptionText = qsTr("All users with whom you shared a connection will no longer be able to connect to it.")
|
||||||
questionDrawer.yesButtonText = qsTr("Continue")
|
var yesButtonText = qsTr("Continue")
|
||||||
questionDrawer.noButtonText = qsTr("Cancel")
|
var noButtonText = qsTr("Cancel")
|
||||||
|
|
||||||
questionDrawer.yesButtonFunction = function() {
|
var yesButtonFunction = function() {
|
||||||
questionDrawer.visible = false
|
|
||||||
PageController.goToPage(PageEnum.PageDeinstalling)
|
PageController.goToPage(PageEnum.PageDeinstalling)
|
||||||
InstallController.removeCurrentlyProcessedContainer()
|
InstallController.removeCurrentlyProcessedContainer()
|
||||||
}
|
}
|
||||||
questionDrawer.noButtonFunction = function() {
|
var noButtonFunction = function() {
|
||||||
questionDrawer.visible = false
|
|
||||||
}
|
}
|
||||||
questionDrawer.visible = true
|
|
||||||
|
showQuestionDrawer(headerText, descriptionText, yesButtonText, noButtonText, yesButtonFunction, noButtonFunction)
|
||||||
}
|
}
|
||||||
|
|
||||||
MouseArea {
|
MouseArea {
|
||||||
@@ -138,9 +137,9 @@ PageType {
|
|||||||
|
|
||||||
DividerType {}
|
DividerType {}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
QuestionDrawer {
|
QuestionDrawer {
|
||||||
id: questionDrawer
|
id: questionDrawer
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -38,13 +38,13 @@ PageType {
|
|||||||
Connections {
|
Connections {
|
||||||
target: ServersModel
|
target: ServersModel
|
||||||
|
|
||||||
function onCurrentlyProcessedServerIndexChanged() {
|
function onProcessedServerIndexChanged() {
|
||||||
settingsContainersListView.updateContainersModelFilters()
|
settingsContainersListView.updateContainersModelFilters()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function updateContainersModelFilters() {
|
function updateContainersModelFilters() {
|
||||||
if (ServersModel.isCurrentlyProcessedServerHasWriteAccess()) {
|
if (ServersModel.isProcessedServerHasWriteAccess()) {
|
||||||
proxyContainersModel.filters = ContainersModelFilters.getWriteAccessProtocolsListFilters()
|
proxyContainersModel.filters = ContainersModelFilters.getWriteAccessProtocolsListFilters()
|
||||||
} else {
|
} else {
|
||||||
proxyContainersModel.filters = ContainersModelFilters.getReadAccessProtocolsListFilters()
|
proxyContainersModel.filters = ContainersModelFilters.getReadAccessProtocolsListFilters()
|
||||||
|
|||||||
@@ -38,13 +38,13 @@ PageType {
|
|||||||
Connections {
|
Connections {
|
||||||
target: ServersModel
|
target: ServersModel
|
||||||
|
|
||||||
function onCurrentlyProcessedServerIndexChanged() {
|
function onProcessedServerIndexChanged() {
|
||||||
settingsContainersListView.updateContainersModelFilters()
|
settingsContainersListView.updateContainersModelFilters()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function updateContainersModelFilters() {
|
function updateContainersModelFilters() {
|
||||||
if (ServersModel.isCurrentlyProcessedServerHasWriteAccess()) {
|
if (ServersModel.isProcessedServerHasWriteAccess()) {
|
||||||
proxyContainersModel.filters = ContainersModelFilters.getWriteAccessServicesListFilters()
|
proxyContainersModel.filters = ContainersModelFilters.getWriteAccessServicesListFilters()
|
||||||
} else {
|
} else {
|
||||||
proxyContainersModel.filters = ContainersModelFilters.getReadAccessServicesListFilters()
|
proxyContainersModel.filters = ContainersModelFilters.getReadAccessServicesListFilters()
|
||||||
@@ -55,6 +55,9 @@ PageType {
|
|||||||
model: SortFilterProxyModel {
|
model: SortFilterProxyModel {
|
||||||
id: proxyContainersModel
|
id: proxyContainersModel
|
||||||
sourceModel: ContainersModel
|
sourceModel: ContainersModel
|
||||||
|
sorters: [
|
||||||
|
RoleSorter { roleName: "isInstalled"; sortOrder: Qt.DescendingOrder }
|
||||||
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
Component.onCompleted: updateContainersModelFilters()
|
Component.onCompleted: updateContainersModelFilters()
|
||||||
|
|||||||
@@ -87,7 +87,7 @@ PageType {
|
|||||||
rightImageSource: "qrc:/images/controls/chevron-right.svg"
|
rightImageSource: "qrc:/images/controls/chevron-right.svg"
|
||||||
|
|
||||||
clickedFunction: function() {
|
clickedFunction: function() {
|
||||||
ServersModel.currentlyProcessedIndex = index
|
ServersModel.processedIndex = index
|
||||||
PageController.goToPage(PageEnum.PageSettingsServerInfo)
|
PageController.goToPage(PageEnum.PageSettingsServerInfo)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,13 +20,23 @@ import "../Components"
|
|||||||
PageType {
|
PageType {
|
||||||
id: root
|
id: root
|
||||||
|
|
||||||
|
property var isServerFromApi: ServersModel.getDefaultServerData("isServerFromApi")
|
||||||
|
|
||||||
|
defaultActiveFocusItem: website_ip_field.textField
|
||||||
|
|
||||||
property bool pageEnabled: {
|
property bool pageEnabled: {
|
||||||
return !ConnectionController.isConnected && !ServersModel.isDefaultServerFromApi()
|
return !ConnectionController.isConnected && !isServerFromApi
|
||||||
}
|
}
|
||||||
|
|
||||||
Component.onCompleted: {
|
Component.onCompleted: {
|
||||||
if (ServersModel.isDefaultServerFromApi()) {
|
if (ConnectionController.isConnected) {
|
||||||
|
PageController.showNotificationMessage(qsTr("Cannot change split tunneling settings during active connection"))
|
||||||
|
root.pageEnabled = false
|
||||||
|
} else if (ServersModel.isDefaultServerDefaultContainerHasSplitTunneling && isServerFromApi) {
|
||||||
PageController.showNotificationMessage(qsTr("Default server does not support split tunneling function"))
|
PageController.showNotificationMessage(qsTr("Default server does not support split tunneling function"))
|
||||||
|
root.pageEnabled = false
|
||||||
|
} else {
|
||||||
|
root.pageEnabled = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -104,7 +114,7 @@ PageType {
|
|||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
Layout.rightMargin: 16
|
Layout.rightMargin: 16
|
||||||
|
|
||||||
checked: SitesModel.isSplitTunnelingEnabled()
|
checked: SitesModel.isTunnelingEnabled
|
||||||
onToggled: {
|
onToggled: {
|
||||||
SitesModel.toggleSplitTunneling(checked)
|
SitesModel.toggleSplitTunneling(checked)
|
||||||
selector.text = root.routeModesModel[getRouteModesModelIndex()].name
|
selector.text = root.routeModesModel[getRouteModesModelIndex()].name
|
||||||
@@ -121,6 +131,7 @@ PageType {
|
|||||||
Layout.rightMargin: 16
|
Layout.rightMargin: 16
|
||||||
|
|
||||||
drawerHeight: 0.4375
|
drawerHeight: 0.4375
|
||||||
|
drawerParent: root
|
||||||
|
|
||||||
enabled: root.pageEnabled
|
enabled: root.pageEnabled
|
||||||
|
|
||||||
@@ -135,7 +146,7 @@ PageType {
|
|||||||
|
|
||||||
clickedFunction: function() {
|
clickedFunction: function() {
|
||||||
selector.text = selectedText
|
selector.text = selectedText
|
||||||
selector.menuVisible = false
|
selector.close()
|
||||||
if (SitesModel.routeMode !== root.routeModesModel[currentIndex].type) {
|
if (SitesModel.routeMode !== root.routeModesModel[currentIndex].type) {
|
||||||
SitesModel.routeMode = root.routeModesModel[currentIndex].type
|
SitesModel.routeMode = root.routeModesModel[currentIndex].type
|
||||||
}
|
}
|
||||||
@@ -202,26 +213,21 @@ PageType {
|
|||||||
rightImageColor: "#D7D8DB"
|
rightImageColor: "#D7D8DB"
|
||||||
|
|
||||||
clickedFunction: function() {
|
clickedFunction: function() {
|
||||||
questionDrawer.headerText = qsTr("Remove ") + url + "?"
|
var headerText = qsTr("Remove ") + url + "?"
|
||||||
questionDrawer.yesButtonText = qsTr("Continue")
|
var yesButtonText = qsTr("Continue")
|
||||||
questionDrawer.noButtonText = qsTr("Cancel")
|
var noButtonText = qsTr("Cancel")
|
||||||
|
|
||||||
questionDrawer.yesButtonFunction = function() {
|
var yesButtonFunction = function() {
|
||||||
questionDrawer.visible = false
|
|
||||||
SitesController.removeSite(index)
|
SitesController.removeSite(index)
|
||||||
}
|
}
|
||||||
questionDrawer.noButtonFunction = function() {
|
var noButtonFunction = function() {
|
||||||
questionDrawer.visible = false
|
|
||||||
}
|
}
|
||||||
questionDrawer.visible = true
|
|
||||||
|
showQuestionDrawer(headerText, "", yesButtonText, noButtonText, yesButtonFunction, noButtonFunction)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
DividerType {}
|
DividerType {}
|
||||||
|
|
||||||
QuestionDrawer {
|
|
||||||
id: questionDrawer
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -249,6 +255,8 @@ PageType {
|
|||||||
anchors.bottomMargin: 24
|
anchors.bottomMargin: 24
|
||||||
|
|
||||||
TextFieldWithHeaderType {
|
TextFieldWithHeaderType {
|
||||||
|
id: website_ip_field
|
||||||
|
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
|
|
||||||
textFieldPlaceholderText: qsTr("website or IP")
|
textFieldPlaceholderText: qsTr("website or IP")
|
||||||
@@ -275,151 +283,155 @@ PageType {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
DrawerType {
|
DrawerType2 {
|
||||||
id: moreActionsDrawer
|
id: moreActionsDrawer
|
||||||
|
|
||||||
width: parent.width
|
anchors.fill: parent
|
||||||
height: parent.height * 0.4375
|
expandedHeight: parent.height * 0.4375
|
||||||
|
|
||||||
FlickableType {
|
expandedContent: ColumnLayout {
|
||||||
anchors.fill: parent
|
id: moreActionsDrawerContent
|
||||||
contentHeight: moreActionsDrawerContent.height
|
|
||||||
ColumnLayout {
|
|
||||||
id: moreActionsDrawerContent
|
|
||||||
|
|
||||||
anchors.top: parent.top
|
|
||||||
anchors.left: parent.left
|
|
||||||
anchors.right: parent.right
|
|
||||||
|
|
||||||
Header2Type {
|
|
||||||
Layout.fillWidth: true
|
|
||||||
Layout.margins: 16
|
|
||||||
|
|
||||||
headerText: qsTr("Import / Export Sites")
|
|
||||||
}
|
|
||||||
|
|
||||||
LabelWithButtonType {
|
|
||||||
Layout.fillWidth: true
|
|
||||||
|
|
||||||
text: qsTr("Import")
|
|
||||||
rightImageSource: "qrc:/images/controls/chevron-right.svg"
|
|
||||||
|
|
||||||
clickedFunction: function() {
|
|
||||||
importSitesDrawer.open()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
DividerType {}
|
|
||||||
|
|
||||||
LabelWithButtonType {
|
|
||||||
Layout.fillWidth: true
|
|
||||||
text: qsTr("Save site list")
|
|
||||||
|
|
||||||
clickedFunction: function() {
|
|
||||||
var fileName = ""
|
|
||||||
if (GC.isMobile()) {
|
|
||||||
fileName = "amnezia_sites.json"
|
|
||||||
} else {
|
|
||||||
fileName = SystemController.getFileName(qsTr("Save sites"),
|
|
||||||
qsTr("Sites files (*.json)"),
|
|
||||||
StandardPaths.standardLocations(StandardPaths.DocumentsLocation) + "/amnezia_sites",
|
|
||||||
true,
|
|
||||||
".json")
|
|
||||||
}
|
|
||||||
if (fileName !== "") {
|
|
||||||
PageController.showBusyIndicator(true)
|
|
||||||
SitesController.exportSites(fileName)
|
|
||||||
moreActionsDrawer.close()
|
|
||||||
PageController.showBusyIndicator(false)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
DividerType {}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
DrawerType {
|
|
||||||
id: importSitesDrawer
|
|
||||||
|
|
||||||
width: parent.width
|
|
||||||
height: parent.height * 0.4375
|
|
||||||
|
|
||||||
BackButtonType {
|
|
||||||
id: importSitesDrawerBackButton
|
|
||||||
|
|
||||||
anchors.top: parent.top
|
anchors.top: parent.top
|
||||||
anchors.left: parent.left
|
anchors.left: parent.left
|
||||||
anchors.right: parent.right
|
anchors.right: parent.right
|
||||||
anchors.topMargin: 16
|
|
||||||
|
|
||||||
backButtonFunction: function() {
|
Header2Type {
|
||||||
importSitesDrawer.close()
|
Layout.fillWidth: true
|
||||||
|
Layout.margins: 16
|
||||||
|
|
||||||
|
headerText: qsTr("Import / Export Sites")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
LabelWithButtonType {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
|
||||||
|
text: qsTr("Import")
|
||||||
|
rightImageSource: "qrc:/images/controls/chevron-right.svg"
|
||||||
|
|
||||||
|
clickedFunction: function() {
|
||||||
|
importSitesDrawer.open()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
DividerType {}
|
||||||
|
|
||||||
|
LabelWithButtonType {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
text: qsTr("Save site list")
|
||||||
|
|
||||||
|
clickedFunction: function() {
|
||||||
|
var fileName = ""
|
||||||
|
if (GC.isMobile()) {
|
||||||
|
fileName = "amnezia_sites.json"
|
||||||
|
} else {
|
||||||
|
fileName = SystemController.getFileName(qsTr("Save sites"),
|
||||||
|
qsTr("Sites files (*.json)"),
|
||||||
|
StandardPaths.standardLocations(StandardPaths.DocumentsLocation) + "/amnezia_sites",
|
||||||
|
true,
|
||||||
|
".json")
|
||||||
|
}
|
||||||
|
if (fileName !== "") {
|
||||||
|
PageController.showBusyIndicator(true)
|
||||||
|
SitesController.exportSites(fileName)
|
||||||
|
moreActionsDrawer.close()
|
||||||
|
PageController.showBusyIndicator(false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
DividerType {}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
FlickableType {
|
DrawerType2 {
|
||||||
anchors.top: importSitesDrawerBackButton.bottom
|
id: importSitesDrawer
|
||||||
anchors.left: parent.left
|
|
||||||
anchors.right: parent.right
|
|
||||||
anchors.bottom: parent.bottom
|
|
||||||
|
|
||||||
contentHeight: importSitesDrawerContent.height
|
anchors.fill: parent
|
||||||
|
expandedHeight: parent.height * 0.4375
|
||||||
|
|
||||||
ColumnLayout {
|
expandedContent: Item {
|
||||||
id: importSitesDrawerContent
|
implicitHeight: importSitesDrawer.expandedHeight
|
||||||
|
|
||||||
|
BackButtonType {
|
||||||
|
id: importSitesDrawerBackButton
|
||||||
|
|
||||||
anchors.top: parent.top
|
anchors.top: parent.top
|
||||||
anchors.left: parent.left
|
anchors.left: parent.left
|
||||||
anchors.right: parent.right
|
anchors.right: parent.right
|
||||||
|
anchors.topMargin: 16
|
||||||
|
|
||||||
Header2Type {
|
backButtonFunction: function() {
|
||||||
Layout.fillWidth: true
|
|
||||||
Layout.margins: 16
|
|
||||||
|
|
||||||
headerText: qsTr("Import a list of sites")
|
|
||||||
}
|
|
||||||
|
|
||||||
LabelWithButtonType {
|
|
||||||
Layout.fillWidth: true
|
|
||||||
|
|
||||||
text: qsTr("Replace site list")
|
|
||||||
|
|
||||||
clickedFunction: function() {
|
|
||||||
var fileName = SystemController.getFileName(qsTr("Open sites file"),
|
|
||||||
qsTr("Sites files (*.json)"))
|
|
||||||
if (fileName !== "") {
|
|
||||||
importSitesDrawerContent.importSites(fileName, true)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
DividerType {}
|
|
||||||
|
|
||||||
LabelWithButtonType {
|
|
||||||
Layout.fillWidth: true
|
|
||||||
text: qsTr("Add imported sites to existing ones")
|
|
||||||
|
|
||||||
clickedFunction: function() {
|
|
||||||
var fileName = SystemController.getFileName(qsTr("Open sites file"),
|
|
||||||
qsTr("Sites files (*.json)"))
|
|
||||||
if (fileName !== "") {
|
|
||||||
importSitesDrawerContent.importSites(fileName, false)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function importSites(fileName, replaceExistingSites) {
|
|
||||||
PageController.showBusyIndicator(true)
|
|
||||||
SitesController.importSites(fileName, replaceExistingSites)
|
|
||||||
PageController.showBusyIndicator(false)
|
|
||||||
importSitesDrawer.close()
|
importSitesDrawer.close()
|
||||||
moreActionsDrawer.close()
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
DividerType {}
|
FlickableType {
|
||||||
|
anchors.top: importSitesDrawerBackButton.bottom
|
||||||
|
anchors.left: parent.left
|
||||||
|
anchors.right: parent.right
|
||||||
|
anchors.bottom: parent.bottom
|
||||||
|
|
||||||
|
contentHeight: importSitesDrawerContent.height
|
||||||
|
|
||||||
|
ColumnLayout {
|
||||||
|
id: importSitesDrawerContent
|
||||||
|
|
||||||
|
anchors.top: parent.top
|
||||||
|
anchors.left: parent.left
|
||||||
|
anchors.right: parent.right
|
||||||
|
|
||||||
|
Header2Type {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
Layout.margins: 16
|
||||||
|
|
||||||
|
headerText: qsTr("Import a list of sites")
|
||||||
|
}
|
||||||
|
|
||||||
|
LabelWithButtonType {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
|
||||||
|
text: qsTr("Replace site list")
|
||||||
|
|
||||||
|
clickedFunction: function() {
|
||||||
|
var fileName = SystemController.getFileName(qsTr("Open sites file"),
|
||||||
|
qsTr("Sites files (*.json)"))
|
||||||
|
if (fileName !== "") {
|
||||||
|
importSitesDrawerContent.importSites(fileName, true)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
DividerType {}
|
||||||
|
|
||||||
|
LabelWithButtonType {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
text: qsTr("Add imported sites to existing ones")
|
||||||
|
|
||||||
|
clickedFunction: function() {
|
||||||
|
var fileName = SystemController.getFileName(qsTr("Open sites file"),
|
||||||
|
qsTr("Sites files (*.json)"))
|
||||||
|
if (fileName !== "") {
|
||||||
|
importSitesDrawerContent.importSites(fileName, false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function importSites(fileName, replaceExistingSites) {
|
||||||
|
PageController.showBusyIndicator(true)
|
||||||
|
SitesController.importSites(fileName, replaceExistingSites)
|
||||||
|
PageController.showBusyIndicator(false)
|
||||||
|
importSitesDrawer.close()
|
||||||
|
moreActionsDrawer.close()
|
||||||
|
}
|
||||||
|
|
||||||
|
DividerType {}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QuestionDrawer {
|
||||||
|
id: questionDrawer
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,6 +12,8 @@ import "../Controls2/TextTypes"
|
|||||||
PageType {
|
PageType {
|
||||||
id: root
|
id: root
|
||||||
|
|
||||||
|
defaultActiveFocusItem: hostname.textField
|
||||||
|
|
||||||
BackButtonType {
|
BackButtonType {
|
||||||
id: backButton
|
id: backButton
|
||||||
|
|
||||||
@@ -57,6 +59,8 @@ PageType {
|
|||||||
onFocusChanged: {
|
onFocusChanged: {
|
||||||
textField.text = textField.text.replace(/^\s+|\s+$/g, '');
|
textField.text = textField.text.replace(/^\s+|\s+$/g, '');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
KeyNavigation.tab: username.textField
|
||||||
}
|
}
|
||||||
|
|
||||||
TextFieldWithHeaderType {
|
TextFieldWithHeaderType {
|
||||||
@@ -65,6 +69,8 @@ PageType {
|
|||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
headerText: qsTr("Login to connect via SSH")
|
headerText: qsTr("Login to connect via SSH")
|
||||||
textFieldPlaceholderText: "root"
|
textFieldPlaceholderText: "root"
|
||||||
|
|
||||||
|
KeyNavigation.tab: secretData.textField
|
||||||
}
|
}
|
||||||
|
|
||||||
TextFieldWithHeaderType {
|
TextFieldWithHeaderType {
|
||||||
@@ -85,15 +91,19 @@ PageType {
|
|||||||
onFocusChanged: {
|
onFocusChanged: {
|
||||||
textField.text = textField.text.replace(/^\s+|\s+$/g, '');
|
textField.text = textField.text.replace(/^\s+|\s+$/g, '');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
KeyNavigation.tab: continueButton
|
||||||
}
|
}
|
||||||
|
|
||||||
BasicButtonType {
|
BasicButtonType {
|
||||||
|
id: continueButton
|
||||||
|
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
Layout.topMargin: 24
|
Layout.topMargin: 24
|
||||||
|
|
||||||
text: qsTr("Continue")
|
text: qsTr("Continue")
|
||||||
|
|
||||||
onClicked: function() {
|
clickedFunc: function() {
|
||||||
forceActiveFocus()
|
forceActiveFocus()
|
||||||
if (!isCredentialsFilled()) {
|
if (!isCredentialsFilled()) {
|
||||||
return
|
return
|
||||||
|
|||||||
@@ -158,7 +158,7 @@ PageType {
|
|||||||
|
|
||||||
text: qsTr("Continue")
|
text: qsTr("Continue")
|
||||||
|
|
||||||
onClicked: function() {
|
clickedFunc: function() {
|
||||||
if (root.isEasySetup) {
|
if (root.isEasySetup) {
|
||||||
ContainersModel.setCurrentlyProcessedContainerIndex(containers.dockerContainer)
|
ContainersModel.setCurrentlyProcessedContainerIndex(containers.dockerContainer)
|
||||||
PageController.goToPage(PageEnum.PageSetupWizardInstalling)
|
PageController.goToPage(PageEnum.PageSetupWizardInstalling)
|
||||||
@@ -192,13 +192,12 @@ PageType {
|
|||||||
return ContainersModel.isAnyContainerInstalled()
|
return ContainersModel.isAnyContainerInstalled()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
text: qsTr("Set up later")
|
text: qsTr("Set up later")
|
||||||
|
|
||||||
onClicked: function() {
|
clickedFunc: function() {
|
||||||
PageController.goToPage(PageEnum.PageSetupWizardInstalling)
|
PageController.goToPage(PageEnum.PageSetupWizardInstalling)
|
||||||
InstallController.addEmptyServer()
|
InstallController.addEmptyServer()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ PageType {
|
|||||||
|
|
||||||
function onInstallContainerFinished(finishedMessage, isServiceInstall) {
|
function onInstallContainerFinished(finishedMessage, isServiceInstall) {
|
||||||
if (!ConnectionController.isConnected && !isServiceInstall) {
|
if (!ConnectionController.isConnected && !isServiceInstall) {
|
||||||
ServersModel.setDefaultContainer(ServersModel.currentlyProcessedIndex, ContainersModel.getCurrentlyProcessedContainerIndex())
|
ServersModel.setDefaultContainer(ServersModel.processedIndex, ContainersModel.getCurrentlyProcessedContainerIndex())
|
||||||
}
|
}
|
||||||
|
|
||||||
PageController.closePage() // close installing page
|
PageController.closePage() // close installing page
|
||||||
@@ -42,7 +42,7 @@ PageType {
|
|||||||
function onInstallServerFinished(finishedMessage) {
|
function onInstallServerFinished(finishedMessage) {
|
||||||
if (!ConnectionController.isConnected) {
|
if (!ConnectionController.isConnected) {
|
||||||
ServersModel.setDefaultServerIndex(ServersModel.getServersCount() - 1);
|
ServersModel.setDefaultServerIndex(ServersModel.getServersCount() - 1);
|
||||||
ServersModel.currentlyProcessedIndex = ServersModel.defaultIndex
|
ServersModel.processedIndex = ServersModel.defaultIndex
|
||||||
}
|
}
|
||||||
|
|
||||||
PageController.goToStartPage()
|
PageController.goToStartPage()
|
||||||
@@ -55,7 +55,7 @@ PageType {
|
|||||||
|
|
||||||
function onServerAlreadyExists(serverIndex) {
|
function onServerAlreadyExists(serverIndex) {
|
||||||
PageController.goToStartPage()
|
PageController.goToStartPage()
|
||||||
ServersModel.currentlyProcessedIndex = serverIndex
|
ServersModel.processedIndex = serverIndex
|
||||||
PageController.goToPage(PageEnum.PageSettingsServerInfo, false)
|
PageController.goToPage(PageEnum.PageSettingsServerInfo, false)
|
||||||
|
|
||||||
PageController.showErrorMessage(qsTr("The server has already been added to the application"))
|
PageController.showErrorMessage(qsTr("The server has already been added to the application"))
|
||||||
@@ -165,7 +165,7 @@ PageType {
|
|||||||
|
|
||||||
text: qsTr("Cancel installation")
|
text: qsTr("Cancel installation")
|
||||||
|
|
||||||
onClicked: {
|
clickedFunc: function() {
|
||||||
InstallController.cancelInstallation()
|
InstallController.cancelInstallation()
|
||||||
PageController.showBusyIndicator(true)
|
PageController.showBusyIndicator(true)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -52,6 +52,8 @@ PageType {
|
|||||||
implicitWidth: processedContainerListView.width
|
implicitWidth: processedContainerListView.width
|
||||||
implicitHeight: (delegateContent.implicitHeight > root.height) ? delegateContent.implicitHeight : root.height
|
implicitHeight: (delegateContent.implicitHeight > root.height) ? delegateContent.implicitHeight : root.height
|
||||||
|
|
||||||
|
property alias port:port
|
||||||
|
|
||||||
ColumnLayout {
|
ColumnLayout {
|
||||||
id: delegateContent
|
id: delegateContent
|
||||||
|
|
||||||
@@ -92,81 +94,85 @@ PageType {
|
|||||||
|
|
||||||
text: qsTr("More detailed")
|
text: qsTr("More detailed")
|
||||||
|
|
||||||
onClicked: {
|
clickedFunc: function() {
|
||||||
showDetailsDrawer.open()
|
showDetailsDrawer.open()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
DrawerType {
|
DrawerType2 {
|
||||||
id: showDetailsDrawer
|
id: showDetailsDrawer
|
||||||
|
parent: root
|
||||||
|
|
||||||
width: parent.width
|
anchors.fill: parent
|
||||||
height: parent.height * 0.9
|
expandedHeight: parent.height * 0.9
|
||||||
|
expandedContent: Item {
|
||||||
|
implicitHeight: showDetailsDrawer.expandedHeight
|
||||||
|
|
||||||
BackButtonType {
|
BackButtonType {
|
||||||
id: showDetailsBackButton
|
id: showDetailsBackButton
|
||||||
|
|
||||||
anchors.top: parent.top
|
|
||||||
anchors.left: parent.left
|
|
||||||
anchors.right: parent.right
|
|
||||||
anchors.topMargin: 16
|
|
||||||
|
|
||||||
backButtonFunction: function() {
|
|
||||||
showDetailsDrawer.close()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
FlickableType {
|
|
||||||
anchors.top: showDetailsBackButton.bottom
|
|
||||||
anchors.left: parent.left
|
|
||||||
anchors.right: parent.right
|
|
||||||
anchors.bottom: parent.bottom
|
|
||||||
contentHeight: {
|
|
||||||
var emptySpaceHeight = parent.height - showDetailsBackButton.implicitHeight - showDetailsBackButton.anchors.topMargin
|
|
||||||
return (showDetailsDrawerContent.height > emptySpaceHeight) ?
|
|
||||||
showDetailsDrawerContent.height : emptySpaceHeight
|
|
||||||
}
|
|
||||||
|
|
||||||
ColumnLayout {
|
|
||||||
id: showDetailsDrawerContent
|
|
||||||
|
|
||||||
anchors.top: parent.top
|
anchors.top: parent.top
|
||||||
anchors.left: parent.left
|
anchors.left: parent.left
|
||||||
anchors.right: parent.right
|
anchors.right: parent.right
|
||||||
anchors.rightMargin: 16
|
anchors.topMargin: 16
|
||||||
anchors.leftMargin: 16
|
|
||||||
|
|
||||||
Header2Type {
|
backButtonFunction: function() {
|
||||||
id: showDetailsDrawerHeader
|
showDetailsDrawer.close()
|
||||||
Layout.fillWidth: true
|
}
|
||||||
Layout.topMargin: 16
|
}
|
||||||
|
|
||||||
headerText: name
|
FlickableType {
|
||||||
|
anchors.top: showDetailsBackButton.bottom
|
||||||
|
anchors.left: parent.left
|
||||||
|
anchors.right: parent.right
|
||||||
|
anchors.bottom: parent.bottom
|
||||||
|
contentHeight: {
|
||||||
|
var emptySpaceHeight = parent.height - showDetailsBackButton.implicitHeight - showDetailsBackButton.anchors.topMargin
|
||||||
|
return (showDetailsDrawerContent.height > emptySpaceHeight) ?
|
||||||
|
showDetailsDrawerContent.height : emptySpaceHeight
|
||||||
}
|
}
|
||||||
|
|
||||||
ParagraphTextType {
|
ColumnLayout {
|
||||||
Layout.fillWidth: true
|
id: showDetailsDrawerContent
|
||||||
Layout.topMargin: 16
|
|
||||||
Layout.bottomMargin: 16
|
|
||||||
|
|
||||||
text: detailedDescription
|
anchors.top: parent.top
|
||||||
textFormat: Text.MarkdownText
|
anchors.left: parent.left
|
||||||
}
|
anchors.right: parent.right
|
||||||
|
anchors.rightMargin: 16
|
||||||
|
anchors.leftMargin: 16
|
||||||
|
|
||||||
|
Header2Type {
|
||||||
|
id: showDetailsDrawerHeader
|
||||||
|
Layout.fillWidth: true
|
||||||
|
Layout.topMargin: 16
|
||||||
|
|
||||||
|
headerText: name
|
||||||
|
}
|
||||||
|
|
||||||
|
ParagraphTextType {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
Layout.topMargin: 16
|
||||||
|
Layout.bottomMargin: 16
|
||||||
|
|
||||||
|
text: detailedDescription
|
||||||
|
textFormat: Text.MarkdownText
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
Rectangle {
|
Rectangle {
|
||||||
Layout.fillHeight: true
|
Layout.fillHeight: true
|
||||||
color: "transparent"
|
color: "transparent"
|
||||||
}
|
}
|
||||||
|
|
||||||
BasicButtonType {
|
BasicButtonType {
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
Layout.bottomMargin: 32
|
Layout.bottomMargin: 32
|
||||||
|
|
||||||
text: qsTr("Close")
|
text: qsTr("Close")
|
||||||
|
|
||||||
onClicked: function() {
|
clickedFunc: function() {
|
||||||
showDetailsDrawer.close()
|
showDetailsDrawer.close()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -197,6 +203,8 @@ PageType {
|
|||||||
headerText: qsTr("Port")
|
headerText: qsTr("Port")
|
||||||
textField.maximumLength: 5
|
textField.maximumLength: 5
|
||||||
textField.validator: IntValidator { bottom: 1; top: 65535 }
|
textField.validator: IntValidator { bottom: 1; top: 65535 }
|
||||||
|
|
||||||
|
KeyNavigation.tab: installButton
|
||||||
}
|
}
|
||||||
|
|
||||||
Rectangle {
|
Rectangle {
|
||||||
@@ -212,7 +220,7 @@ PageType {
|
|||||||
|
|
||||||
text: qsTr("Install")
|
text: qsTr("Install")
|
||||||
|
|
||||||
onClicked: function() {
|
clickedFunc: function() {
|
||||||
PageController.goToPage(PageEnum.PageSetupWizardInstalling);
|
PageController.goToPage(PageEnum.PageSetupWizardInstalling);
|
||||||
InstallController.install(dockerContainer, port.textFieldText, transportProtoSelector.currentIndex)
|
InstallController.install(dockerContainer, port.textFieldText, transportProtoSelector.currentIndex)
|
||||||
}
|
}
|
||||||
@@ -232,6 +240,8 @@ PageType {
|
|||||||
var protocolSelectorVisible = ProtocolProps.defaultTransportProtoChangeable(defaultContainerProto)
|
var protocolSelectorVisible = ProtocolProps.defaultTransportProtoChangeable(defaultContainerProto)
|
||||||
transportProtoSelector.visible = protocolSelectorVisible
|
transportProtoSelector.visible = protocolSelectorVisible
|
||||||
transportProtoHeader.visible = protocolSelectorVisible
|
transportProtoHeader.visible = protocolSelectorVisible
|
||||||
|
|
||||||
|
defaultActiveFocusItem = port.textField
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -115,8 +115,8 @@ PageType {
|
|||||||
|
|
||||||
text: qsTr("I have the data to connect")
|
text: qsTr("I have the data to connect")
|
||||||
|
|
||||||
onClicked: {
|
clickedFunc: function() {
|
||||||
connectionTypeSelection.visible = true
|
connectionTypeSelection.open()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -135,13 +135,15 @@ PageType {
|
|||||||
|
|
||||||
text: qsTr("I have nothing")
|
text: qsTr("I have nothing")
|
||||||
|
|
||||||
onClicked: Qt.openUrlExternally(qsTr("https://amnezia.org/instructions/0_starter-guide"))
|
clickedFunc: function() {
|
||||||
|
Qt.openUrlExternally(qsTr("https://amnezia.org/instructions/0_starter-guide"))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
ConnectionTypeSelectionDrawer {
|
ConnectionTypeSelectionDrawer {
|
||||||
id: connectionTypeSelection
|
id: connectionTypeSelection
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
BusyIndicatorType {
|
BusyIndicatorType {
|
||||||
|
|||||||
@@ -12,6 +12,8 @@ import "../Config"
|
|||||||
PageType {
|
PageType {
|
||||||
id: root
|
id: root
|
||||||
|
|
||||||
|
defaultActiveFocusItem: textKey.textField
|
||||||
|
|
||||||
FlickableType {
|
FlickableType {
|
||||||
id: fl
|
id: fl
|
||||||
anchors.top: parent.top
|
anchors.top: parent.top
|
||||||
@@ -56,11 +58,15 @@ PageType {
|
|||||||
textField.text = ""
|
textField.text = ""
|
||||||
textField.paste()
|
textField.paste()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
KeyNavigation.tab: continueButton
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
BasicButtonType {
|
BasicButtonType {
|
||||||
|
id: continueButton
|
||||||
|
|
||||||
anchors.bottom: parent.bottom
|
anchors.bottom: parent.bottom
|
||||||
anchors.left: parent.left
|
anchors.left: parent.left
|
||||||
anchors.right: parent.right
|
anchors.right: parent.right
|
||||||
@@ -70,7 +76,7 @@ PageType {
|
|||||||
|
|
||||||
text: qsTr("Continue")
|
text: qsTr("Continue")
|
||||||
|
|
||||||
onClicked: function() {
|
clickedFunc: function() {
|
||||||
ImportController.extractConfigFromCode(textKey.textFieldText)
|
ImportController.extractConfigFromCode(textKey.textFieldText)
|
||||||
PageController.goToPage(PageEnum.PageSetupWizardViewConfig)
|
PageController.goToPage(PageEnum.PageSetupWizardViewConfig)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ PageType {
|
|||||||
function onImportFinished() {
|
function onImportFinished() {
|
||||||
if (!ConnectionController.isConnected) {
|
if (!ConnectionController.isConnected) {
|
||||||
ServersModel.setDefaultServerIndex(ServersModel.getServersCount() - 1);
|
ServersModel.setDefaultServerIndex(ServersModel.getServersCount() - 1);
|
||||||
ServersModel.currentlyProcessedIndex = ServersModel.defaultIndex
|
ServersModel.processedIndex = ServersModel.defaultIndex
|
||||||
}
|
}
|
||||||
|
|
||||||
PageController.goToStartPage()
|
PageController.goToStartPage()
|
||||||
@@ -109,7 +109,7 @@ PageType {
|
|||||||
|
|
||||||
text: showContent ? qsTr("Collapse content") : qsTr("Show content")
|
text: showContent ? qsTr("Collapse content") : qsTr("Show content")
|
||||||
|
|
||||||
onClicked: {
|
clickedFunc: function() {
|
||||||
showContent = !showContent
|
showContent = !showContent
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -151,7 +151,7 @@ PageType {
|
|||||||
Layout.bottomMargin: 32
|
Layout.bottomMargin: 32
|
||||||
|
|
||||||
text: qsTr("Connect")
|
text: qsTr("Connect")
|
||||||
onClicked: {
|
clickedFunc: function() {
|
||||||
ImportController.importConfig()
|
ImportController.importConfig()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,6 +16,8 @@ import "../Components"
|
|||||||
PageType {
|
PageType {
|
||||||
id: root
|
id: root
|
||||||
|
|
||||||
|
defaultActiveFocusItem: clientNameTextField.textField
|
||||||
|
|
||||||
enum ConfigType {
|
enum ConfigType {
|
||||||
AmneziaConnection,
|
AmneziaConnection,
|
||||||
OpenVpn,
|
OpenVpn,
|
||||||
@@ -29,7 +31,7 @@ PageType {
|
|||||||
PageController.showBusyIndicator(true)
|
PageController.showBusyIndicator(true)
|
||||||
ExportController.revokeConfig(index,
|
ExportController.revokeConfig(index,
|
||||||
ContainersModel.getCurrentlyProcessedContainerIndex(),
|
ContainersModel.getCurrentlyProcessedContainerIndex(),
|
||||||
ServersModel.getCurrentlyProcessedServerCredentials())
|
ServersModel.getProcessedServerCredentials())
|
||||||
PageController.showBusyIndicator(false)
|
PageController.showBusyIndicator(false)
|
||||||
PageController.showNotificationMessage(qsTr("Config revoked"))
|
PageController.showNotificationMessage(qsTr("Config revoked"))
|
||||||
}
|
}
|
||||||
@@ -41,8 +43,6 @@ PageType {
|
|||||||
shareConnectionDrawer.headerText = qsTr("Connection to ") + serverSelector.text
|
shareConnectionDrawer.headerText = qsTr("Connection to ") + serverSelector.text
|
||||||
shareConnectionDrawer.configContentHeaderText = qsTr("File with connection settings to ") + serverSelector.text
|
shareConnectionDrawer.configContentHeaderText = qsTr("File with connection settings to ") + serverSelector.text
|
||||||
|
|
||||||
shareConnectionDrawer.needCloseButton = false
|
|
||||||
|
|
||||||
shareConnectionDrawer.open()
|
shareConnectionDrawer.open()
|
||||||
shareConnectionDrawer.contentVisible = false
|
shareConnectionDrawer.contentVisible = false
|
||||||
PageController.showBusyIndicator(true)
|
PageController.showBusyIndicator(true)
|
||||||
@@ -80,11 +80,6 @@ PageType {
|
|||||||
}
|
}
|
||||||
|
|
||||||
PageController.showBusyIndicator(false)
|
PageController.showBusyIndicator(false)
|
||||||
|
|
||||||
shareConnectionDrawer.needCloseButton = true
|
|
||||||
PageController.showTopCloseButton(true)
|
|
||||||
|
|
||||||
shareConnectionDrawer.contentVisible = true
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function onExportErrorOccurred(errorMessage) {
|
function onExportErrorOccurred(errorMessage) {
|
||||||
@@ -129,7 +124,7 @@ PageType {
|
|||||||
FlickableType {
|
FlickableType {
|
||||||
anchors.top: parent.top
|
anchors.top: parent.top
|
||||||
anchors.bottom: parent.bottom
|
anchors.bottom: parent.bottom
|
||||||
contentHeight: content.height
|
contentHeight: content.height + 10
|
||||||
|
|
||||||
ColumnLayout {
|
ColumnLayout {
|
||||||
id: content
|
id: content
|
||||||
@@ -154,14 +149,15 @@ PageType {
|
|||||||
shareFullAccessDrawer.open()
|
shareFullAccessDrawer.open()
|
||||||
}
|
}
|
||||||
|
|
||||||
DrawerType {
|
DrawerType2 {
|
||||||
id: shareFullAccessDrawer
|
id: shareFullAccessDrawer
|
||||||
|
|
||||||
width: root.width
|
parent: root
|
||||||
height: root.height * 0.45
|
|
||||||
|
|
||||||
|
anchors.fill: parent
|
||||||
|
expandedHeight: root.height * 0.45
|
||||||
|
|
||||||
ColumnLayout {
|
expandedContent: ColumnLayout {
|
||||||
anchors.top: parent.top
|
anchors.top: parent.top
|
||||||
anchors.left: parent.left
|
anchors.left: parent.left
|
||||||
anchors.right: parent.right
|
anchors.right: parent.right
|
||||||
@@ -234,7 +230,7 @@ PageType {
|
|||||||
accessTypeSelector.currentIndex = 1
|
accessTypeSelector.currentIndex = 1
|
||||||
PageController.showBusyIndicator(true)
|
PageController.showBusyIndicator(true)
|
||||||
ExportController.updateClientManagementModel(ContainersModel.getCurrentlyProcessedContainerIndex(),
|
ExportController.updateClientManagementModel(ContainersModel.getCurrentlyProcessedContainerIndex(),
|
||||||
ServersModel.getCurrentlyProcessedServerCredentials())
|
ServersModel.getProcessedServerCredentials())
|
||||||
PageController.showBusyIndicator(false)
|
PageController.showBusyIndicator(false)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -264,6 +260,8 @@ PageType {
|
|||||||
textField.maximumLength: 20
|
textField.maximumLength: 20
|
||||||
|
|
||||||
checkEmptyText: true
|
checkEmptyText: true
|
||||||
|
|
||||||
|
KeyNavigation.tab: shareButton
|
||||||
}
|
}
|
||||||
|
|
||||||
DropDownType {
|
DropDownType {
|
||||||
@@ -276,6 +274,7 @@ PageType {
|
|||||||
Layout.topMargin: 16
|
Layout.topMargin: 16
|
||||||
|
|
||||||
drawerHeight: 0.4375
|
drawerHeight: 0.4375
|
||||||
|
drawerParent: root
|
||||||
|
|
||||||
descriptionText: qsTr("Server")
|
descriptionText: qsTr("Server")
|
||||||
headerText: qsTr("Server")
|
headerText: qsTr("Server")
|
||||||
@@ -305,7 +304,7 @@ PageType {
|
|||||||
serverSelector.severSelectorIndexChanged()
|
serverSelector.severSelectorIndexChanged()
|
||||||
}
|
}
|
||||||
|
|
||||||
serverSelector.menuVisible = false
|
serverSelector.close()
|
||||||
}
|
}
|
||||||
|
|
||||||
Component.onCompleted: {
|
Component.onCompleted: {
|
||||||
@@ -316,7 +315,7 @@ PageType {
|
|||||||
|
|
||||||
function handler() {
|
function handler() {
|
||||||
serverSelector.text = selectedText
|
serverSelector.text = selectedText
|
||||||
ServersModel.currentlyProcessedIndex = proxyServersModel.mapToSource(currentIndex)
|
ServersModel.processedIndex = proxyServersModel.mapToSource(currentIndex)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -328,6 +327,7 @@ PageType {
|
|||||||
Layout.topMargin: 16
|
Layout.topMargin: 16
|
||||||
|
|
||||||
drawerHeight: 0.5
|
drawerHeight: 0.5
|
||||||
|
drawerParent: root
|
||||||
|
|
||||||
descriptionText: qsTr("Protocol")
|
descriptionText: qsTr("Protocol")
|
||||||
headerText: qsTr("Protocol")
|
headerText: qsTr("Protocol")
|
||||||
@@ -358,14 +358,14 @@ PageType {
|
|||||||
clickedFunction: function() {
|
clickedFunction: function() {
|
||||||
handler()
|
handler()
|
||||||
|
|
||||||
protocolSelector.menuVisible = false
|
protocolSelector.close()
|
||||||
}
|
}
|
||||||
|
|
||||||
Connections {
|
Connections {
|
||||||
target: serverSelector
|
target: serverSelector
|
||||||
|
|
||||||
function onSeverSelectorIndexChanged() {
|
function onSeverSelectorIndexChanged() {
|
||||||
var defaultContainer = proxyContainersModel.mapFromSource(ServersModel.getDefaultContainer(ServersModel.currentlyProcessedIndex))
|
var defaultContainer = proxyContainersModel.mapFromSource(ServersModel.getProcessedServerData("defaultContainer"))
|
||||||
protocolSelectorListView.currentIndex = defaultContainer
|
protocolSelectorListView.currentIndex = defaultContainer
|
||||||
protocolSelectorListView.triggerCurrentItem()
|
protocolSelectorListView.triggerCurrentItem()
|
||||||
}
|
}
|
||||||
@@ -388,7 +388,7 @@ PageType {
|
|||||||
if (accessTypeSelector.currentIndex === 1) {
|
if (accessTypeSelector.currentIndex === 1) {
|
||||||
PageController.showBusyIndicator(true)
|
PageController.showBusyIndicator(true)
|
||||||
ExportController.updateClientManagementModel(ContainersModel.getCurrentlyProcessedContainerIndex(),
|
ExportController.updateClientManagementModel(ContainersModel.getCurrentlyProcessedContainerIndex(),
|
||||||
ServersModel.getCurrentlyProcessedServerCredentials())
|
ServersModel.getProcessedServerCredentials())
|
||||||
PageController.showBusyIndicator(false)
|
PageController.showBusyIndicator(false)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -423,6 +423,7 @@ PageType {
|
|||||||
Layout.topMargin: 16
|
Layout.topMargin: 16
|
||||||
|
|
||||||
drawerHeight: 0.4375
|
drawerHeight: 0.4375
|
||||||
|
drawerParent: root
|
||||||
|
|
||||||
visible: accessTypeSelector.currentIndex === 0
|
visible: accessTypeSelector.currentIndex === 0
|
||||||
enabled: root.connectionTypesModel.length > 1
|
enabled: root.connectionTypesModel.length > 1
|
||||||
@@ -446,7 +447,7 @@ PageType {
|
|||||||
clickedFunction: function() {
|
clickedFunction: function() {
|
||||||
exportTypeSelector.text = selectedText
|
exportTypeSelector.text = selectedText
|
||||||
exportTypeSelector.currentIndex = currentIndex
|
exportTypeSelector.currentIndex = currentIndex
|
||||||
exportTypeSelector.menuVisible = false
|
exportTypeSelector.close()
|
||||||
}
|
}
|
||||||
|
|
||||||
Component.onCompleted: {
|
Component.onCompleted: {
|
||||||
@@ -456,11 +457,9 @@ PageType {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ShareConnectionDrawer {
|
|
||||||
id: shareConnectionDrawer
|
|
||||||
}
|
|
||||||
|
|
||||||
BasicButtonType {
|
BasicButtonType {
|
||||||
|
id: shareButton
|
||||||
|
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
Layout.topMargin: 40
|
Layout.topMargin: 40
|
||||||
|
|
||||||
@@ -470,7 +469,7 @@ PageType {
|
|||||||
text: qsTr("Share")
|
text: qsTr("Share")
|
||||||
imageSource: "qrc:/images/controls/share-2.svg"
|
imageSource: "qrc:/images/controls/share-2.svg"
|
||||||
|
|
||||||
onClicked: {
|
clickedFunc: function(){
|
||||||
if (clientNameTextField.textFieldText !== "") {
|
if (clientNameTextField.textFieldText !== "") {
|
||||||
ExportController.generateConfig(root.connectionTypesModel[exportTypeSelector.currentIndex].type)
|
ExportController.generateConfig(root.connectionTypesModel[exportTypeSelector.currentIndex].type)
|
||||||
}
|
}
|
||||||
@@ -561,13 +560,15 @@ PageType {
|
|||||||
|
|
||||||
DividerType {}
|
DividerType {}
|
||||||
|
|
||||||
DrawerType {
|
DrawerType2 {
|
||||||
id: clientInfoDrawer
|
id: clientInfoDrawer
|
||||||
|
|
||||||
width: root.width
|
parent: root
|
||||||
height: root.height * 0.5
|
|
||||||
|
|
||||||
ColumnLayout {
|
anchors.fill: parent
|
||||||
|
expandedHeight: root.height * 0.5
|
||||||
|
|
||||||
|
expandedContent: ColumnLayout {
|
||||||
anchors.top: parent.top
|
anchors.top: parent.top
|
||||||
anchors.left: parent.left
|
anchors.left: parent.left
|
||||||
anchors.right: parent.right
|
anchors.right: parent.right
|
||||||
@@ -598,30 +599,33 @@ PageType {
|
|||||||
|
|
||||||
text: qsTr("Rename")
|
text: qsTr("Rename")
|
||||||
|
|
||||||
onClicked: function() {
|
clickedFunc: function() {
|
||||||
clientNameEditDrawer.open()
|
clientNameEditDrawer.open()
|
||||||
}
|
}
|
||||||
|
|
||||||
DrawerType {
|
DrawerType2 {
|
||||||
id: clientNameEditDrawer
|
id: clientNameEditDrawer
|
||||||
|
|
||||||
width: root.width
|
parent: root
|
||||||
height: root.height * 0.35
|
|
||||||
|
|
||||||
onVisibleChanged: {
|
anchors.fill: parent
|
||||||
if (clientNameEditDrawer.visible) {
|
expandedHeight: root.height * 0.35
|
||||||
clientNameEditor.textField.forceActiveFocus()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ColumnLayout {
|
expandedContent: ColumnLayout {
|
||||||
anchors.top: parent.top
|
anchors.top: parent.top
|
||||||
anchors.left: parent.left
|
anchors.left: parent.left
|
||||||
anchors.right: parent.right
|
anchors.right: parent.right
|
||||||
anchors.topMargin: 16
|
anchors.topMargin: 32
|
||||||
anchors.leftMargin: 16
|
anchors.leftMargin: 16
|
||||||
anchors.rightMargin: 16
|
anchors.rightMargin: 16
|
||||||
|
|
||||||
|
Connections {
|
||||||
|
target: clientNameEditDrawer
|
||||||
|
function onOpened() {
|
||||||
|
clientNameEditor.textField.forceActiveFocus()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
TextFieldWithHeaderType {
|
TextFieldWithHeaderType {
|
||||||
id: clientNameEditor
|
id: clientNameEditor
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
@@ -629,14 +633,18 @@ PageType {
|
|||||||
textFieldText: clientName
|
textFieldText: clientName
|
||||||
textField.maximumLength: 20
|
textField.maximumLength: 20
|
||||||
checkEmptyText: true
|
checkEmptyText: true
|
||||||
|
|
||||||
|
KeyNavigation.tab: saveButton
|
||||||
}
|
}
|
||||||
|
|
||||||
BasicButtonType {
|
BasicButtonType {
|
||||||
|
id: saveButton
|
||||||
|
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
|
|
||||||
text: qsTr("Save")
|
text: qsTr("Save")
|
||||||
|
|
||||||
onClicked: {
|
clickedFunc: function() {
|
||||||
if (clientNameEditor.textFieldText === "") {
|
if (clientNameEditor.textFieldText === "") {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -646,7 +654,7 @@ PageType {
|
|||||||
ExportController.renameClient(index,
|
ExportController.renameClient(index,
|
||||||
clientNameEditor.textFieldText,
|
clientNameEditor.textFieldText,
|
||||||
ContainersModel.getCurrentlyProcessedContainerIndex(),
|
ContainersModel.getCurrentlyProcessedContainerIndex(),
|
||||||
ServersModel.getCurrentlyProcessedServerCredentials())
|
ServersModel.getProcessedServerCredentials())
|
||||||
PageController.showBusyIndicator(false)
|
PageController.showBusyIndicator(false)
|
||||||
clientNameEditDrawer.close()
|
clientNameEditDrawer.close()
|
||||||
}
|
}
|
||||||
@@ -668,21 +676,20 @@ PageType {
|
|||||||
|
|
||||||
text: qsTr("Revoke")
|
text: qsTr("Revoke")
|
||||||
|
|
||||||
onClicked: function() {
|
clickedFunc: function() {
|
||||||
questionDrawer.headerText = qsTr("Revoke the config for a user - %1?").arg(clientName)
|
var headerText = qsTr("Revoke the config for a user - %1?").arg(clientName)
|
||||||
questionDrawer.descriptionText = qsTr("The user will no longer be able to connect to your server.")
|
var descriptionText = qsTr("The user will no longer be able to connect to your server.")
|
||||||
questionDrawer.yesButtonText = qsTr("Continue")
|
var yesButtonText = qsTr("Continue")
|
||||||
questionDrawer.noButtonText = qsTr("Cancel")
|
var noButtonText = qsTr("Cancel")
|
||||||
|
|
||||||
questionDrawer.yesButtonFunction = function() {
|
var yesButtonFunction = function() {
|
||||||
questionDrawer.close()
|
|
||||||
clientInfoDrawer.close()
|
clientInfoDrawer.close()
|
||||||
root.revokeConfig(index)
|
root.revokeConfig(index)
|
||||||
}
|
}
|
||||||
questionDrawer.noButtonFunction = function() {
|
var noButtonFunction = function() {
|
||||||
questionDrawer.close()
|
|
||||||
}
|
}
|
||||||
questionDrawer.open()
|
|
||||||
|
showQuestionDrawer(headerText, descriptionText, yesButtonText, noButtonText, yesButtonFunction, noButtonFunction)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -690,12 +697,15 @@ PageType {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
QuestionDrawer {
|
|
||||||
id: questionDrawer
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ShareConnectionDrawer {
|
||||||
|
id: shareConnectionDrawer
|
||||||
|
|
||||||
|
anchors.fill: parent
|
||||||
|
}
|
||||||
|
|
||||||
MouseArea {
|
MouseArea {
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
onPressed: function(mouse) {
|
onPressed: function(mouse) {
|
||||||
|
|||||||
@@ -69,6 +69,7 @@ PageType {
|
|||||||
Layout.topMargin: 16
|
Layout.topMargin: 16
|
||||||
|
|
||||||
drawerHeight: 0.4375
|
drawerHeight: 0.4375
|
||||||
|
drawerParent: root
|
||||||
|
|
||||||
descriptionText: qsTr("Server")
|
descriptionText: qsTr("Server")
|
||||||
headerText: qsTr("Server")
|
headerText: qsTr("Server")
|
||||||
@@ -99,7 +100,7 @@ PageType {
|
|||||||
|
|
||||||
shareConnectionDrawer.headerText = qsTr("Accessing ") + serverSelector.text
|
shareConnectionDrawer.headerText = qsTr("Accessing ") + serverSelector.text
|
||||||
shareConnectionDrawer.configContentHeaderText = qsTr("File with accessing settings to ") + serverSelector.text
|
shareConnectionDrawer.configContentHeaderText = qsTr("File with accessing settings to ") + serverSelector.text
|
||||||
serverSelector.menuVisible = false
|
serverSelector.close()
|
||||||
}
|
}
|
||||||
|
|
||||||
Component.onCompleted: {
|
Component.onCompleted: {
|
||||||
@@ -110,7 +111,7 @@ PageType {
|
|||||||
|
|
||||||
function handler() {
|
function handler() {
|
||||||
serverSelector.text = selectedText
|
serverSelector.text = selectedText
|
||||||
ServersModel.currentlyProcessedIndex = proxyServersModel.mapToSource(currentIndex)
|
ServersModel.processedIndex = proxyServersModel.mapToSource(currentIndex)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -122,12 +123,10 @@ PageType {
|
|||||||
text: qsTr("Share")
|
text: qsTr("Share")
|
||||||
imageSource: "qrc:/images/controls/share-2.svg"
|
imageSource: "qrc:/images/controls/share-2.svg"
|
||||||
|
|
||||||
onClicked: function() {
|
clickedFunc: function() {
|
||||||
shareConnectionDrawer.headerText = qsTr("Connection to ") + serverSelector.text
|
shareConnectionDrawer.headerText = qsTr("Connection to ") + serverSelector.text
|
||||||
shareConnectionDrawer.configContentHeaderText = qsTr("File with connection settings to ") + serverSelector.text
|
shareConnectionDrawer.configContentHeaderText = qsTr("File with connection settings to ") + serverSelector.text
|
||||||
|
|
||||||
shareConnectionDrawer.needCloseButton = false
|
|
||||||
|
|
||||||
shareConnectionDrawer.open()
|
shareConnectionDrawer.open()
|
||||||
shareConnectionDrawer.contentVisible = false
|
shareConnectionDrawer.contentVisible = false
|
||||||
PageController.showBusyIndicator(true)
|
PageController.showBusyIndicator(true)
|
||||||
@@ -140,16 +139,15 @@ PageType {
|
|||||||
|
|
||||||
PageController.showBusyIndicator(false)
|
PageController.showBusyIndicator(false)
|
||||||
|
|
||||||
shareConnectionDrawer.needCloseButton = true
|
|
||||||
PageController.showTopCloseButton(true)
|
|
||||||
|
|
||||||
shareConnectionDrawer.contentVisible = true
|
shareConnectionDrawer.contentVisible = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ShareConnectionDrawer {
|
|
||||||
id: shareConnectionDrawer
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ShareConnectionDrawer {
|
||||||
|
id: shareConnectionDrawer
|
||||||
|
|
||||||
|
anchors.fill: parent
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,22 +20,16 @@ PageType {
|
|||||||
function onGoToPageHome() {
|
function onGoToPageHome() {
|
||||||
tabBar.setCurrentIndex(0)
|
tabBar.setCurrentIndex(0)
|
||||||
tabBarStackView.goToTabBarPage(PageEnum.PageHome)
|
tabBarStackView.goToTabBarPage(PageEnum.PageHome)
|
||||||
|
|
||||||
PageController.updateDrawerRootPage(PageEnum.PageHome)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function onGoToPageSettings() {
|
function onGoToPageSettings() {
|
||||||
tabBar.setCurrentIndex(2)
|
tabBar.setCurrentIndex(2)
|
||||||
tabBarStackView.goToTabBarPage(PageEnum.PageSettings)
|
tabBarStackView.goToTabBarPage(PageEnum.PageSettings)
|
||||||
|
|
||||||
PageController.updateDrawerRootPage(PageEnum.PageSettings)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function onGoToPageViewConfig() {
|
function onGoToPageViewConfig() {
|
||||||
var pagePath = PageController.getPagePath(PageEnum.PageSetupWizardViewConfig)
|
var pagePath = PageController.getPagePath(PageEnum.PageSetupWizardViewConfig)
|
||||||
tabBarStackView.push(pagePath, { "objectName" : pagePath }, StackView.PushTransition)
|
tabBarStackView.push(pagePath, { "objectName" : pagePath }, StackView.PushTransition)
|
||||||
|
|
||||||
PageController.updateDrawerRootPage(PageEnum.PageSetupWizardViewConfig)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function onShowBusyIndicator(visible) {
|
function onShowBusyIndicator(visible) {
|
||||||
@@ -44,15 +38,14 @@ PageType {
|
|||||||
tabBar.enabled = !visible
|
tabBar.enabled = !visible
|
||||||
}
|
}
|
||||||
|
|
||||||
// function onShowTopCloseButton(visible) {
|
|
||||||
// topCloseButton.visible = visible
|
|
||||||
// }
|
|
||||||
|
|
||||||
function onEnableTabBar(enabled) {
|
function onEnableTabBar(enabled) {
|
||||||
tabBar.enabled = enabled
|
tabBar.enabled = enabled
|
||||||
}
|
}
|
||||||
|
|
||||||
function onClosePage() {
|
function onClosePage() {
|
||||||
|
tabBar.isServerInfoShow = tabBarStackView.currentItem.objectName !== PageController.getPagePath(PageEnum.PageSettingsServerInfo)
|
||||||
|
&& tabBarStackView.currentItem.objectName !== PageController.getPagePath(PageEnum.PageSettingsSplitTunneling)
|
||||||
|
|
||||||
if (tabBarStackView.depth <= 1) {
|
if (tabBarStackView.depth <= 1) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -61,13 +54,14 @@ PageType {
|
|||||||
|
|
||||||
function onGoToPage(page, slide) {
|
function onGoToPage(page, slide) {
|
||||||
var pagePath = PageController.getPagePath(page)
|
var pagePath = PageController.getPagePath(page)
|
||||||
|
|
||||||
if (slide) {
|
if (slide) {
|
||||||
tabBarStackView.push(pagePath, { "objectName" : pagePath }, StackView.PushTransition)
|
tabBarStackView.push(pagePath, { "objectName" : pagePath }, StackView.PushTransition)
|
||||||
} else {
|
} else {
|
||||||
tabBarStackView.push(pagePath, { "objectName" : pagePath }, StackView.Immediate)
|
tabBarStackView.push(pagePath, { "objectName" : pagePath }, StackView.Immediate)
|
||||||
}
|
}
|
||||||
|
|
||||||
PageController.updateDrawerRootPage(page)
|
tabBar.isServerInfoShow = page === PageEnum.PageSettingsServerInfo || PageEnum.PageSettingsSplitTunneling || tabBar.isServerInfoShow
|
||||||
}
|
}
|
||||||
|
|
||||||
function onGoToStartPage() {
|
function onGoToStartPage() {
|
||||||
@@ -115,20 +109,12 @@ PageType {
|
|||||||
function onNoInstalledContainers() {
|
function onNoInstalledContainers() {
|
||||||
PageController.setTriggeredBtConnectButton(true)
|
PageController.setTriggeredBtConnectButton(true)
|
||||||
|
|
||||||
ServersModel.currentlyProcessedIndex = ServersModel.getDefaultServerIndex()
|
ServersModel.processedIndex = ServersModel.getDefaultServerIndex()
|
||||||
InstallController.setShouldCreateServer(false)
|
InstallController.setShouldCreateServer(false)
|
||||||
PageController.goToPage(PageEnum.PageSetupWizardEasy)
|
PageController.goToPage(PageEnum.PageSetupWizardEasy)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Connections {
|
|
||||||
target: ApiController
|
|
||||||
|
|
||||||
function onErrorOccurred(errorMessage) {
|
|
||||||
PageController.showErrorMessage(errorMessage)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
StackViewType {
|
StackViewType {
|
||||||
id: tabBarStackView
|
id: tabBarStackView
|
||||||
|
|
||||||
@@ -146,26 +132,21 @@ PageType {
|
|||||||
var pagePath = PageController.getPagePath(page)
|
var pagePath = PageController.getPagePath(page)
|
||||||
tabBarStackView.clear(StackView.Immediate)
|
tabBarStackView.clear(StackView.Immediate)
|
||||||
tabBarStackView.replace(pagePath, { "objectName" : pagePath }, StackView.Immediate)
|
tabBarStackView.replace(pagePath, { "objectName" : pagePath }, StackView.Immediate)
|
||||||
|
tabBar.isServerInfoShow = false
|
||||||
PageController.updateDrawerRootPage(page)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Component.onCompleted: {
|
Component.onCompleted: {
|
||||||
var pagePath = PageController.getPagePath(PageEnum.PageHome)
|
var pagePath = PageController.getPagePath(PageEnum.PageHome)
|
||||||
ServersModel.currentlyProcessedIndex = ServersModel.defaultIndex
|
ServersModel.processedIndex = ServersModel.defaultIndex
|
||||||
tabBarStackView.push(pagePath, { "objectName" : pagePath })
|
tabBarStackView.push(pagePath, { "objectName" : pagePath })
|
||||||
}
|
}
|
||||||
|
|
||||||
// onWidthChanged: {
|
|
||||||
// topCloseButton.x = tabBarStackView.x + tabBarStackView.width -
|
|
||||||
// topCloseButton.buttonWidth - topCloseButton.rightPadding
|
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
TabBar {
|
TabBar {
|
||||||
id: tabBar
|
id: tabBar
|
||||||
|
|
||||||
property int previousIndex: 0
|
property int previousIndex: 0
|
||||||
|
property bool isServerInfoShow: false
|
||||||
|
|
||||||
anchors.right: parent.right
|
anchors.right: parent.right
|
||||||
anchors.left: parent.left
|
anchors.left: parent.left
|
||||||
@@ -196,11 +177,11 @@ PageType {
|
|||||||
}
|
}
|
||||||
|
|
||||||
TabImageButtonType {
|
TabImageButtonType {
|
||||||
isSelected: tabBar.currentIndex === 0
|
isSelected: tabBar.isServerInfoShow ? false : tabBar.currentIndex === 0
|
||||||
image: "qrc:/images/controls/home.svg"
|
image: "qrc:/images/controls/home.svg"
|
||||||
onClicked: {
|
onClicked: {
|
||||||
tabBarStackView.goToTabBarPage(PageEnum.PageHome)
|
tabBarStackView.goToTabBarPage(PageEnum.PageHome)
|
||||||
ServersModel.currentlyProcessedIndex = ServersModel.defaultIndex
|
ServersModel.processedIndex = ServersModel.defaultIndex
|
||||||
tabBar.previousIndex = 0
|
tabBar.previousIndex = 0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -230,7 +211,7 @@ PageType {
|
|||||||
}
|
}
|
||||||
|
|
||||||
TabImageButtonType {
|
TabImageButtonType {
|
||||||
isSelected: tabBar.currentIndex === 2
|
isSelected: tabBar.isServerInfoShow ? true : tabBar.currentIndex === 2
|
||||||
image: "qrc:/images/controls/settings-2.svg"
|
image: "qrc:/images/controls/settings-2.svg"
|
||||||
onClicked: {
|
onClicked: {
|
||||||
tabBarStackView.goToTabBarPage(PageEnum.PageSettings)
|
tabBarStackView.goToTabBarPage(PageEnum.PageSettings)
|
||||||
@@ -253,13 +234,6 @@ PageType {
|
|||||||
z: 1
|
z: 1
|
||||||
}
|
}
|
||||||
|
|
||||||
// TopCloseButtonType {
|
|
||||||
// id: topCloseButton
|
|
||||||
|
|
||||||
// x: tabBarStackView.width - topCloseButton.buttonWidth - topCloseButton.rightPadding
|
|
||||||
// z: 1
|
|
||||||
// }
|
|
||||||
|
|
||||||
ConnectionTypeSelectionDrawer {
|
ConnectionTypeSelectionDrawer {
|
||||||
id: connectionTypeSelection
|
id: connectionTypeSelection
|
||||||
|
|
||||||
|
|||||||
+60
-23
@@ -8,6 +8,7 @@ import PageEnum 1.0
|
|||||||
|
|
||||||
import "Config"
|
import "Config"
|
||||||
import "Controls2"
|
import "Controls2"
|
||||||
|
import "Components"
|
||||||
|
|
||||||
Window {
|
Window {
|
||||||
id: root
|
id: root
|
||||||
@@ -134,32 +135,15 @@ Window {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Item {
|
Item {
|
||||||
anchors.right: parent.right
|
anchors.fill: parent
|
||||||
anchors.left: parent.left
|
|
||||||
anchors.bottom: parent.bottom
|
|
||||||
|
|
||||||
implicitHeight: popupErrorMessage.height
|
DrawerType2 {
|
||||||
|
|
||||||
DrawerType {
|
|
||||||
id: privateKeyPassphraseDrawer
|
id: privateKeyPassphraseDrawer
|
||||||
|
|
||||||
width: root.width
|
anchors.fill: parent
|
||||||
height: root.height * 0.35
|
expandedHeight: root.height * 0.35
|
||||||
|
|
||||||
onVisibleChanged: {
|
expandedContent: ColumnLayout {
|
||||||
if (privateKeyPassphraseDrawer.visible) {
|
|
||||||
passphrase.textFieldText = ""
|
|
||||||
passphrase.textField.forceActiveFocus()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
onAboutToHide: {
|
|
||||||
PageController.showBusyIndicator(true)
|
|
||||||
}
|
|
||||||
onAboutToShow: {
|
|
||||||
PageController.showBusyIndicator(false)
|
|
||||||
}
|
|
||||||
|
|
||||||
ColumnLayout {
|
|
||||||
anchors.top: parent.top
|
anchors.top: parent.top
|
||||||
anchors.left: parent.left
|
anchors.left: parent.left
|
||||||
anchors.right: parent.right
|
anchors.right: parent.right
|
||||||
@@ -167,6 +151,24 @@ Window {
|
|||||||
anchors.leftMargin: 16
|
anchors.leftMargin: 16
|
||||||
anchors.rightMargin: 16
|
anchors.rightMargin: 16
|
||||||
|
|
||||||
|
Connections {
|
||||||
|
target: privateKeyPassphraseDrawer
|
||||||
|
function onOpened() {
|
||||||
|
passphrase.textFieldText = ""
|
||||||
|
passphrase.textField.forceActiveFocus()
|
||||||
|
}
|
||||||
|
|
||||||
|
function onAboutToHide() {
|
||||||
|
if (passphrase.textFieldText !== "") {
|
||||||
|
PageController.showBusyIndicator(true)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function onAboutToShow() {
|
||||||
|
PageController.showBusyIndicator(false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
TextFieldWithHeaderType {
|
TextFieldWithHeaderType {
|
||||||
id: passphrase
|
id: passphrase
|
||||||
|
|
||||||
@@ -180,9 +182,13 @@ Window {
|
|||||||
clickedFunc: function() {
|
clickedFunc: function() {
|
||||||
hidePassword = !hidePassword
|
hidePassword = !hidePassword
|
||||||
}
|
}
|
||||||
|
|
||||||
|
KeyNavigation.tab: saveButton
|
||||||
}
|
}
|
||||||
|
|
||||||
BasicButtonType {
|
BasicButtonType {
|
||||||
|
id: saveButton
|
||||||
|
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
|
|
||||||
defaultColor: "transparent"
|
defaultColor: "transparent"
|
||||||
@@ -194,7 +200,7 @@ Window {
|
|||||||
|
|
||||||
text: qsTr("Save")
|
text: qsTr("Save")
|
||||||
|
|
||||||
onClicked: {
|
clickedFunc: function() {
|
||||||
privateKeyPassphraseDrawer.close()
|
privateKeyPassphraseDrawer.close()
|
||||||
PageController.passphraseRequestDrawerClosed(passphrase.textFieldText)
|
PageController.passphraseRequestDrawerClosed(passphrase.textFieldText)
|
||||||
}
|
}
|
||||||
@@ -203,6 +209,37 @@ Window {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Item {
|
||||||
|
anchors.fill: parent
|
||||||
|
|
||||||
|
QuestionDrawer {
|
||||||
|
id: questionDrawer
|
||||||
|
|
||||||
|
anchors.fill: parent
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function showQuestionDrawer(headerText, descriptionText, yesButtonText, noButtonText, yesButtonFunction, noButtonFunction) {
|
||||||
|
questionDrawer.headerText = headerText
|
||||||
|
questionDrawer.descriptionText = descriptionText
|
||||||
|
questionDrawer.yesButtonText = yesButtonText
|
||||||
|
questionDrawer.noButtonText = noButtonText
|
||||||
|
|
||||||
|
questionDrawer.yesButtonFunction = function() {
|
||||||
|
questionDrawer.close()
|
||||||
|
if (yesButtonFunction && typeof yesButtonFunction === "function") {
|
||||||
|
yesButtonFunction()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
questionDrawer.noButtonFunction = function() {
|
||||||
|
questionDrawer.close()
|
||||||
|
if (noButtonFunction && typeof noButtonFunction === "function") {
|
||||||
|
noButtonFunction()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
questionDrawer.open()
|
||||||
|
}
|
||||||
|
|
||||||
FileDialog {
|
FileDialog {
|
||||||
id: mainFileDialog
|
id: mainFileDialog
|
||||||
|
|
||||||
|
|||||||
@@ -146,7 +146,8 @@ if [ "${MAC_CERT_PW+x}" ]; then
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
echo "Building DMG installer..."
|
echo "Building DMG installer..."
|
||||||
hdiutil create -size 120mb -volname AmneziaVPN -srcfolder $BUILD_DIR/installer/$APP_NAME.app -ov -format UDZO $DMG_FILENAME
|
# Allow Terminal to make changes in Privacy & Security > App Management
|
||||||
|
hdiutil create -size 256mb -volname AmneziaVPN -srcfolder $BUILD_DIR/installer/$APP_NAME.app -ov -format UDZO $DMG_FILENAME
|
||||||
|
|
||||||
if [ "${MAC_CERT_PW+x}" ]; then
|
if [ "${MAC_CERT_PW+x}" ]; then
|
||||||
echo "Signing DMG installer..."
|
echo "Signing DMG installer..."
|
||||||
|
|||||||
Reference in New Issue
Block a user