moved the platform-specific android code for the new ui

This commit is contained in:
vladimir.kuznetsov 2023-07-24 16:31:04 +09:00
parent 5b8a0881b7
commit 0a1359ed16
31 changed files with 854 additions and 764 deletions

View file

@ -11,9 +11,12 @@
#include "configurators/openvpn_configurator.h"
#include "configurators/wireguard_configurator.h"
#include "qrcodegen.hpp"
#include "core/errorstrings.h"
#ifdef Q_OS_ANDROID
#include "platforms/android/android_controller.h"
#include "platforms/android/androidutils.h"
#endif
#include "qrcodegen.hpp"
ExportController::ExportController(const QSharedPointer<ServersModel> &serversModel,
const QSharedPointer<ContainersModel> &containersModel,
@ -25,6 +28,14 @@ ExportController::ExportController(const QSharedPointer<ServersModel> &serversMo
m_settings(settings),
m_configurator(configurator)
{
#ifdef Q_OS_ANDROID
m_authResultNotifier.reset(new AuthResultNotifier);
m_authResultReceiver.reset(new AuthResultReceiver(m_authResultNotifier));
connect(m_authResultNotifier.get(), &AuthResultNotifier::authFailed, this,
[this]() { emit exportErrorOccurred(tr("Access error!")); });
connect(m_authResultNotifier.get(), &AuthResultNotifier::authSuccessful, this,
&ExportController::generateFullAccessConfig);
#endif
}
void ExportController::generateFullAccessConfig()
@ -44,6 +55,27 @@ void ExportController::generateFullAccessConfig()
emit exportConfigChanged();
}
#if defined(Q_OS_ANDROID)
void ExportController::generateFullAccessConfigAndroid()
{
/* We use builtin keyguard for ssh key export protection on Android */
QJniObject activity = AndroidUtils::getActivity();
auto appContext = activity.callObjectMethod("getApplicationContext", "()Landroid/content/Context;");
if (appContext.isValid()) {
auto intent = QJniObject::callStaticObjectMethod("org/amnezia/vpn/AuthHelper", "getAuthIntent",
"(Landroid/content/Context;)Landroid/content/Intent;",
appContext.object());
if (intent.isValid()) {
if (intent.object<jobject>() != nullptr) {
QtAndroidPrivate::startActivity(intent.object<jobject>(), 1, m_authResultReceiver.get());
}
} else {
generateFullAccessConfig();
}
}
}
#endif
void ExportController::generateConnectionConfig()
{
clearPreviousConfig();
@ -194,6 +226,35 @@ void ExportController::saveFile()
QDesktopServices::openUrl(fi.absoluteDir().absolutePath());
}
void ExportController::shareFile()
{
#if defined Q_OS_IOS
ext.replace("*", "");
QString fileName = QDir::tempPath() + "/" + suggestedName;
if (fileName.isEmpty())
return;
if (!fileName.endsWith(ext))
fileName.append(ext);
QFile::remove(fileName);
QFile save(fileName);
save.open(QIODevice::WriteOnly);
save.write(data.toUtf8());
save.close();
QStringList filesToSend;
filesToSend.append(fileName);
MobileUtils::shareText(filesToSend);
return;
#endif
#if defined Q_OS_ANDROID
AndroidController::instance()->shareConfig(m_config, "amnezia_config");
return;
#endif
}
QList<QString> ExportController::generateQrCodeImageSeries(const QByteArray &data)
{
double k = 850;

View file

@ -6,6 +6,9 @@
#include "configurators/vpn_configurator.h"
#include "ui/models/containers_model.h"
#include "ui/models/servers_model.h"
#ifdef Q_OS_ANDROID
#include "platforms/android/authResultReceiver.h"
#endif
class ExportController : public QObject
{
@ -22,6 +25,9 @@ public:
public slots:
void generateFullAccessConfig();
#if defined(Q_OS_ANDROID)
void generateFullAccessConfigAndroid();
#endif
void generateConnectionConfig();
void generateOpenVpnConfig();
void generateWireGuardConfig();
@ -30,6 +36,7 @@ public slots:
QList<QString> getQrCodes();
void saveFile();
void shareFile();
signals:
void generateConfig(int type);
@ -52,6 +59,11 @@ private:
QString m_config;
QList<QString> m_qrCodes;
#ifdef Q_OS_ANDROID
QSharedPointer<AuthResultNotifier> m_authResultNotifier;
QSharedPointer<QAndroidActivityResultReceiver> m_authResultReceiver;
#endif
};
#endif // EXPORTCONTROLLER_H

View file

@ -2,8 +2,15 @@
#include <QFile>
#include <QFileInfo>
#include <QStandardPaths>
#include "core/errorstrings.h"
#ifdef Q_OS_ANDROID
#include "../../platforms/android/android_controller.h"
#include "../../platforms/android/androidutils.h"
#include <QJniObject>
#endif
#include "utilities.h"
namespace
{
@ -41,33 +48,58 @@ ImportController::ImportController(const QSharedPointer<ServersModel> &serversMo
const std::shared_ptr<Settings> &settings, QObject *parent)
: QObject(parent), m_serversModel(serversModel), m_containersModel(containersModel), m_settings(settings)
{
#ifdef Q_OS_ANDROID
// Set security screen for Android app
AndroidUtils::runOnAndroidThreadSync([]() {
QJniObject activity = AndroidUtils::getActivity();
QJniObject window = activity.callObjectMethod("getWindow", "()Landroid/view/Window;");
if (window.isValid()) {
const int FLAG_SECURE = 8192;
window.callMethod<void>("addFlags", "(I)V", FLAG_SECURE);
}
});
#endif
}
void ImportController::extractConfigFromFile(const QUrl &fileUrl)
void ImportController::extractConfigFromFile()
{
QFile file(fileUrl.toLocalFile());
QString fileName = Utils::getFileName(Q_NULLPTR, tr("Open config file"),
QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation),
"*.vpn *.ovpn *.conf");
QFile file(fileName);
if (file.open(QIODevice::ReadOnly)) {
QString data = file.readAll();
auto configFormat = checkConfigFormat(data);
if (configFormat == ConfigTypes::OpenVpn) {
m_config = extractOpenVpnConfig(data);
} else if (configFormat == ConfigTypes::WireGuard) {
m_config = extractWireGuardConfig(data);
} else {
m_config = extractAmneziaConfig(data);
}
extractConfigFromData(data);
m_configFileName = QFileInfo(file.fileName()).fileName();
}
}
void ImportController::extractConfigFromData(QString &data)
{
auto configFormat = checkConfigFormat(data);
if (configFormat == ConfigTypes::OpenVpn) {
m_config = extractOpenVpnConfig(data);
} else if (configFormat == ConfigTypes::WireGuard) {
m_config = extractWireGuardConfig(data);
} else {
m_config = extractAmneziaConfig(data);
}
}
void ImportController::extractConfigFromCode(QString code)
{
m_config = extractAmneziaConfig(code);
m_configFileName = "";
}
void ImportController::extractConfigFromQr()
{
#ifdef Q_OS_ANDROID
AndroidController::instance()->startQrReaderActivity();
#endif
}
QString ImportController::getConfig()
{
return QJsonDocument(m_config).toJson(QJsonDocument::Indented);

View file

@ -3,10 +3,10 @@
#include <QObject>
#include "core/defs.h"
#include "containers/containers_defs.h"
#include "ui/models/servers_model.h"
#include "core/defs.h"
#include "ui/models/containers_model.h"
#include "ui/models/servers_model.h"
class ImportController : public QObject
{
@ -14,13 +14,14 @@ class ImportController : public QObject
public:
explicit ImportController(const QSharedPointer<ServersModel> &serversModel,
const QSharedPointer<ContainersModel> &containersModel,
const std::shared_ptr<Settings> &settings,
QObject *parent = nullptr);
const std::shared_ptr<Settings> &settings, QObject *parent = nullptr);
public slots:
void importConfig();
void extractConfigFromFile(const QUrl &fileUrl);
void extractConfigFromFile();
void extractConfigFromData(QString &data);
void extractConfigFromCode(QString code);
void extractConfigFromQr();
QString getConfig();
QString getConfigFileName();
@ -39,7 +40,6 @@ private:
QJsonObject m_config;
QString m_configFileName;
};
#endif // IMPORTCONTROLLER_H

View file

@ -8,6 +8,34 @@
#include "core/servercontroller.h"
#include "utilities.h"
namespace
{
#ifdef Q_OS_WINDOWS
QString getNextDriverLetter()
{
QProcess drivesProc;
drivesProc.start("wmic logicaldisk get caption");
drivesProc.waitForFinished();
QString drives = drivesProc.readAll();
qDebug() << drives;
QString letters = "CFGHIJKLMNOPQRSTUVWXYZ";
QString letter;
for (int i = letters.size() - 1; i > 0; i--) {
letter = letters.at(i);
if (!drives.contains(letter + ":"))
break;
}
if (letter == "C:") {
// set err info
qDebug() << "Can't find free drive letter";
return "";
}
return letter;
}
#endif
}
InstallController::InstallController(const QSharedPointer<ServersModel> &serversModel,
const QSharedPointer<ContainersModel> &containersModel,
const std::shared_ptr<Settings> &settings, QObject *parent)
@ -15,6 +43,17 @@ InstallController::InstallController(const QSharedPointer<ServersModel> &servers
{
}
InstallController::~InstallController()
{
#ifdef Q_OS_WINDOWS
for (QSharedPointer<QProcess> process : m_sftpMountProcesses) {
Utils::signalCtrl(process->processId(), CTRL_C_EVENT);
process->kill();
process->waitForFinished();
}
#endif
}
void InstallController::install(DockerContainer container, int port, TransportProto transportProto)
{
Proto mainProto = ContainerProps::defaultProtocol(container);

View file

@ -16,6 +16,7 @@ public:
explicit InstallController(const QSharedPointer<ServersModel> &serversModel,
const QSharedPointer<ContainersModel> &containersModel,
const std::shared_ptr<Settings> &settings, QObject *parent = nullptr);
~InstallController();
public slots:
void install(DockerContainer container, int port, TransportProto transportProto);

View file

@ -1,7 +1,9 @@
#include "pageController.h"
PageController::PageController(const QSharedPointer<ServersModel> &serversModel,
QObject *parent) : QObject(parent), m_serversModel(serversModel)
#include <QApplication>
PageController::PageController(const QSharedPointer<ServersModel> &serversModel, QObject *parent)
: QObject(parent), m_serversModel(serversModel)
{
}
@ -24,3 +26,24 @@ QString PageController::getPagePath(PageLoader::PageEnum page)
QString pageName = metaEnum.valueToKey(static_cast<int>(page));
return "qrc:/ui/qml/Pages2/" + pageName + ".qml";
}
void PageController::closeWindow()
{
#ifdef Q_OS_ANDROID
qApp->quit();
#else
if (m_serversModel->getServersCount() == 0) {
qApp->quit();
} else {
emit hideMainWindow();
}
#endif
}
void PageController::keyPressEvent(Qt::Key key)
{
switch (key) {
case Qt::Key_Back: emit closePage();
default: return;
}
}

View file

@ -41,6 +41,7 @@ namespace PageLoader
PageSetupWizardConfigSource,
PageSetupWizardTextKey,
PageSetupWizardViewConfig,
PageSetupWizardQrReader,
PageProtocolOpenVpnSettings,
PageProtocolShadowSocksSettings,
@ -67,15 +68,25 @@ public slots:
QString getInitialPage();
QString getPagePath(PageLoader::PageEnum page);
void closeWindow();
void keyPressEvent(Qt::Key key);
signals:
void goToPageHome();
void goToPageSettings();
void goToPageViewConfig();
void closePage();
void restorePageHomeState(bool isContainerInstalled = false);
void replaceStartPage();
void showErrorMessage(QString errorMessage);
void showInfoMessage(QString message);
void showBusyIndicator(bool visible);
void raise();
void hideMainWindow();
void raiseMainWindow();
private:
QSharedPointer<ServersModel> m_serversModel;

View file

@ -6,20 +6,21 @@
#include "VpnLogic.h"
#include "core/errorstrings.h"
#include <core/servercontroller.h>
#include <QTimer>
#include <core/servercontroller.h>
#if defined(Q_OS_ANDROID)
#include "../../platforms/android/androidutils.h"
#include "../../platforms/android/androidutils.h"
#endif
ServerSettingsLogic::ServerSettingsLogic(UiLogic *logic, QObject *parent):
PageLogicBase(logic, parent),
m_labelWaitInfoVisible{true},
m_pushButtonClearClientCacheVisible{true},
m_pushButtonShareFullVisible{true},
m_pushButtonClearClientCacheText{tr("Clear client cached profile")}
{ }
ServerSettingsLogic::ServerSettingsLogic(UiLogic *logic, QObject *parent)
: PageLogicBase(logic, parent),
m_labelWaitInfoVisible { true },
m_pushButtonClearClientCacheVisible { true },
m_pushButtonShareFullVisible { true },
m_pushButtonClearClientCacheText { tr("Clear client cached profile") }
{
}
void ServerSettingsLogic::onUpdatePage()
{
@ -33,11 +34,11 @@ void ServerSettingsLogic::onUpdatePage()
const QString &userName = server.value(config_key::userName).toString();
const QString &hostName = server.value(config_key::hostName).toString();
QString name = QString("%1%2%3%4%5")
.arg(userName)
.arg(userName.isEmpty() ? "" : "@")
.arg(hostName)
.arg(port.isEmpty() ? "" : ":")
.arg(port);
.arg(userName)
.arg(userName.isEmpty() ? "" : "@")
.arg(hostName)
.arg(port.isEmpty() ? "" : ":")
.arg(port);
set_labelServerText(name);
set_lineEditDescriptionText(server.value(config_key::description).toString());
@ -49,15 +50,15 @@ void ServerSettingsLogic::onUpdatePage()
void ServerSettingsLogic::onPushButtonForgetServer()
{
if (m_settings->defaultServerIndex() == uiLogic()->m_selectedServerIndex && uiLogic()->m_vpnConnection->isConnected()) {
if (m_settings->defaultServerIndex() == uiLogic()->m_selectedServerIndex
&& uiLogic()->m_vpnConnection->isConnected()) {
uiLogic()->pageLogic<VpnLogic>()->onDisconnect();
}
m_settings->removeServer(uiLogic()->m_selectedServerIndex);
if (m_settings->defaultServerIndex() == uiLogic()->m_selectedServerIndex) {
m_settings->setDefaultServer(0);
}
else if (m_settings->defaultServerIndex() > uiLogic()->m_selectedServerIndex) {
} else if (m_settings->defaultServerIndex() > uiLogic()->m_selectedServerIndex) {
m_settings->setDefaultServer(m_settings->defaultServerIndex() - 1);
}
@ -65,14 +66,12 @@ void ServerSettingsLogic::onPushButtonForgetServer()
m_settings->setDefaultServer(-1);
}
uiLogic()->m_selectedServerIndex = -1;
uiLogic()->onUpdateAllPages();
if (m_settings->serversCount() == 0) {
uiLogic()->setStartPage(Page::Start);
}
else {
} else {
uiLogic()->closePage();
}
}
@ -86,9 +85,7 @@ void ServerSettingsLogic::onPushButtonClearClientCacheClicked()
m_settings->clearLastConnectionConfig(uiLogic()->m_selectedServerIndex, container);
}
QTimer::singleShot(3000, this, [this]() {
set_pushButtonClearClientCacheText(tr("Clear client cached profile"));
});
QTimer::singleShot(3000, this, [this]() { set_pushButtonClearClientCacheText(tr("Clear client cached profile")); });
}
void ServerSettingsLogic::onLineEditDescriptionEditingFinished()
@ -111,7 +108,7 @@ void authResultReceiver::handleActivityResult(int receiverRequestCode, int resul
{
qDebug() << "receiverRequestCode" << receiverRequestCode << "resultCode" << resultCode;
if (resultCode == -1) { //ResultOK
if (resultCode == -1) { // ResultOK
uiLogic()->pageLogic<ShareConnectionLogic>()->updateSharingPage(m_serverIndex, DockerContainer::None);
emit uiLogic()->goToShareProtocolPage(Proto::Any);
}
@ -121,26 +118,27 @@ void authResultReceiver::handleActivityResult(int receiverRequestCode, int resul
void ServerSettingsLogic::onPushButtonShareFullClicked()
{
#if defined(Q_OS_ANDROID)
/* We use builtin keyguard for ssh key export protection on Android */
/* We use builtin keyguard for ssh key export protection on Android */
QJniObject activity = AndroidUtils::getActivity();
auto appContext = activity.callObjectMethod(
"getApplicationContext", "()Landroid/content/Context;");
auto appContext = activity.callObjectMethod("getApplicationContext", "()Landroid/content/Context;");
if (appContext.isValid()) {
QAndroidActivityResultReceiver *receiver = new authResultReceiver(uiLogic(), uiLogic()->m_selectedServerIndex);
auto intent = QJniObject::callStaticObjectMethod(
"org/amnezia/vpn/AuthHelper", "getAuthIntent",
"(Landroid/content/Context;)Landroid/content/Intent;", appContext.object());
auto intent = QJniObject::callStaticObjectMethod("org/amnezia/vpn/AuthHelper", "getAuthIntent",
"(Landroid/content/Context;)Landroid/content/Intent;",
appContext.object());
if (intent.isValid()) {
if (intent.object<jobject>() != nullptr) {
QtAndroidPrivate::startActivity(intent.object<jobject>(), 1, receiver);
}
} else {
uiLogic()->pageLogic<ShareConnectionLogic>()->updateSharingPage(uiLogic()->m_selectedServerIndex, DockerContainer::None);
QtAndroidPrivate::startActivity(intent.object<jobject>(), 1, receiver);
}
} else {
uiLogic()->pageLogic<ShareConnectionLogic>()->updateSharingPage(uiLogic()->m_selectedServerIndex,
DockerContainer::None);
emit uiLogic()->goToShareProtocolPage(Proto::Any);
}
}
#else
uiLogic()->pageLogic<ShareConnectionLogic>()->updateSharingPage(uiLogic()->m_selectedServerIndex, DockerContainer::None);
uiLogic()->pageLogic<ShareConnectionLogic>()->updateSharingPage(uiLogic()->m_selectedServerIndex,
DockerContainer::None);
emit uiLogic()->goToShareProtocolPage(Proto::Any);
#endif
}

View file

@ -1,68 +1,69 @@
#include "StartPageLogic.h"
#include "ViewConfigLogic.h"
#include "core/errorstrings.h"
#include "../uilogic.h"
#include "configurators/ssh_configurator.h"
#include "configurators/vpn_configurator.h"
#include "../uilogic.h"
#include "utilities.h"
#include "core/errorstrings.h"
#include "core/servercontroller.h"
#include "utilities.h"
#include <QEventLoop>
#include <QFileDialog>
#include <QStandardPaths>
#include <QEventLoop>
#ifdef Q_OS_ANDROID
#include <QJniObject>
#include "../../platforms/android/androidutils.h"
#include "../../platforms/android/android_controller.h"
#include "../../platforms/android/android_controller.h"
#include "../../platforms/android/androidutils.h"
#include <QJniObject>
#endif
namespace {
enum class ConfigTypes {
Amnezia,
OpenVpn,
WireGuard
};
ConfigTypes checkConfigFormat(const QString &config)
namespace
{
const QString openVpnConfigPatternCli = "client";
const QString openVpnConfigPatternProto1 = "proto tcp";
const QString openVpnConfigPatternProto2 = "proto udp";
const QString openVpnConfigPatternDriver1 = "dev tun";
const QString openVpnConfigPatternDriver2 = "dev tap";
enum class ConfigTypes {
Amnezia,
OpenVpn,
WireGuard
};
const QString wireguardConfigPatternSectionInterface = "[Interface]";
const QString wireguardConfigPatternSectionPeer = "[Peer]";
ConfigTypes checkConfigFormat(const QString &config)
{
const QString openVpnConfigPatternCli = "client";
const QString openVpnConfigPatternProto1 = "proto tcp";
const QString openVpnConfigPatternProto2 = "proto udp";
const QString openVpnConfigPatternDriver1 = "dev tun";
const QString openVpnConfigPatternDriver2 = "dev tap";
if (config.contains(openVpnConfigPatternCli) &&
(config.contains(openVpnConfigPatternProto1) || config.contains(openVpnConfigPatternProto2)) &&
(config.contains(openVpnConfigPatternDriver1) || config.contains(openVpnConfigPatternDriver2))) {
return ConfigTypes::OpenVpn;
} else if (config.contains(wireguardConfigPatternSectionInterface) &&
config.contains(wireguardConfigPatternSectionPeer))
return ConfigTypes::WireGuard;
return ConfigTypes::Amnezia;
}
const QString wireguardConfigPatternSectionInterface = "[Interface]";
const QString wireguardConfigPatternSectionPeer = "[Peer]";
if (config.contains(openVpnConfigPatternCli)
&& (config.contains(openVpnConfigPatternProto1) || config.contains(openVpnConfigPatternProto2))
&& (config.contains(openVpnConfigPatternDriver1) || config.contains(openVpnConfigPatternDriver2))) {
return ConfigTypes::OpenVpn;
} else if (config.contains(wireguardConfigPatternSectionInterface)
&& config.contains(wireguardConfigPatternSectionPeer))
return ConfigTypes::WireGuard;
return ConfigTypes::Amnezia;
}
}
StartPageLogic::StartPageLogic(UiLogic *logic, QObject *parent):
PageLogicBase(logic, parent),
m_pushButtonConnectEnabled{true},
m_pushButtonConnectText{tr("Connect")},
m_pushButtonConnectKeyChecked{false},
m_labelWaitInfoVisible{true},
m_pushButtonBackFromStartVisible{true},
m_ipAddressPortRegex{Utils::ipAddressPortRegExp()}
StartPageLogic::StartPageLogic(UiLogic *logic, QObject *parent)
: PageLogicBase(logic, parent),
m_pushButtonConnectEnabled { true },
m_pushButtonConnectText { tr("Connect") },
m_pushButtonConnectKeyChecked { false },
m_labelWaitInfoVisible { true },
m_pushButtonBackFromStartVisible { true },
m_ipAddressPortRegex { Utils::ipAddressPortRegExp() }
{
#ifdef Q_OS_ANDROID
// Set security screen for Android app
AndroidUtils::runOnAndroidThreadSync([]() {
QJniObject activity = AndroidUtils::getActivity();
QJniObject window = activity.callObjectMethod("getWindow", "()Landroid/view/Window;");
if (window.isValid()){
if (window.isValid()) {
const int FLAG_SECURE = 8192;
window.callMethod<void>("addFlags", "(I)V", FLAG_SECURE);
}
@ -89,17 +90,13 @@ void StartPageLogic::onUpdatePage()
void StartPageLogic::onPushButtonConnect()
{
if (pushButtonConnectKeyChecked()){
if (lineEditIpText().isEmpty() ||
lineEditLoginText().isEmpty() ||
textEditSshKeyText().isEmpty() ) {
if (pushButtonConnectKeyChecked()) {
if (lineEditIpText().isEmpty() || lineEditLoginText().isEmpty() || textEditSshKeyText().isEmpty()) {
set_labelWaitInfoText(tr("Please fill in all fields"));
return;
}
} else {
if (lineEditIpText().isEmpty() ||
lineEditLoginText().isEmpty() ||
lineEditPasswordText().isEmpty() ) {
if (lineEditIpText().isEmpty() || lineEditLoginText().isEmpty() || lineEditPasswordText().isEmpty()) {
set_labelWaitInfoText(tr("Please fill in all fields"));
return;
}
@ -174,7 +171,8 @@ void StartPageLogic::onPushButtonConnect()
set_pushButtonConnectText(tr("Connect"));
uiLogic()->m_installCredentials = serverCredentials;
if (ok) emit uiLogic()->goToPage(Page::NewServer);
if (ok)
emit uiLogic()->goToPage(Page::NewServer);
}
void StartPageLogic::onPushButtonImport()
@ -185,8 +183,10 @@ void StartPageLogic::onPushButtonImport()
void StartPageLogic::onPushButtonImportOpenFile()
{
QString fileName = UiLogic::getOpenFileName(Q_NULLPTR, tr("Open config file"),
QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation), "*.vpn *.ovpn *.conf");
if (fileName.isEmpty()) return;
QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation),
"*.vpn *.ovpn *.conf");
if (fileName.isEmpty())
return;
QFile file(fileName);
file.open(QIODevice::ReadOnly);
@ -226,8 +226,7 @@ bool StartPageLogic::importConnection(const QJsonObject &profile)
// check config
uiLogic()->pageLogic<ViewConfigLogic>()->set_configJson(profile);
emit uiLogic()->goToPage(Page::ViewConfig);
}
else {
} else {
qDebug() << "Failed to import profile";
qDebug().noquote() << QJsonDocument(profile).toJson();
return false;
@ -298,7 +297,6 @@ bool StartPageLogic::importConnectionFromOpenVpnConfig(const QString &config)
o[config_key::defaultContainer] = "amnezia-openvpn";
o[config_key::description] = m_settings->nextAvailableServerName();
const static QRegularExpression dnsRegExp("dhcp-option DNS (\\b\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\b)");
QRegularExpressionMatchIterator dnsMatch = dnsRegExp.globalMatch(config);
if (dnsMatch.hasNext()) {
@ -345,7 +343,9 @@ bool StartPageLogic::importConnectionFromWireguardConfig(const QString &config)
o[config_key::defaultContainer] = "amnezia-wireguard";
o[config_key::description] = m_settings->nextAvailableServerName();
const static QRegularExpression dnsRegExp("DNS = (\\b\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\b).*(\\b\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\b)");
const static QRegularExpression dnsRegExp(
"DNS = "
"(\\b\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\b).*(\\b\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\b)");
QRegularExpressionMatch dnsMatch = dnsRegExp.match(config);
if (dnsMatch.hasMatch()) {
o[config_key::dns1] = dnsMatch.captured(1);

View file

@ -54,10 +54,10 @@ DrawerType {
Layout.fillWidth: true
Layout.topMargin: 16
text: qsTr("Save connection code")
text: Qt.platform.os === "android" ? qsTr("Share") : qsTr("Save connection code")
onClicked: {
ExportController.saveFile()
Qt.platform.os === "android" ? ExportController.shareFile() : ExportController.saveFile()
}
}

View file

@ -26,7 +26,7 @@ CheckBox {
hoverEnabled: true
indicator: Rectangle {
id: checkBoxBackground
id: background
anchors.verticalCenter: parent.verticalCenter
@ -57,7 +57,6 @@ CheckBox {
radius: 4
Image {
id: indicator
anchors.centerIn: parent
source: root.pressed ? imageSource : root.checked ? imageSource : ""
@ -71,31 +70,38 @@ CheckBox {
}
}
contentItem: ColumnLayout {
anchors.left: parent.left
anchors.right: parent.right
anchors.leftMargin: 8 + checkBoxBackground.width
contentItem: Item {
implicitWidth: content.implicitWidth
implicitHeight: content.implicitHeight
spacing: 4
anchors.fill: parent
anchors.leftMargin: 8 + background.width
ListItemTitleType {
Layout.fillWidth: true
// Layout.topMargin: 16
// Layout.bottomMargin: description.visible ? 0 : 16
ColumnLayout {
id: content
text: root.text
}
anchors.left: parent.left
anchors.right: parent.right
anchors.verticalCenter: parent.verticalCenter
CaptionTextType {
id: description
spacing: 4
Layout.fillWidth: true
Layout.bottomMargin: 16
ListItemTitleType {
Layout.fillWidth: true
text: root.descriptionText
color: "#878b91"
text: root.text
}
visible: root.descriptionText !== ""
CaptionTextType {
id: description
Layout.fillWidth: true
text: root.descriptionText
color: "#878b91"
visible: root.descriptionText !== ""
}
}
}

View file

@ -20,7 +20,6 @@ Item {
if (root.stackView.depth <= 1) {
return
}
root.stackView.pop()
}

View file

@ -85,44 +85,50 @@ RadioButton {
}
}
contentItem: ColumnLayout {
id: content
anchors.left: parent.left
anchors.right: parent.right
contentItem: Item {
implicitWidth: content.implicitWidth
implicitHeight: content.implicitHeight
anchors.fill: parent
anchors.leftMargin: 8 + background.width
spacing: 4
ColumnLayout {
id: content
ListItemTitleType {
text: root.text
anchors.left: parent.left
anchors.right: parent.right
anchors.verticalCenter: parent.verticalCenter
color: {
if (root.checked) {
return selectedTextColor
spacing: 4
ListItemTitleType {
text: root.text
color: {
if (root.checked) {
return selectedTextColor
}
return textColor
}
Layout.fillWidth: true
Behavior on color {
PropertyAnimation { duration: 200 }
}
return textColor
}
Layout.fillWidth: true
Layout.topMargin: 16
Layout.bottomMargin: description.visible ? 0 : 16
CaptionTextType {
id: description
Behavior on color {
PropertyAnimation { duration: 200 }
color: "#878B91"
text: root.descriptionText
visible: root.descriptionText !== ""
Layout.fillWidth: true
}
}
CaptionTextType {
id: description
color: "#878B91"
text: root.descriptionText
visible: root.descriptionText !== ""
Layout.fillWidth: true
Layout.bottomMargin: 16
}
}
MouseArea {

View file

@ -43,8 +43,8 @@ PageType {
Layout.topMargin: 16
Layout.leftMargin: 16
Layout.rightMargin: 16
Layout.preferredWidth: 344
Layout.preferredHeight: 279
Layout.preferredWidth: 291
Layout.preferredHeight: 224
}
Header2TextType {
@ -100,7 +100,7 @@ And if you don't like the app, all the more support it - the donation will be us
text: qsTr("Show other methods on Github")
onClicked: Qt.openUrlExternally("https://github.com/amnezia-vpn/amnezia-client")
onClicked: Qt.openUrlExternally("https://github.com/amnezia-vpn/amnezia-client#donate")
}
ParagraphTextType {

View file

@ -61,16 +61,18 @@ PageType {
leftImageSource: "qrc:/images/controls/folder-open.svg"
clickedFunction: function() {
onClicked: fileDialog.open()
// onClicked: fileDialog.open()
ImportController.extractConfigFromFile()
goToPage(PageEnum.PageSetupWizardViewConfig)
}
FileDialog {
id: fileDialog
onAccepted: {
ImportController.extractConfigFromFile(selectedFile)
goToPage(PageEnum.PageSetupWizardViewConfig)
}
}
// FileDialog {
// id: fileDialog
// onAccepted: {
// ImportController.extractConfigFromFile(selectedFile)
// goToPage(PageEnum.PageSetupWizardViewConfig)
// }
// }
}
DividerType {}
@ -84,6 +86,8 @@ PageType {
leftImageSource: "qrc:/images/controls/qr-code.svg"
clickedFunction: function() {
ImportController.extractConfigFromQr()
// goToPage(PageEnum.PageSetupWizardQrReader)
}
}

View file

@ -0,0 +1,52 @@
import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
import QtQuick.Dialogs
import PageEnum 1.0
import QRCodeReader 1.0
import "./"
import "../Controls2"
import "../Controls2/TextTypes"
import "../Config"
PageType {
id: root
ColumnLayout {
anchors.fill: parent
spacing: 0
BackButtonType {
Layout.topMargin: 20
}
ParagraphTextType {
Layout.fillWidth: true
text: qsTr("Point the camera at the QR code and hold for a couple of seconds.")
}
ProgressBarType {
}
Item {
Layout.fillHeight: true
Layout.fillWidth: true
QRCodeReader {
id: qrCodeReader
Component.onCompleted: {
qrCodeReader.setCameraSize(Qt.rect(parent.x,
parent.y,
parent.width,
parent.height))
qrCodeReader.startReading()
}
}
}
}
}

View file

@ -20,6 +20,10 @@ PageType {
popupErrorMessage.popupErrorMessageText = errorMessage
popupErrorMessage.open()
}
function onGoToPageViewConfig() {
goToPage(PageEnum.PageSetupWizardViewConfig)
}
}
FlickableType {

View file

@ -18,7 +18,7 @@ PageType {
enum ConfigType {
AmneziaConnection,
AmenziaFullAccess,
AmneziaFullAccess,
OpenVpn,
WireGuard
}
@ -33,7 +33,14 @@ PageType {
switch (type) {
case PageShare.ConfigType.AmneziaConnection: ExportController.generateConnectionConfig(); break;
case PageShare.ConfigType.AmenziaFullAccess: ExportController.generateFullAccessConfig(); break;
case PageShare.ConfigType.AmneziaFullAccess: {
if (Qt.platform.os === "android") {
ExportController.generateFullAccessConfigAndroid();
} else {
ExportController.generateFullAccessConfig();
}
break;
}
case PageShare.ConfigType.OpenVpn: ExportController.generateOpenVpnConfig(); break;
case PageShare.ConfigType.WireGuard: ExportController.generateWireGuardConfig(); break;
}
@ -48,6 +55,8 @@ PageType {
}
}
property string fullConfigServerSelectorText
property string connectionServerSelectorText
property bool showContent: false
property bool shareButtonEnabled: false
property list<QtObject> connectionTypesModel: [
@ -118,6 +127,7 @@ PageType {
onClicked: {
accessTypeSelector.currentIndex = 0
serverSelector.text = root.connectionServerSelectorText
}
}
@ -129,6 +139,7 @@ PageType {
onClicked: {
accessTypeSelector.currentIndex = 1
serverSelector.text = root.fullConfigServerSelectorText
}
}
}
@ -176,14 +187,24 @@ PageType {
currentIndex: 0
clickedFunction: function() {
serverSelector.text = selectedText
ServersModel.currentlyProcessedIndex = currentIndex
protocolSelector.visible = true
root.shareButtonEnabled = false
handler()
if (accessTypeSelector.currentIndex === 0) {
protocolSelector.visible = true
root.shareButtonEnabled = false
} else {
serverSelector.menuVisible = false
}
}
Component.onCompleted: {
handler()
}
function handler() {
serverSelector.text = selectedText
root.fullConfigServerSelectorText = selectedText
root.connectionServerSelectorText = selectedText
ServersModel.currentlyProcessedIndex = currentIndex
}
}
@ -260,7 +281,9 @@ PageType {
}
Component.onCompleted: {
handler()
if (accessTypeSelector.currentIndex === 0) {
handler()
}
}
function handler() {
@ -272,6 +295,8 @@ PageType {
}
serverSelector.text += ", " + selectedText
root.connectionServerSelectorText = serverSelector.text
shareConnectionDrawer.headerText = qsTr("Connection to ") + serverSelector.text
shareConnectionDrawer.configContentHeaderText = qsTr("File with connection settings to ") + serverSelector.text
ContainersModel.setCurrentlyProcessedContainerIndex(proxyContainersModel.mapToSource(currentIndex))

View file

@ -25,6 +25,11 @@ PageType {
tabBarStackView.goToTabBarPage(PageController.getPagePath(PageEnum.PageSettings))
}
function onGoToPageViewConfig() {
var pagePath = PageController.getPagePath(PageEnum.PageSetupWizardViewConfig)
tabBarStackView.push(pagePath, { "objectName" : pagePath }, StackView.PushTransition)
}
function onShowErrorMessage(errorMessage) {
popupErrorMessage.popupErrorMessageText = errorMessage
popupErrorMessage.open()
@ -35,6 +40,13 @@ PageType {
tabBarStackView.enabled = !visible
tabBar.enabled = !visible
}
function onClosePage() {
if (tabBarStackView.depth <= 1) {
return
}
tabBarStackView.pop()
}
}
StackViewType {

View file

@ -1,282 +0,0 @@
import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
import PageEnum 1.0
import "./"
import "../Controls2"
import "../Config"
import "../Controls2/TextTypes"
Item {
id: root
ColumnLayout {
id: content
anchors.top: parent.top
anchors.left: parent.left
anchors.right: parent.right
HeaderType {
id: header
Layout.rightMargin: 16
Layout.leftMargin: 16
Layout.topMargin: 20
Layout.bottomMargin: 32
Layout.fillWidth: true
backButtonImage: "qrc:/images/controls/arrow-left.svg"
headerText: "Server 1"
descriptionText: "root 192.168.111.111"
}
Item {
Layout.fillWidth: true
TabBar {
id: tabBar
anchors {
top: parent.top
right: parent.right
left: parent.left
}
background: Rectangle {
color: "transparent"
}
TabButtonType {
id: bb
isSelected: tabBar.currentIndex === 0
text: qsTr("Протоколы")
}
TabButtonType {
isSelected: tabBar.currentIndex === 1
text: qsTr("Сервисы")
}
TabButtonType {
isSelected: tabBar.currentIndex === 2
text: qsTr("Данные")
}
}
StackLayout {
id: stackLayout
currentIndex: tabBar.currentIndex
anchors.top: tabBar.bottom
anchors.topMargin: 16
width: parent.width
height: root.height - header.implicitHeight - tabBar.implicitHeight - 100
Item {
id: protocolsTab
FlickableType {
anchors.top: parent.top
anchors.bottom: parent.bottom
contentHeight: protocolsTabContent.height
ColumnLayout {
id: protocolsTabContent
anchors.top: parent.top
anchors.left: parent.left
anchors.right: parent.right
BasicButtonType {
Layout.fillWidth: true
Layout.leftMargin: 16
Layout.rightMargin: 16
text: qsTr("Forget this server")
}
BasicButtonType {
Layout.fillWidth: true
Layout.leftMargin: 16
Layout.rightMargin: 16
defaultColor: "transparent"
hoveredColor: Qt.rgba(255, 255, 255, 0.08)
pressedColor: Qt.rgba(255, 255, 255, 0.12)
disabledColor: "#878B91"
textColor: "#D7D8DB"
borderWidth: 1
text: qsTr("Forget this server")
}
TextFieldWithHeaderType {
Layout.fillWidth: true
Layout.leftMargin: 16
Layout.rightMargin: 16
headerText: "Server IP adress [:port]"
}
LabelWithButtonType {
id: ip
Layout.fillWidth: true
Layout.leftMargin: 16
Layout.rightMargin: 16
text: "IP, логин и пароль от сервера"
rightImageSource: "qrc:/images/controls/chevron-right.svg"
}
Rectangle {
Layout.fillWidth: true
Layout.leftMargin: 16
Layout.rightMargin: 16
height: 1
color: "#2C2D30"
}
LabelWithButtonType {
Layout.fillWidth: true
Layout.leftMargin: 16
Layout.rightMargin: 16
text: "QR-код, ключ или файл настроек"
rightImageSource: "qrc:/images/controls/chevron-right.svg"
}
Rectangle {
Layout.fillWidth: true
Layout.leftMargin: 16
Layout.rightMargin: 16
height: 1
color: "#2C2D30"
}
CardType {
Layout.fillWidth: true
Layout.leftMargin: 16
Layout.rightMargin: 16
headerText: "Высокий"
bodyText: "Многие иностранные сайты и VPN-провайдеры заблокированы"
footerText: "футер"
}
CardType {
Layout.fillWidth: true
Layout.leftMargin: 16
Layout.rightMargin: 16
headerText: "Высокий"
bodyText: "Многие иностранные сайты и VPN-провайдеры заблокированы"
footerText: "футер"
}
DropDownType {
Layout.fillWidth: true
text: "IP, логин и пароль от сервера"
descriptionText: "IP, логин и пароль от сервера"
menuModel: [
qsTr("SHA512"),
qsTr("SHA384"),
qsTr("SHA256"),
qsTr("SHA3-512"),
qsTr("SHA3-384"),
qsTr("SHA3-256"),
qsTr("whirlpool"),
qsTr("BLAKE2b512"),
qsTr("BLAKE2s256"),
qsTr("SHA1")
]
}
}
}
}
Item {
id: servicesTab
FlickableType {
anchors.top: parent.top
anchors.bottom: parent.bottom
contentHeight: servicesTabContent.height
ColumnLayout {
id: servicesTabContent
anchors.top: parent.top
anchors.left: parent.left
anchors.right: parent.right
CheckBoxType {
Layout.leftMargin: 16
Layout.rightMargin: 16
Layout.fillWidth: true
text: qsTr("Auto-negotiate encryption")
}
CheckBoxType {
Layout.leftMargin: 16
Layout.rightMargin: 16
Layout.fillWidth: true
text: qsTr("Auto-negotiate encryption")
descriptionText: qsTr("Auto-negotiate encryption")
}
Rectangle {
implicitWidth: buttonGroup.implicitWidth
implicitHeight: buttonGroup.implicitHeight
Layout.leftMargin: 16
Layout.rightMargin: 16
color: "#1C1D21"
radius: 16
RowLayout {
id: buttonGroup
spacing: 0
HorizontalRadioButton {
implicitWidth: (root.width - 32) / 2
text: "UDP"
}
HorizontalRadioButton {
implicitWidth: (root.width - 32) / 2
text: "TCP"
}
}
}
VerticalRadioButton {
text: "Раздельное туннелирование"
descriptionText: "Позволяет подключаться к одним сайтам через защищенное соединение, а к другим в обход него"
checked: true
Layout.fillWidth: true
Layout.leftMargin: 16
Layout.rightMargin: 16
}
VerticalRadioButton {
text: "Раздельное туннелирование"
Layout.fillWidth: true
Layout.leftMargin: 16
Layout.rightMargin: 16
}
SwitcherType {
text: "Auto-negotiate encryption"
Layout.fillWidth: true
Layout.leftMargin: 16
Layout.rightMargin: 16
}
}
}
}
}
}
}
}

View file

@ -18,10 +18,9 @@ Window {
color: "#0E0E11"
// todo
onClosing: function() {
console.debug("QML onClosing signal")
UiLogic.onCloseWindow()
PageController.closeWindow()
}
title: "AmneziaVPN"
@ -36,6 +35,11 @@ Window {
var pagePath = PageController.getInitialPage()
rootStackView.push(pagePath, { "objectName" : pagePath })
}
Keys.onPressed: function(event) {
PageController.keyPressEvent(event.key)
event.accepted = true
}
}
Connections {
@ -49,10 +53,14 @@ Window {
rootStackView.replace(pagePath, { "objectName" : pagePath })
}
function onRaise() {
function onRaiseMainWindow() {
root.show()
root.raise()
root.requestActivate()
}
function onHideMainWindow() {
root.hide()
}
}
}

View file

@ -10,79 +10,76 @@
#include <QKeyEvent>
#include <QMenu>
#include <QMetaEnum>
#include <QMetaObject>
#include <QQmlFile>
#include <QStandardPaths>
#include <QSysInfo>
#include <QThread>
#include <QTimer>
#include <QQmlFile>
#include <QMetaObject>
#include <QStandardPaths>
#include "amnezia_application.h"
#include "configurators/cloak_configurator.h"
#include "configurators/vpn_configurator.h"
#include "configurators/openvpn_configurator.h"
#include "configurators/shadowsocks_configurator.h"
#include "configurators/ssh_configurator.h"
#include "configurators/vpn_configurator.h"
#include "core/servercontroller.h"
#include "core/server_defs.h"
#include "core/errorstrings.h"
#include "core/server_defs.h"
#include "core/servercontroller.h"
#include "containers/containers_defs.h"
#include "ui/qautostart.h"
#include "logger.h"
#include "version.h"
#include "uilogic.h"
#include "utilities.h"
#include "version.h"
#include "vpnconnection.h"
#include <functional>
#if defined Q_OS_MAC || defined Q_OS_LINUX
#include "ui/macos_util.h"
#include "ui/macos_util.h"
#endif
#ifdef Q_OS_ANDROID
#include "platforms/android/android_controller.h"
#include "platforms/android/android_controller.h"
#endif
#include "platforms/ios/MobileUtils.h"
#include "pages_logic/AdvancedServerSettingsLogic.h"
#include "pages_logic/AppSettingsLogic.h"
#include "pages_logic/ClientInfoLogic.h"
#include "pages_logic/ClientManagementLogic.h"
#include "pages_logic/GeneralSettingsLogic.h"
#include "pages_logic/NetworkSettingsLogic.h"
#include "pages_logic/NewServerProtocolsLogic.h"
#include "pages_logic/QrDecoderLogic.h"
#include "pages_logic/ServerConfiguringProgressLogic.h"
#include "pages_logic/ServerContainersLogic.h"
#include "pages_logic/ServerListLogic.h"
#include "pages_logic/ServerSettingsLogic.h"
#include "pages_logic/ServerContainersLogic.h"
#include "pages_logic/ShareConnectionLogic.h"
#include "pages_logic/SitesLogic.h"
#include "pages_logic/StartPageLogic.h"
#include "pages_logic/ViewConfigLogic.h"
#include "pages_logic/VpnLogic.h"
#include "pages_logic/WizardLogic.h"
#include "pages_logic/AdvancedServerSettingsLogic.h"
#include "pages_logic/ClientManagementLogic.h"
#include "pages_logic/ClientInfoLogic.h"
#include "pages_logic/protocols/CloakLogic.h"
#include "pages_logic/protocols/OpenVpnLogic.h"
#include "pages_logic/protocols/ShadowSocksLogic.h"
#include "pages_logic/protocols/OtherProtocolsLogic.h"
#include "pages_logic/protocols/ShadowSocksLogic.h"
#include "pages_logic/protocols/WireGuardLogic.h"
using namespace amnezia;
using namespace PageEnumNS;
UiLogic::UiLogic(std::shared_ptr<Settings> settings, std::shared_ptr<VpnConfigurator> configurator,
QObject *parent) :
QObject(parent),
m_settings(settings),
m_configurator(configurator)
UiLogic::UiLogic(std::shared_ptr<Settings> settings, std::shared_ptr<VpnConfigurator> configurator, QObject *parent)
: QObject(parent), m_settings(settings), m_configurator(configurator)
{
m_protocolsModel = new ProtocolsModel(settings, this);
m_clientManagementModel = new ClientManagementModel(this);
@ -90,7 +87,6 @@ UiLogic::UiLogic(std::shared_ptr<Settings> settings, std::shared_ptr<VpnConfigur
m_vpnConnection->moveToThread(&m_vpnConnectionThread);
m_vpnConnectionThread.start();
m_protocolLogicMap.insert(Proto::OpenVpn, new OpenVpnLogic(this));
m_protocolLogicMap.insert(Proto::ShadowSocks, new ShadowSocksLogic(this));
m_protocolLogicMap.insert(Proto::Cloak, new CloakLogic(this));
@ -99,7 +95,6 @@ UiLogic::UiLogic(std::shared_ptr<Settings> settings, std::shared_ptr<VpnConfigur
m_protocolLogicMap.insert(Proto::Dns, new OtherProtocolsLogic(this));
m_protocolLogicMap.insert(Proto::Sftp, new OtherProtocolsLogic(this));
m_protocolLogicMap.insert(Proto::TorWebSite, new OtherProtocolsLogic(this));
}
UiLogic::~UiLogic()
@ -129,33 +124,37 @@ UiLogic::~UiLogic()
void UiLogic::initializeUiLogic()
{
#ifdef Q_OS_ANDROID
connect(AndroidController::instance(), &AndroidController::initialized, [this](bool status, bool connected, const QDateTime& connectionDate) {
if (connected) {
pageLogic<VpnLogic>()->onConnectionStateChanged(Vpn::ConnectionState::Connected);
if (m_vpnConnection) m_vpnConnection->restoreConnection();
}
});
if (!AndroidController::instance()->initialize(pageLogic<StartPageLogic>())) {
qCritical() << QString("Init failed");
if (m_vpnConnection) m_vpnConnection->connectionStateChanged(Vpn::ConnectionState::Error);
return;
}
connect(AndroidController::instance(), &AndroidController::initialized,
[this](bool status, bool connected, const QDateTime &connectionDate) {
if (connected) {
pageLogic<VpnLogic>()->onConnectionStateChanged(Vpn::ConnectionState::Connected);
if (m_vpnConnection)
m_vpnConnection->restoreConnection();
}
});
// if (!AndroidController::instance()->initialize(pageLogic<StartPageLogic>())) {
// qCritical() << QString("Init failed");
// if (m_vpnConnection) m_vpnConnection->connectionStateChanged(Vpn::ConnectionState::Error);
// return;
// }
#endif
m_notificationHandler = NotificationHandler::create(qmlRoot());
connect(m_vpnConnection, &VpnConnection::connectionStateChanged, m_notificationHandler, &NotificationHandler::setConnectionState);
connect(m_vpnConnection, &VpnConnection::connectionStateChanged, m_notificationHandler,
&NotificationHandler::setConnectionState);
connect(m_notificationHandler, &NotificationHandler::raiseRequested, this, &UiLogic::raise);
connect(m_notificationHandler, &NotificationHandler::connectRequested, pageLogic<VpnLogic>(), &VpnLogic::onConnect);
connect(m_notificationHandler, &NotificationHandler::disconnectRequested, pageLogic<VpnLogic>(), &VpnLogic::onDisconnect);
connect(m_notificationHandler, &NotificationHandler::disconnectRequested, pageLogic<VpnLogic>(),
&VpnLogic::onDisconnect);
// if (m_settings->serversCount() > 0) {
// if (m_settings->defaultServerIndex() < 0) m_settings->setDefaultServer(0);
// emit goToPage(Page::PageStart, true, false);
// }
// else {
// emit goToPage(Page::PageSetupWizardStart, true, false);
// }
// if (m_settings->serversCount() > 0) {
// if (m_settings->defaultServerIndex() < 0) m_settings->setDefaultServer(0);
// emit goToPage(Page::PageStart, true, false);
// }
// else {
// emit goToPage(Page::PageSetupWizardStart, true, false);
// }
m_selectedServerIndex = m_settings->defaultServerIndex();
@ -165,14 +164,13 @@ void UiLogic::initializeUiLogic()
void UiLogic::showOnStartup()
{
if (! m_settings->isStartMinimized()) {
if (!m_settings->isStartMinimized()) {
emit show();
}
else {
} else {
#ifdef Q_OS_WIN
emit hide();
#elif defined Q_OS_MACX
// TODO: fix: setDockIconVisible(false);
// TODO: fix: setDockIconVisible(false);
#endif
}
}
@ -180,7 +178,7 @@ void UiLogic::showOnStartup()
void UiLogic::onUpdateAllPages()
{
for (auto logic : m_logicMap) {
if (dynamic_cast<ClientInfoLogic*>(logic) || dynamic_cast<ClientManagementLogic*>(logic)) {
if (dynamic_cast<ClientInfoLogic *>(logic) || dynamic_cast<ClientManagementLogic *>(logic)) {
continue;
}
logic->onUpdatePage();
@ -191,57 +189,50 @@ void UiLogic::keyPressEvent(Qt::Key key)
{
switch (key) {
case Qt::Key_AsciiTilde:
case Qt::Key_QuoteLeft: emit toggleLogPanel();
break;
case Qt::Key_L: Logger::openLogsFolder();
break;
case Qt::Key_K: Logger::openServiceLogsFolder();
break;
case Qt::Key_QuoteLeft: emit toggleLogPanel(); break;
case Qt::Key_L: Logger::openLogsFolder(); break;
case Qt::Key_K: Logger::openServiceLogsFolder(); break;
#ifdef QT_DEBUG
case Qt::Key_Q:
qApp->quit();
break;
case Qt::Key_Q: qApp->quit(); break;
case Qt::Key_H:
m_selectedServerIndex = m_settings->defaultServerIndex();
m_selectedDockerContainer = m_settings->defaultContainer(m_selectedServerIndex);
//updateSharingPage(selectedServerIndex, m_settings->serverCredentials(selectedServerIndex), selectedDockerContainer);
// updateSharingPage(selectedServerIndex, m_settings->serverCredentials(selectedServerIndex), selectedDockerContainer);
emit goToPage(Page::ShareConnection);
break;
#endif
case Qt::Key_C:
qDebug().noquote() << "Def server" << m_settings->defaultServerIndex() << m_settings->defaultContainerName(m_settings->defaultServerIndex());
qDebug().noquote() << "Def server" << m_settings->defaultServerIndex()
<< m_settings->defaultContainerName(m_settings->defaultServerIndex());
qDebug().noquote() << QJsonDocument(m_settings->defaultServer()).toJson();
break;
case Qt::Key_A:
emit goToPage(Page::Start);
break;
case Qt::Key_A: emit goToPage(Page::Start); break;
case Qt::Key_S:
m_selectedServerIndex = m_settings->defaultServerIndex();
emit goToPage(Page::ServerSettings);
break;
case Qt::Key_P:
onGotoCurrentProtocolsPage();
break;
case Qt::Key_P: onGotoCurrentProtocolsPage(); break;
case Qt::Key_T:
m_configurator->sshConfigurator->openSshTerminal(m_settings->serverCredentials(m_settings->defaultServerIndex()));
break;
case Qt::Key_Escape:
if (currentPage() == Page::Vpn) break;
if (currentPage() == Page::ServerConfiguringProgress) break;
if (currentPage() == Page::Vpn)
break;
if (currentPage() == Page::ServerConfiguringProgress)
break;
case Qt::Key_Back:
// if (currentPage() == Page::Start && pagesStack.size() < 2) break;
// if (currentPage() == Page::Sites &&
// ui->tableView_sites->selectionModel()->selection().indexes().size() > 0) {
// ui->tableView_sites->clearSelection();
// break;
// }
// if (currentPage() == Page::Start && pagesStack.size() < 2) break;
// if (currentPage() == Page::Sites &&
// ui->tableView_sites->selectionModel()->selection().indexes().size() > 0) {
// ui->tableView_sites->clearSelection();
// break;
// }
emit closePage();
emit closePage();
//}
default:
;
default:;
}
}
@ -250,8 +241,7 @@ void UiLogic::onCloseWindow()
#ifdef Q_OS_ANDROID
qApp->quit();
#else
if (m_settings->serversCount() == 0)
{
if (m_settings->serversCount() == 0) {
qApp->quit();
} else {
emit hide();
@ -267,7 +257,6 @@ QString UiLogic::containerName(int container)
QString UiLogic::containerDesc(int container)
{
return ContainerProps::containerDescriptions().value(static_cast<DockerContainer>(container));
}
void UiLogic::onGotoCurrentProtocolsPage()
@ -286,50 +275,50 @@ void UiLogic::installServer(QPair<DockerContainer, QJsonObject> &container)
qApp->processEvents();
ServerConfiguringProgressLogic::PageFunc pageFunc;
pageFunc.setEnabledFunc = [this] (bool enabled) -> void {
pageFunc.setEnabledFunc = [this](bool enabled) -> void {
pageLogic<ServerConfiguringProgressLogic>()->set_pageEnabled(enabled);
};
ServerConfiguringProgressLogic::ButtonFunc noButton;
ServerConfiguringProgressLogic::LabelFunc waitInfoFunc;
waitInfoFunc.setTextFunc = [this] (const QString& text) -> void {
waitInfoFunc.setTextFunc = [this](const QString &text) -> void {
pageLogic<ServerConfiguringProgressLogic>()->set_labelWaitInfoText(text);
};
waitInfoFunc.setVisibleFunc = [this] (bool visible) -> void {
waitInfoFunc.setVisibleFunc = [this](bool visible) -> void {
pageLogic<ServerConfiguringProgressLogic>()->set_labelWaitInfoVisible(visible);
};
ServerConfiguringProgressLogic::ProgressFunc progressBarFunc;
progressBarFunc.setVisibleFunc = [this] (bool visible) -> void {
progressBarFunc.setVisibleFunc = [this](bool visible) -> void {
pageLogic<ServerConfiguringProgressLogic>()->set_progressBarVisible(visible);
};
progressBarFunc.setValueFunc = [this] (int value) -> void {
progressBarFunc.setValueFunc = [this](int value) -> void {
pageLogic<ServerConfiguringProgressLogic>()->set_progressBarValue(value);
};
progressBarFunc.getValueFunc = [this] (void) -> int {
progressBarFunc.getValueFunc = [this](void) -> int {
return pageLogic<ServerConfiguringProgressLogic>()->progressBarValue();
};
progressBarFunc.getMaximumFunc = [this] (void) -> int {
progressBarFunc.getMaximumFunc = [this](void) -> int {
return pageLogic<ServerConfiguringProgressLogic>()->progressBarMaximum();
};
progressBarFunc.setTextVisibleFunc = [this] (bool visible) -> void {
progressBarFunc.setTextVisibleFunc = [this](bool visible) -> void {
pageLogic<ServerConfiguringProgressLogic>()->set_progressBarTextVisible(visible);
};
progressBarFunc.setTextFunc = [this] (const QString& text) -> void {
progressBarFunc.setTextFunc = [this](const QString &text) -> void {
pageLogic<ServerConfiguringProgressLogic>()->set_progressBarText(text);
};
ServerConfiguringProgressLogic::LabelFunc busyInfoFunc;
busyInfoFunc.setTextFunc = [this] (const QString& text) -> void {
busyInfoFunc.setTextFunc = [this](const QString &text) -> void {
pageLogic<ServerConfiguringProgressLogic>()->set_labelServerBusyText(text);
};
busyInfoFunc.setVisibleFunc = [this] (bool visible) -> void {
busyInfoFunc.setVisibleFunc = [this](bool visible) -> void {
pageLogic<ServerConfiguringProgressLogic>()->set_labelServerBusyVisible(visible);
};
ServerConfiguringProgressLogic::ButtonFunc cancelButtonFunc;
cancelButtonFunc.setVisibleFunc = [this] (bool visible) -> void {
cancelButtonFunc.setVisibleFunc = [this](bool visible) -> void {
pageLogic<ServerConfiguringProgressLogic>()->set_pushButtonCancelVisible(visible);
};
@ -338,13 +327,12 @@ void UiLogic::installServer(QPair<DockerContainer, QJsonObject> &container)
if (errorCode == ErrorCode::NoError) {
if (!isContainerAlreadyAddedToGui(container.first)) {
progressBarFunc.setTextFunc(QString("Installing %1").arg(ContainerProps::containerToString(container.first)));
auto installAction = [&] () {
auto installAction = [&]() {
ServerController serverController(m_settings);
return serverController.setupContainer(m_installCredentials, container.first, container.second);
};
errorCode = pageLogic<ServerConfiguringProgressLogic>()->doInstallAction(installAction, pageFunc, progressBarFunc,
noButton, waitInfoFunc,
busyInfoFunc, cancelButtonFunc);
errorCode = pageLogic<ServerConfiguringProgressLogic>()->doInstallAction(
installAction, pageFunc, progressBarFunc, noButton, waitInfoFunc, busyInfoFunc, cancelButtonFunc);
if (errorCode == ErrorCode::NoError) {
if (!isServerCreated) {
QJsonObject server;
@ -354,7 +342,7 @@ void UiLogic::installServer(QPair<DockerContainer, QJsonObject> &container)
server.insert(config_key::port, m_installCredentials.port);
server.insert(config_key::description, m_settings->nextAvailableServerName());
server.insert(config_key::containers, QJsonArray{container.second});
server.insert(config_key::containers, QJsonArray { container.second });
server.insert(config_key::defaultContainer, ContainerProps::containerToString(container.first));
m_settings->addServer(server);
@ -371,22 +359,23 @@ void UiLogic::installServer(QPair<DockerContainer, QJsonObject> &container)
}
} else {
onUpdateAllPages();
emit showWarningMessage("Attention! The container you are trying to install is already installed on the server. "
"All installed containers have been added to the application ");
emit showWarningMessage(
"Attention! The container you are trying to install is already installed on the server. "
"All installed containers have been added to the application ");
emit setStartPage(Page::Vpn);
return;
}
}
emit showWarningMessage(tr("Error occurred while configuring server.") + "\n" +
tr("Error message: ") + errorString(errorCode) + "\n" +
tr("See logs for details."));
emit showWarningMessage(tr("Error occurred while configuring server.") + "\n" + tr("Error message: ")
+ errorString(errorCode) + "\n" + tr("See logs for details."));
emit closePage();
}
PageProtocolLogicBase *UiLogic::protocolLogic(Proto p)
{
PageProtocolLogicBase *logic = m_protocolLogicMap.value(p);
if (logic) return logic;
if (logic)
return logic;
else {
qCritical() << "UiLogic::protocolLogic Warning: logic missing for" << p;
return new PageProtocolLogicBase(this);
@ -418,7 +407,7 @@ PageEnumNS::Page UiLogic::currentPage()
return static_cast<PageEnumNS::Page>(currentPageValue());
}
void UiLogic::saveTextFile(const QString& desc, const QString& suggestedName, QString ext, const QString& data)
void UiLogic::saveTextFile(const QString &desc, const QString &suggestedName, QString ext, const QString &data)
{
#ifdef Q_OS_IOS
shareTempFile(suggestedName, ext, data);
@ -429,17 +418,19 @@ void UiLogic::saveTextFile(const QString& desc, const QString& suggestedName, QS
QString docDir = QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation);
QUrl fileName;
#ifdef AMNEZIA_DESKTOP
fileName = QFileDialog::getSaveFileUrl(nullptr, desc,
QUrl::fromLocalFile(docDir + "/" + suggestedName), "*" + ext);
if (fileName.isEmpty()) return;
if (!fileName.toString().endsWith(ext)) fileName = QUrl(fileName.toString() + ext);
fileName = QFileDialog::getSaveFileUrl(nullptr, desc, QUrl::fromLocalFile(docDir + "/" + suggestedName), "*" + ext);
if (fileName.isEmpty())
return;
if (!fileName.toString().endsWith(ext))
fileName = QUrl(fileName.toString() + ext);
#elif defined Q_OS_ANDROID
qDebug() << "UiLogic::shareConfig" << data;
AndroidController::instance()->shareConfig(data, suggestedName);
return;
#endif
if (fileName.isEmpty()) return;
if (fileName.isEmpty())
return;
#ifdef AMNEZIA_DESKTOP
QFile save(fileName.toLocalFile());
@ -458,11 +449,13 @@ void UiLogic::saveTextFile(const QString& desc, const QString& suggestedName, QS
void UiLogic::saveBinaryFile(const QString &desc, QString ext, const QString &data)
{
ext.replace("*", "");
QString fileName = QFileDialog::getSaveFileName(nullptr, desc,
QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation), "*" + ext);
QString fileName = QFileDialog::getSaveFileName(
nullptr, desc, QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation), "*" + ext);
if (fileName.isEmpty()) return;
if (!fileName.endsWith(ext)) fileName.append(ext);
if (fileName.isEmpty())
return;
if (!fileName.endsWith(ext))
fileName.append(ext);
QFile save(fileName);
save.open(QIODevice::WriteOnly);
@ -478,12 +471,15 @@ void UiLogic::copyToClipboard(const QString &text)
qApp->clipboard()->setText(text);
}
void UiLogic::shareTempFile(const QString &suggestedName, QString ext, const QString& data) {
void UiLogic::shareTempFile(const QString &suggestedName, QString ext, const QString &data)
{
ext.replace("*", "");
QString fileName = QDir::tempPath() + "/" + suggestedName;
if (fileName.isEmpty()) return;
if (!fileName.endsWith(ext)) fileName.append(ext);
if (fileName.isEmpty())
return;
if (!fileName.endsWith(ext))
fileName.append(ext);
QFile::remove(fileName);
@ -497,14 +493,14 @@ void UiLogic::shareTempFile(const QString &suggestedName, QString ext, const QSt
MobileUtils::shareText(filesToSend);
}
QString UiLogic::getOpenFileName(QWidget *parent, const QString &caption, const QString &dir,
const QString &filter, QString *selectedFilter, QFileDialog::Options options)
QString UiLogic::getOpenFileName(QWidget *parent, const QString &caption, const QString &dir, const QString &filter,
QString *selectedFilter, QFileDialog::Options options)
{
QString fileName = QFileDialog::getOpenFileName(parent, caption, dir, filter, selectedFilter, options);
#ifdef Q_OS_ANDROID
// patch for files containing spaces etc
const QString sep {"raw%3A%2F"};
const QString sep { "raw%3A%2F" };
if (fileName.startsWith("content://") && fileName.contains(sep)) {
QString contentUrl = fileName.split(sep).at(0);
QString rawUrl = fileName.split(sep).at(1);
@ -590,7 +586,8 @@ ErrorCode UiLogic::addAlreadyInstalledContainersGui(bool &isServerCreated)
}
if (createNewServer) {
server.insert(config_key::defaultContainer, ContainerProps::containerToString(installedContainers.firstKey()));
server.insert(config_key::defaultContainer,
ContainerProps::containerToString(installedContainers.firstKey()));
m_settings->addServer(server);
m_settings->setDefaultServer(m_settings->serversCount() - 1);
isServerCreated = true;