From 08a8eadb49f94edf59ab6b0f28307bc90fa1eaa0 Mon Sep 17 00:00:00 2001 From: "vladimir.kuznetsov" Date: Sun, 1 Jan 2023 21:48:20 +0300 Subject: [PATCH] added display of a notification that the server is busy installing third-party software - refactoring doInstallAction functions --- client/CMakeLists.txt | 4 +- client/core/scripts_registry.cpp | 1 + client/core/scripts_registry.h | 3 +- client/core/servercontroller.cpp | 34 ++- client/core/servercontroller.h | 3 + client/resources.qrc | 1 + client/server_scripts/check_server_is_busy.sh | 4 + client/server_scripts/install_docker.sh | 2 +- .../ServerConfiguringProgressLogic.cpp | 68 +++-- .../ServerConfiguringProgressLogic.h | 27 +- .../ui/pages_logic/protocols/CloakLogic.cpp | 58 +++-- client/ui/pages_logic/protocols/CloakLogic.h | 4 + .../ui/pages_logic/protocols/OpenVpnLogic.cpp | 58 +++-- .../ui/pages_logic/protocols/OpenVpnLogic.h | 5 + .../protocols/ShadowSocksLogic.cpp | 74 ++++-- .../pages_logic/protocols/ShadowSocksLogic.h | 10 +- .../Pages/PageServerConfiguringProgress.qml | 16 ++ .../ui/qml/Pages/Protocols/PageProtoCloak.qml | 30 ++- .../qml/Pages/Protocols/PageProtoOpenVPN.qml | 32 ++- .../Pages/Protocols/PageProtoShadowSocks.qml | 46 +++- client/ui/uilogic.cpp | 232 +++--------------- client/ui/uilogic.h | 32 --- 22 files changed, 398 insertions(+), 346 deletions(-) create mode 100644 client/server_scripts/check_server_is_busy.sh diff --git a/client/CMakeLists.txt b/client/CMakeLists.txt index 8aeddc32..82b3b4fd 100644 --- a/client/CMakeLists.txt +++ b/client/CMakeLists.txt @@ -21,13 +21,13 @@ set_property(GLOBAL PROPERTY PREDEFINED_TARGETS_FOLDER "Autogen") find_package(Qt6 REQUIRED COMPONENTS Widgets Core Gui Network Xml RemoteObjects Quick Svg QuickControls2 - Core5Compat + Core5Compat Concurrent ) set(LIBS ${LIBS} Qt6::Widgets Qt6::Core Qt6::Gui Qt6::Network Qt6::Xml Qt6::RemoteObjects Qt6::Quick Qt6::Svg Qt6::QuickControls2 - Qt6::Core5Compat + Qt6::Core5Compat Qt6::Concurrent ) qt_standard_project_setup() diff --git a/client/core/scripts_registry.cpp b/client/core/scripts_registry.cpp index 77c056bd..d33881a2 100644 --- a/client/core/scripts_registry.cpp +++ b/client/core/scripts_registry.cpp @@ -31,6 +31,7 @@ QString amnezia::scriptName(SharedScriptType type) case SharedScriptType::remove_all_containers: return QLatin1String("remove_all_containers.sh"); case SharedScriptType::setup_host_firewall: return QLatin1String("setup_host_firewall.sh"); case SharedScriptType::check_connection: return QLatin1String("check_connection.sh"); + case SharedScriptType::check_server_is_busy: return QLatin1String("check_server_is_busy.sh"); } } diff --git a/client/core/scripts_registry.h b/client/core/scripts_registry.h index 3d69d95a..9528d763 100644 --- a/client/core/scripts_registry.h +++ b/client/core/scripts_registry.h @@ -15,7 +15,8 @@ enum SharedScriptType { remove_container, remove_all_containers, setup_host_firewall, - check_connection + check_connection, + check_server_is_busy }; enum ProtocolScriptType { // Protocol scripts diff --git a/client/core/servercontroller.cpp b/client/core/servercontroller.cpp index c7336b62..ef1511b2 100644 --- a/client/core/servercontroller.cpp +++ b/client/core/servercontroller.cpp @@ -12,6 +12,8 @@ #include #include #include +#include +#include #include "sftpchannel.h" #include "sshconnectionmanager.h" @@ -528,14 +530,36 @@ ErrorCode ServerController::installDockerWorker(const ServerCredentials &credent stdOut += data + "\n"; }; - ErrorCode e = runScript(credentials, - replaceVars(amnezia::scriptData(SharedScriptType::install_docker), - genVarsForScript(credentials)), - cbReadStdOut, cbReadStdErr); + QFutureWatcher watcher; + + QFuture future = QtConcurrent::run([this, &stdOut, &cbReadStdOut, &cbReadStdErr, &credentials]() { + do { + stdOut.clear(); + runScript(credentials, + replaceVars(amnezia::scriptData(SharedScriptType::check_server_is_busy), + genVarsForScript(credentials)), cbReadStdOut, cbReadStdErr); + if (!stdOut.isEmpty() || stdOut.contains("Unable to acquire the dpkg frontend lock")) { + emit serverIsBusy(true); + QThread::msleep(1000); + } + } while (!stdOut.isEmpty()); + }); + + watcher.setFuture(future); + + QEventLoop wait; + QObject::connect(&watcher, &QFutureWatcher::finished, &wait, &QEventLoop::quit); + wait.exec(); + + emit serverIsBusy(false); + + ErrorCode error = runScript(credentials, + replaceVars(amnezia::scriptData(SharedScriptType::install_docker), + genVarsForScript(credentials)), cbReadStdOut, cbReadStdErr); if (stdOut.contains("command not found")) return ErrorCode::ServerDockerFailedError; - return e; + return error; } ErrorCode ServerController::prepareHostWorker(const ServerCredentials &credentials, DockerContainer container, const QJsonObject &config) diff --git a/client/core/servercontroller.h b/client/core/servercontroller.h index 091eaa52..b151dc54 100644 --- a/client/core/servercontroller.h +++ b/client/core/servercontroller.h @@ -84,6 +84,9 @@ private: std::shared_ptr m_settings; std::shared_ptr m_configurator; + +signals: + void serverIsBusy(const bool isBusy); }; #endif // SERVERCONTROLLER_H diff --git a/client/resources.qrc b/client/resources.qrc index a7e67e39..75a410d0 100644 --- a/client/resources.qrc +++ b/client/resources.qrc @@ -160,5 +160,6 @@ ui/qml/Pages/PageQrDecoderIos.qml server_scripts/website_tor/Dockerfile ui/qml/Pages/PageViewConfig.qml + server_scripts/check_server_is_busy.sh diff --git a/client/server_scripts/check_server_is_busy.sh b/client/server_scripts/check_server_is_busy.sh new file mode 100644 index 00000000..17c27864 --- /dev/null +++ b/client/server_scripts/check_server_is_busy.sh @@ -0,0 +1,4 @@ +pm_apt="/usr/bin/apt-get";\ +if [[ -f "$pm_apt" ]]; then pm=$pm_apt; else exit; fi;\ +if [[ ! -f "/usr/bin/sudo" ]]; then $pm update -y -q; $pm install -y -q sudo; fi;\ +sudo fuser /var/lib/dpkg/lock-frontend \ No newline at end of file diff --git a/client/server_scripts/install_docker.sh b/client/server_scripts/install_docker.sh index baff7cb6..e12ab2c1 100644 --- a/client/server_scripts/install_docker.sh +++ b/client/server_scripts/install_docker.sh @@ -3,7 +3,7 @@ if [[ -f "$pm_apt" ]]; then pm=$pm_apt; docker_pkg="docker.io"; else pm=$pm_yum; if [[ ! -f "/usr/bin/sudo" ]]; then $pm update -y -q; $pm install -y -q sudo; fi;\ docker_service=$(systemctl list-units --full -all | grep docker.service | grep -v inactive | grep -v dead | grep -v failed);\ if [[ -f "$pm_apt" ]]; then export DEBIAN_FRONTEND=noninteractive; fi;\ -if [[ -z "$docker_service" ]]; then sudo $pm update -y -q; sudo $pm install -y -q curl $docker_pkg; fi;\ +if [[ -z "$docker_service" ]]; then sudo $pm update -y -q; sudo $pm install -y -q curl $docker_pkg; fi;\ docker_service=$(systemctl list-units --full -all | grep docker.service | grep -v inactive | grep -v dead | grep -v failed);\ if [[ -z "$docker_service" ]]; then sleep 5 && sudo systemctl start docker && sleep 5; fi;\ docker --version diff --git a/client/ui/pages_logic/ServerConfiguringProgressLogic.cpp b/client/ui/pages_logic/ServerConfiguringProgressLogic.cpp index 32ae366d..23697181 100644 --- a/client/ui/pages_logic/ServerConfiguringProgressLogic.cpp +++ b/client/ui/pages_logic/ServerConfiguringProgressLogic.cpp @@ -5,6 +5,8 @@ #include #include +#include "core/servercontroller.h" + ServerConfiguringProgressLogic::ServerConfiguringProgressLogic(UiLogic *logic, QObject *parent): PageLogicBase(logic, parent), m_progressBarValue{0}, @@ -13,7 +15,9 @@ ServerConfiguringProgressLogic::ServerConfiguringProgressLogic(UiLogic *logic, Q m_progressBarVisible{true}, m_progressBarMaximium{100}, m_progressBarTextVisible{true}, - m_progressBarText{tr("Configuring...")} + m_progressBarText{tr("Configuring...")}, + m_labelServerBusyVisible{false}, + m_labelServerBusyText{""} { } @@ -30,14 +34,14 @@ ErrorCode ServerConfiguringProgressLogic::doInstallAction(const std::function void { set_pageEnabled(enabled); }; - ButtonFunc button; - LabelFunc info; + ButtonFunc noButton; + LabelFunc noWaitInfo; ProgressFunc progress; - progress.setVisibleFunc = [this] (bool visible) ->void { + progress.setVisibleFunc = [this] (bool visible) -> void { set_progressBarVisible(visible); }; - progress.setValueFunc = [this] (int value) ->void { + progress.setValueFunc = [this] (int value) -> void { set_progressBarValue(value); }; progress.getValueFunc = [this] (void) -> int { @@ -47,8 +51,24 @@ ErrorCode ServerConfiguringProgressLogic::doInstallAction(const std::function void { + set_labelServerBusyText(text); + }; + busyInfo.setVisibleFunc = [this] (bool visible) -> void { + set_labelServerBusyVisible(visible); + }; + return doInstallAction(action, page, progress, noButton, noWaitInfo, busyInfo); +} +ErrorCode ServerConfiguringProgressLogic::doInstallAction(const std::function &action, + const PageFunc &page, + const ProgressFunc &progress, + const ButtonFunc &button, + const LabelFunc &waitInfo, + const LabelFunc &serverBusyInfo) +{ progress.setVisibleFunc(true); if (page.setEnabledFunc) { page.setEnabledFunc(false); @@ -56,11 +76,11 @@ ErrorCode ServerConfiguringProgressLogic::doInstallAction(const std::function 0) { + if (remainingVal > 0) { QTimer timer1; QEventLoop loop1; @@ -120,8 +158,8 @@ ErrorCode ServerConfiguringProgressLogic::doInstallAction(const std::function &action); + AUTO_PROPERTY(bool, labelServerBusyVisible) + AUTO_PROPERTY(QString, labelServerBusyText) private: struct ProgressFunc { @@ -48,5 +43,23 @@ private: std::function setTextFunc; }; +public: + explicit ServerConfiguringProgressLogic(UiLogic *uiLogic, QObject *parent = nullptr); + ~ServerConfiguringProgressLogic() = default; + + friend class OpenVpnLogic; + friend class ShadowSocksLogic; + friend class CloakLogic; + friend class UiLogic; + + void onUpdatePage() override; + ErrorCode doInstallAction(const std::function &action); + ErrorCode doInstallAction(const std::function &action, + const PageFunc &page, + const ProgressFunc &progress, + const ButtonFunc &button, + const LabelFunc &waitInfo, + const LabelFunc &serverBusyInfo); + }; #endif // SERVER_CONFIGURING_PROGRESS_LOGIC_H diff --git a/client/ui/pages_logic/protocols/CloakLogic.cpp b/client/ui/pages_logic/protocols/CloakLogic.cpp index 59019990..1456e457 100644 --- a/client/ui/pages_logic/protocols/CloakLogic.cpp +++ b/client/ui/pages_logic/protocols/CloakLogic.cpp @@ -1,7 +1,10 @@ #include "CloakLogic.h" -#include "core/servercontroller.h" + #include -#include "../../uilogic.h" + +#include "core/servercontroller.h" +#include "ui/uilogic.h" +#include "ui/pages_logic/ServerConfiguringProgressLogic.h" using namespace amnezia; using namespace PageEnumNS; @@ -59,40 +62,59 @@ void CloakLogic::onPushButtonSaveClicked() QJsonObject newContainerConfig = containerConfig; newContainerConfig.insert(ProtocolProps::protoToString(Proto::Cloak), protocolConfig); - UiLogic::PageFunc page_func; - page_func.setEnabledFunc = [this] (bool enabled) -> void { + ServerConfiguringProgressLogic::PageFunc pageFunc; + pageFunc.setEnabledFunc = [this] (bool enabled) -> void { set_pageEnabled(enabled); }; - UiLogic::ButtonFunc pushButton_save_func; - pushButton_save_func.setVisibleFunc = [this] (bool visible) ->void { + ServerConfiguringProgressLogic::ButtonFunc saveButtonFunc; + saveButtonFunc.setVisibleFunc = [this] (bool visible) -> void { set_pushButtonSaveVisible(visible); }; - UiLogic::LabelFunc label_info_func; - label_info_func.setVisibleFunc = [this] (bool visible) ->void { + ServerConfiguringProgressLogic::LabelFunc waitInfoFunc; + waitInfoFunc.setVisibleFunc = [this] (bool visible) -> void { set_labelInfoVisible(visible); }; - label_info_func.setTextFunc = [this] (const QString& text) ->void { + waitInfoFunc.setTextFunc = [this] (const QString& text) -> void { set_labelInfoText(text); }; - UiLogic::ProgressFunc progressBar_reset; - progressBar_reset.setVisibleFunc = [this] (bool visible) ->void { + ServerConfiguringProgressLogic::ProgressFunc progressBarFunc; + progressBarFunc.setVisibleFunc = [this] (bool visible) -> void { set_progressBarResetVisible(visible); }; - progressBar_reset.setValueFunc = [this] (int value) ->void { + progressBarFunc.setValueFunc = [this] (int value) -> void { set_progressBarResetValue(value); }; - progressBar_reset.getValueFunc = [this] (void) -> int { + progressBarFunc.getValueFunc = [this] (void) -> int { return progressBarResetValue(); }; - progressBar_reset.getMaximiumFunc = [this] (void) -> int { + progressBarFunc.getMaximiumFunc = [this] (void) -> int { return progressBarResetMaximium(); }; + progressBarFunc.setTextVisibleFunc = [this] (bool visible) -> void { + set_progressBarTextVisible(visible); + }; + progressBarFunc.setTextFunc = [this] (const QString& text) -> void { + set_progressBarText(text); + }; - ErrorCode e = uiLogic()->doInstallAction([this, containerConfig, &newContainerConfig](){ - return m_serverController->updateContainer(m_settings->serverCredentials(uiLogic()->selectedServerIndex), uiLogic()->selectedDockerContainer, containerConfig, newContainerConfig); + ServerConfiguringProgressLogic::LabelFunc busyInfoFuncy; + busyInfoFuncy.setTextFunc = [this] (const QString& text) -> void { + set_labelServerBusyText(text); + }; + busyInfoFuncy.setVisibleFunc = [this] (bool visible) -> void { + set_labelServerBusyVisible(visible); + }; + + progressBarFunc.setTextVisibleFunc(true); + progressBarFunc.setTextFunc(QString("Configuring...")); + ErrorCode e = uiLogic()->pageLogic()->doInstallAction([this, containerConfig, &newContainerConfig](){ + return m_serverController->updateContainer(m_settings->serverCredentials(uiLogic()->selectedServerIndex), + uiLogic()->selectedDockerContainer, + containerConfig, + newContainerConfig); }, - page_func, progressBar_reset, - pushButton_save_func, label_info_func); + pageFunc, progressBarFunc, + saveButtonFunc, waitInfoFunc, busyInfoFuncy); if (!e) { m_settings->setContainerConfig(uiLogic()->selectedServerIndex, uiLogic()->selectedDockerContainer, newContainerConfig); diff --git a/client/ui/pages_logic/protocols/CloakLogic.h b/client/ui/pages_logic/protocols/CloakLogic.h index d88252c8..57afb5b0 100644 --- a/client/ui/pages_logic/protocols/CloakLogic.h +++ b/client/ui/pages_logic/protocols/CloakLogic.h @@ -20,7 +20,11 @@ class CloakLogic : public PageProtocolLogicBase AUTO_PROPERTY(QString, labelInfoText) AUTO_PROPERTY(int, progressBarResetValue) AUTO_PROPERTY(int, progressBarResetMaximium) + AUTO_PROPERTY(bool, progressBarTextVisible) + AUTO_PROPERTY(QString, progressBarText) + AUTO_PROPERTY(bool, labelServerBusyVisible) + AUTO_PROPERTY(QString, labelServerBusyText) public: Q_INVOKABLE void onPushButtonSaveClicked(); diff --git a/client/ui/pages_logic/protocols/OpenVpnLogic.cpp b/client/ui/pages_logic/protocols/OpenVpnLogic.cpp index 91f21151..a25fd134 100644 --- a/client/ui/pages_logic/protocols/OpenVpnLogic.cpp +++ b/client/ui/pages_logic/protocols/OpenVpnLogic.cpp @@ -1,7 +1,10 @@ #include "OpenVpnLogic.h" -#include "core/servercontroller.h" + #include -#include "../../uilogic.h" + +#include "core/servercontroller.h" +#include "ui/uilogic.h" +#include "ui/pages_logic/ServerConfiguringProgressLogic.h" using namespace amnezia; using namespace PageEnumNS; @@ -98,40 +101,59 @@ void OpenVpnLogic::onPushButtonProtoOpenVpnSaveClicked() QJsonObject newContainerConfig = containerConfig; newContainerConfig.insert(ProtocolProps::protoToString(Proto::OpenVpn), protocolConfig); - UiLogic::PageFunc page_proto_openvpn; - page_proto_openvpn.setEnabledFunc = [this] (bool enabled) -> void { + ServerConfiguringProgressLogic::PageFunc pageFunc; + pageFunc.setEnabledFunc = [this] (bool enabled) -> void { set_pageEnabled(enabled); }; - UiLogic::ButtonFunc pushButton_proto_openvpn_save; - pushButton_proto_openvpn_save.setVisibleFunc = [this] (bool visible) ->void { + ServerConfiguringProgressLogic::ButtonFunc saveButtonFunc; + saveButtonFunc.setVisibleFunc = [this] (bool visible) -> void { set_pushButtonSaveVisible(visible); }; - UiLogic::LabelFunc label_proto_openvpn_info; - label_proto_openvpn_info.setVisibleFunc = [this] (bool visible) ->void { + ServerConfiguringProgressLogic::LabelFunc waitInfoFunc; + waitInfoFunc.setVisibleFunc = [this] (bool visible) -> void { set_labelProtoOpenVpnInfoVisible(visible); }; - label_proto_openvpn_info.setTextFunc = [this] (const QString& text) ->void { + waitInfoFunc.setTextFunc = [this] (const QString& text) -> void { set_labelProtoOpenVpnInfoText(text); }; - UiLogic::ProgressFunc progressBar_proto_openvpn_reset; - progressBar_proto_openvpn_reset.setVisibleFunc = [this] (bool visible) ->void { + ServerConfiguringProgressLogic::ProgressFunc progressBarFunc; + progressBarFunc.setVisibleFunc = [this] (bool visible) -> void { set_progressBarResetVisible(visible); }; - progressBar_proto_openvpn_reset.setValueFunc = [this] (int value) ->void { + progressBarFunc.setValueFunc = [this] (int value) -> void { set_progressBarResetValue(value); }; - progressBar_proto_openvpn_reset.getValueFunc = [this] (void) -> int { + progressBarFunc.getValueFunc = [this] (void) -> int { return progressBarResetValue(); }; - progressBar_proto_openvpn_reset.getMaximiumFunc = [this] (void) -> int { + progressBarFunc.getMaximiumFunc = [this] (void) -> int { return progressBarResetMaximium(); }; + progressBarFunc.setTextVisibleFunc = [this] (bool visible) -> void { + set_progressBarTextVisible(visible); + }; + progressBarFunc.setTextFunc = [this] (const QString& text) -> void { + set_progressBarText(text); + }; - ErrorCode e = uiLogic()->doInstallAction([this, containerConfig, &newContainerConfig](){ - return m_serverController->updateContainer(m_settings->serverCredentials(uiLogic()->selectedServerIndex), uiLogic()->selectedDockerContainer, containerConfig, newContainerConfig); + ServerConfiguringProgressLogic::LabelFunc busyInfoFuncy; + busyInfoFuncy.setTextFunc = [this] (const QString& text) -> void { + set_labelServerBusyText(text); + }; + busyInfoFuncy.setVisibleFunc = [this] (bool visible) -> void { + set_labelServerBusyVisible(visible); + }; + + progressBarFunc.setTextVisibleFunc(true); + progressBarFunc.setTextFunc(QString("Configuring...")); + ErrorCode e = uiLogic()->pageLogic()->doInstallAction([this, containerConfig, &newContainerConfig](){ + return m_serverController->updateContainer(m_settings->serverCredentials(uiLogic()->selectedServerIndex), + uiLogic()->selectedDockerContainer, + containerConfig, + newContainerConfig); }, - page_proto_openvpn, progressBar_proto_openvpn_reset, - pushButton_proto_openvpn_save, label_proto_openvpn_info); + pageFunc, progressBarFunc, + saveButtonFunc, waitInfoFunc, busyInfoFuncy); if (!e) { m_settings->setContainerConfig(uiLogic()->selectedServerIndex, uiLogic()->selectedDockerContainer, newContainerConfig); diff --git a/client/ui/pages_logic/protocols/OpenVpnLogic.h b/client/ui/pages_logic/protocols/OpenVpnLogic.h index 23c2dd4d..1dafe5ee 100644 --- a/client/ui/pages_logic/protocols/OpenVpnLogic.h +++ b/client/ui/pages_logic/protocols/OpenVpnLogic.h @@ -34,6 +34,11 @@ class OpenVpnLogic : public PageProtocolLogicBase AUTO_PROPERTY(QString, labelProtoOpenVpnInfoText) AUTO_PROPERTY(int, progressBarResetValue) AUTO_PROPERTY(int, progressBarResetMaximium) + AUTO_PROPERTY(bool, progressBarTextVisible) + AUTO_PROPERTY(QString, progressBarText) + + AUTO_PROPERTY(bool, labelServerBusyVisible) + AUTO_PROPERTY(QString, labelServerBusyText) public: Q_INVOKABLE void onPushButtonProtoOpenVpnSaveClicked(); diff --git a/client/ui/pages_logic/protocols/ShadowSocksLogic.cpp b/client/ui/pages_logic/protocols/ShadowSocksLogic.cpp index 1d5da936..c2575a4d 100644 --- a/client/ui/pages_logic/protocols/ShadowSocksLogic.cpp +++ b/client/ui/pages_logic/protocols/ShadowSocksLogic.cpp @@ -1,7 +1,10 @@ #include "ShadowSocksLogic.h" -#include "core/servercontroller.h" + #include -#include "../../uilogic.h" + +#include "core/servercontroller.h" +#include "ui/pages_logic/ServerConfiguringProgressLogic.h" +#include "ui/uilogic.h" using namespace amnezia; using namespace PageEnumNS; @@ -11,12 +14,12 @@ ShadowSocksLogic::ShadowSocksLogic(UiLogic *logic, QObject *parent): m_comboBoxCipherText{"chacha20-poly1305"}, m_lineEditPortText{}, m_pushButtonSaveVisible{false}, - m_progressBaResetVisible{false}, + m_progressBarResetVisible{false}, m_lineEditPortEnabled{false}, m_labelInfoVisible{true}, m_labelInfoText{}, - m_progressBaResetValue{0}, - m_progressBaResetMaximium{100} + m_progressBarResetValue{0}, + m_progressBarResetMaximium{100} { } @@ -25,7 +28,7 @@ void ShadowSocksLogic::updateProtocolPage(const QJsonObject &ssConfig, DockerCon { set_pageEnabled(haveAuthData); set_pushButtonSaveVisible(haveAuthData); - set_progressBaResetVisible(haveAuthData); + set_progressBarResetVisible(haveAuthData); set_comboBoxCipherText(ssConfig.value(config_key::cipher). toString(protocols::shadowsocks::defaultCipher)); @@ -51,40 +54,59 @@ void ShadowSocksLogic::onPushButtonSaveClicked() QJsonObject containerConfig = m_settings->containerConfig(uiLogic()->selectedServerIndex, uiLogic()->selectedDockerContainer); QJsonObject newContainerConfig = containerConfig; newContainerConfig.insert(ProtocolProps::protoToString(Proto::ShadowSocks), protocolConfig); - UiLogic::PageFunc page_proto_shadowsocks; - page_proto_shadowsocks.setEnabledFunc = [this] (bool enabled) -> void { + ServerConfiguringProgressLogic::PageFunc pageFunc; + pageFunc.setEnabledFunc = [this] (bool enabled) -> void { set_pageEnabled(enabled); }; - UiLogic::ButtonFunc pushButton_proto_shadowsocks_save; - pushButton_proto_shadowsocks_save.setVisibleFunc = [this] (bool visible) ->void { + ServerConfiguringProgressLogic::ButtonFunc saveButtonFunc; + saveButtonFunc.setVisibleFunc = [this] (bool visible) -> void { set_pushButtonSaveVisible(visible); }; - UiLogic::LabelFunc label_proto_shadowsocks_info; - label_proto_shadowsocks_info.setVisibleFunc = [this] (bool visible) ->void { + ServerConfiguringProgressLogic::LabelFunc waitInfoFunc; + waitInfoFunc.setVisibleFunc = [this] (bool visible) -> void { set_labelInfoVisible(visible); }; - label_proto_shadowsocks_info.setTextFunc = [this] (const QString& text) ->void { + waitInfoFunc.setTextFunc = [this] (const QString& text) -> void { set_labelInfoText(text); }; - UiLogic::ProgressFunc progressBar_reset; - progressBar_reset.setVisibleFunc = [this] (bool visible) ->void { - set_progressBaResetVisible(visible); + ServerConfiguringProgressLogic::ProgressFunc progressBarFunc; + progressBarFunc.setVisibleFunc = [this] (bool visible) -> void { + set_progressBarResetVisible(visible); }; - progressBar_reset.setValueFunc = [this] (int value) ->void { - set_progressBaResetValue(value); + progressBarFunc.setValueFunc = [this] (int value) -> void { + set_progressBarResetValue(value); }; - progressBar_reset.getValueFunc = [this] (void) -> int { - return progressBaResetValue(); + progressBarFunc.getValueFunc = [this] (void) -> int { + return progressBarResetValue(); }; - progressBar_reset.getMaximiumFunc = [this] (void) -> int { - return progressBaResetMaximium(); + progressBarFunc.getMaximiumFunc = [this] (void) -> int { + return progressBarResetMaximium(); + }; + progressBarFunc.setTextVisibleFunc = [this] (bool visible) -> void { + set_progressBarTextVisible(visible); + }; + progressBarFunc.setTextFunc = [this] (const QString& text) -> void { + set_progressBarText(text); }; - ErrorCode e = uiLogic()->doInstallAction([this, containerConfig, &newContainerConfig](){ - return m_serverController->updateContainer(m_settings->serverCredentials(uiLogic()->selectedServerIndex), uiLogic()->selectedDockerContainer, containerConfig, newContainerConfig); + ServerConfiguringProgressLogic::LabelFunc busyInfoFuncy; + busyInfoFuncy.setTextFunc = [this] (const QString& text) -> void { + set_labelServerBusyText(text); + }; + busyInfoFuncy.setVisibleFunc = [this] (bool visible) -> void { + set_labelServerBusyVisible(visible); + }; + + progressBarFunc.setTextVisibleFunc(true); + progressBarFunc.setTextFunc(QString("Configuring...")); + ErrorCode e = uiLogic()->pageLogic()->doInstallAction([this, containerConfig, &newContainerConfig](){ + return m_serverController->updateContainer(m_settings->serverCredentials(uiLogic()->selectedServerIndex), + uiLogic()->selectedDockerContainer, + containerConfig, + newContainerConfig); }, - page_proto_shadowsocks, progressBar_reset, - pushButton_proto_shadowsocks_save, label_proto_shadowsocks_info); + pageFunc, progressBarFunc, + saveButtonFunc, waitInfoFunc, busyInfoFuncy); if (!e) { m_settings->setContainerConfig(uiLogic()->selectedServerIndex, uiLogic()->selectedDockerContainer, newContainerConfig); diff --git a/client/ui/pages_logic/protocols/ShadowSocksLogic.h b/client/ui/pages_logic/protocols/ShadowSocksLogic.h index 4e566825..1300511f 100644 --- a/client/ui/pages_logic/protocols/ShadowSocksLogic.h +++ b/client/ui/pages_logic/protocols/ShadowSocksLogic.h @@ -12,13 +12,17 @@ class ShadowSocksLogic : public PageProtocolLogicBase AUTO_PROPERTY(QString, comboBoxCipherText) AUTO_PROPERTY(QString, lineEditPortText) AUTO_PROPERTY(bool, pushButtonSaveVisible) - AUTO_PROPERTY(bool, progressBaResetVisible) + AUTO_PROPERTY(bool, progressBarResetVisible) AUTO_PROPERTY(bool, lineEditPortEnabled) AUTO_PROPERTY(bool, labelInfoVisible) AUTO_PROPERTY(QString, labelInfoText) - AUTO_PROPERTY(int, progressBaResetValue) - AUTO_PROPERTY(int, progressBaResetMaximium) + AUTO_PROPERTY(int, progressBarResetValue) + AUTO_PROPERTY(int, progressBarResetMaximium) + AUTO_PROPERTY(bool, progressBarTextVisible) + AUTO_PROPERTY(QString, progressBarText) + AUTO_PROPERTY(bool, labelServerBusyVisible) + AUTO_PROPERTY(QString, labelServerBusyText) public: Q_INVOKABLE void onPushButtonSaveClicked(); diff --git a/client/ui/qml/Pages/PageServerConfiguringProgress.qml b/client/ui/qml/Pages/PageServerConfiguringProgress.qml index 1cd154ca..e481dbfe 100644 --- a/client/ui/qml/Pages/PageServerConfiguringProgress.qml +++ b/client/ui/qml/Pages/PageServerConfiguringProgress.qml @@ -27,6 +27,22 @@ PageBase { horizontalAlignment: Text.AlignHCenter } + LabelType { + id: labelServerBusy + x: 0 + anchors.top: label.bottom + anchors.topMargin: 30 + + anchors.horizontalCenter: parent.horizontalCenter + horizontalAlignment: Text.AlignHCenter + + width: parent.width - 40 + height: 41 + + text: ServerConfiguringProgressLogic.labelServerBusyText + visible: ServerConfiguringProgressLogic.labelServerBusyVisible + } + LabelType { anchors.bottom: pr.top anchors.bottomMargin: 20 diff --git a/client/ui/qml/Pages/Protocols/PageProtoCloak.qml b/client/ui/qml/Pages/Protocols/PageProtoCloak.qml index 01ad4f81..17dc829a 100644 --- a/client/ui/qml/Pages/Protocols/PageProtoCloak.qml +++ b/client/ui/qml/Pages/Protocols/PageProtoCloak.qml @@ -14,6 +14,7 @@ PageProtocolBase { enabled: logic.pageEnabled BackButton { id: back + enabled: logic.pageEnabled } Caption { @@ -110,12 +111,20 @@ PageProtocolBase { } } + LabelType { + id: label_server_busy + horizontalAlignment: Text.AlignHCenter + Layout.maximumWidth: parent.width + Layout.fillWidth: true + visible: logic.labelServerBusyVisible + text: logic.labelServerBusyText + } + LabelType { id: label_proto_cloak_info - x: 30 - anchors.bottom: pb_save.top - anchors.bottomMargin: 10 - width: parent.width - 40 + horizontalAlignment: Text.AlignHCenter + Layout.maximumWidth: parent.width + Layout.fillWidth: true visible: logic.labelInfoVisible text: logic.labelInfoText } @@ -146,6 +155,19 @@ PageProtocolBase { } } visible: logic.progressBarResetVisible + LabelType { + anchors.left: parent.left + anchors.right: parent.right + anchors.verticalCenter: parent.verticalCenter + text: logic.progressBarText + horizontalAlignment: Text.AlignHCenter + verticalAlignment: Text.AlignVCenter + font.family: "Lato" + font.styleName: "normal" + font.pixelSize: 16 + color: "#D4D4D4" + visible: logic.progressBarTextVisible + } } BlueButtonType { id: pb_save diff --git a/client/ui/qml/Pages/Protocols/PageProtoOpenVPN.qml b/client/ui/qml/Pages/Protocols/PageProtoOpenVPN.qml index 8387b9fe..a644bf59 100644 --- a/client/ui/qml/Pages/Protocols/PageProtoOpenVPN.qml +++ b/client/ui/qml/Pages/Protocols/PageProtoOpenVPN.qml @@ -13,6 +13,7 @@ PageProtocolBase { BackButton { id: back + enabled: logic.pageEnabled } Caption { id: caption @@ -345,9 +346,19 @@ PageProtocolBase { } LabelType { - id: label_proto_openvpn_info + id: label_server_busy + horizontalAlignment: Text.AlignHCenter + Layout.maximumWidth: parent.width + Layout.fillWidth: true + visible: logic.labelServerBusyVisible + text: logic.labelServerBusyText + } - height: 41 + LabelType { + id: label_proto_openvpn_info + horizontalAlignment: Text.AlignHCenter + Layout.maximumWidth: parent.width + Layout.fillWidth: true visible: logic.labelProtoOpenVpnInfoVisible text: logic.labelProtoOpenVpnInfoText } @@ -395,11 +406,20 @@ PageProtocolBase { } } } - + LabelType { + anchors.left: parent.left + anchors.right: parent.right + anchors.verticalCenter: parent.verticalCenter + text: logic.progressBarText + horizontalAlignment: Text.AlignHCenter + verticalAlignment: Text.AlignVCenter + font.family: "Lato" + font.styleName: "normal" + font.pixelSize: 16 + color: "#D4D4D4" + visible: logic.progressBarTextVisible + } } - } - } - } diff --git a/client/ui/qml/Pages/Protocols/PageProtoShadowSocks.qml b/client/ui/qml/Pages/Protocols/PageProtoShadowSocks.qml index e2726106..3fe0df26 100644 --- a/client/ui/qml/Pages/Protocols/PageProtoShadowSocks.qml +++ b/client/ui/qml/Pages/Protocols/PageProtoShadowSocks.qml @@ -13,6 +13,7 @@ PageProtocolBase { BackButton { id: back + enabled: logic.pageEnabled } Caption { @@ -88,27 +89,33 @@ PageProtocolBase { Item { Layout.fillHeight: true } - } + LabelType { + id: label_server_busy + horizontalAlignment: Text.AlignHCenter + Layout.maximumWidth: parent.width + Layout.fillWidth: true + visible: logic.labelServerBusyVisible + text: logic.labelServerBusyText + } - LabelType { - id: label_proto_shadowsocks_info - x: 30 - anchors.bottom: pb_save.top - anchors.bottomMargin: 10 - width: parent.width - 40 - height: 41 - visible: logic.labelInfoVisible - text: logic.labelInfoText + LabelType { + id: label_proto_shadowsocks_info + horizontalAlignment: Text.AlignHCenter + Layout.maximumWidth: parent.width + Layout.fillWidth: true + visible: logic.labelInfoVisible + text: logic.labelInfoText + } } ProgressBar { id: progressBar_reset anchors.fill: pb_save from: 0 - to: logic.progressBaResetMaximium - value: logic.progressBaResetValue - visible: logic.progressBaResetVisible + to: logic.progressBarResetMaximium + value: logic.progressBarResetValue + visible: logic.progressBarResetVisible background: Rectangle { implicitWidth: parent.width implicitHeight: parent.height @@ -126,6 +133,19 @@ PageProtocolBase { color: Qt.rgba(255, 255, 255, 0.15); } } + LabelType { + anchors.left: parent.left + anchors.right: parent.right + anchors.verticalCenter: parent.verticalCenter + text: logic.progressBarText + horizontalAlignment: Text.AlignHCenter + verticalAlignment: Text.AlignVCenter + font.family: "Lato" + font.styleName: "normal" + font.pixelSize: 16 + color: "#D4D4D4" + visible: logic.progressBarTextVisible + } } BlueButtonType { diff --git a/client/ui/uilogic.cpp b/client/ui/uilogic.cpp index e336fa76..9d43f414 100644 --- a/client/ui/uilogic.cpp +++ b/client/ui/uilogic.cpp @@ -303,44 +303,62 @@ void UiLogic::installServer(QMap &containers) loop.exec(); qApp->processEvents(); - PageFunc page_new_server_configuring; - page_new_server_configuring.setEnabledFunc = [this] (bool enabled) -> void { + ServerConfiguringProgressLogic::PageFunc pageFunc; + pageFunc.setEnabledFunc = [this] (bool enabled) -> void { pageLogic()->set_pageEnabled(enabled); }; - ButtonFunc no_button; - LabelFunc label_new_server_configuring_wait_info; - label_new_server_configuring_wait_info.setTextFunc = [this] (const QString& text) -> void { + + ServerConfiguringProgressLogic::ButtonFunc noButton; + + ServerConfiguringProgressLogic::LabelFunc waitInfoFunc; + waitInfoFunc.setTextFunc = [this] (const QString& text) -> void { pageLogic()->set_labelWaitInfoText(text); }; - label_new_server_configuring_wait_info.setVisibleFunc = [this] (bool visible) ->void { + waitInfoFunc.setVisibleFunc = [this] (bool visible) -> void { pageLogic()->set_labelWaitInfoVisible(visible); }; - ProgressFunc progressBar_new_server_configuring; - progressBar_new_server_configuring.setVisibleFunc = [this] (bool visible) ->void { + + ServerConfiguringProgressLogic::ProgressFunc progressBarFunc; + progressBarFunc.setVisibleFunc = [this] (bool visible) -> void { pageLogic()->set_progressBarVisible(visible); }; - progressBar_new_server_configuring.setValueFunc = [this] (int value) ->void { + progressBarFunc.setValueFunc = [this] (int value) -> void { pageLogic()->set_progressBarValue(value); }; - progressBar_new_server_configuring.getValueFunc = [this] (void) -> int { + progressBarFunc.getValueFunc = [this] (void) -> int { return pageLogic()->progressBarValue(); }; - progressBar_new_server_configuring.getMaximiumFunc = [this] (void) -> int { + progressBarFunc.getMaximiumFunc = [this] (void) -> int { return pageLogic()->progressBarMaximium(); }; - progressBar_new_server_configuring.setTextVisibleFunc = [this] (bool visible) ->void { + progressBarFunc.setTextVisibleFunc = [this] (bool visible) -> void { pageLogic()->set_progressBarTextVisible(visible); }; - progressBar_new_server_configuring.setTextFunc = [this] (const QString& text) ->void { + progressBarFunc.setTextFunc = [this] (const QString& text) -> void { pageLogic()->set_progressBarText(text); }; - bool ok = installContainers(installCredentials, containers, - page_new_server_configuring, - progressBar_new_server_configuring, - no_button, - label_new_server_configuring_wait_info); - if (ok) { + ServerConfiguringProgressLogic::LabelFunc busyInfoFunc; + busyInfoFunc.setTextFunc = [this] (const QString& text) -> void { + pageLogic()->set_labelServerBusyText(text); + }; + busyInfoFunc.setVisibleFunc = [this] (bool visible) -> void { + pageLogic()->set_labelServerBusyVisible(visible); + }; + + int count = 0; + ErrorCode error; + for (QMap::iterator i = containers.begin(); i != containers.end(); i++, count++) { + progressBarFunc.setTextFunc(QString("Installing %1 %2 %3").arg(count+1).arg(tr("of")).arg(containers.size())); + + error = pageLogic()->doInstallAction([&] () { + return m_serverController->setupContainer(installCredentials, i.key(), i.value()); + }, pageFunc, progressBarFunc, noButton, waitInfoFunc, busyInfoFunc); + + m_serverController->disconnectFromHost(installCredentials); + } + + if (error == ErrorCode::NoError) { QJsonObject server; server.insert(config_key::hostName, installCredentials.hostName); server.insert(config_key::userName, installCredentials.userName); @@ -367,182 +385,6 @@ void UiLogic::installServer(QMap &containers) } } -bool UiLogic::installContainers(ServerCredentials credentials, - QMap &containers, - const PageFunc &page, - const ProgressFunc &progress, - const ButtonFunc &button, - const LabelFunc &info) -{ - if (!progress.setValueFunc) return false; - - if (page.setEnabledFunc) { - page.setEnabledFunc(false); - } - if (button.setVisibleFunc) { - button.setVisibleFunc(false); - } - - if (info.setVisibleFunc) { - info.setVisibleFunc(true); - } - if (info.setTextFunc) { - info.setTextFunc(tr("Please wait, configuring process may take up to 5 minutes")); - } - - int cnt = 0; - for (QMap::iterator i = containers.begin(); i != containers.end(); i++, cnt++) { - QTimer timer; - connect(&timer, &QTimer::timeout, [progress](){ - progress.setValueFunc(progress.getValueFunc() + 1); - }); - - progress.setValueFunc(0); - timer.start(1000); - - progress.setTextVisibleFunc(true); - progress.setTextFunc(QString("Installing %1 %2 %3").arg(cnt+1).arg(tr("of")).arg(containers.size())); - - ErrorCode e = m_serverController->setupContainer(credentials, i.key(), i.value()); - qDebug() << "Setup server finished with code" << e; - m_serverController->disconnectFromHost(credentials); - - if (e) { - if (page.setEnabledFunc) { - page.setEnabledFunc(true); - } - if (button.setVisibleFunc) { - button.setVisibleFunc(true); - } - if (info.setVisibleFunc) { - info.setVisibleFunc(false); - } - - QMessageBox::warning(nullptr, APPLICATION_NAME, - tr("Error occurred while configuring server.") + "\n" + - errorString(e)); - - return false; - } - - // just ui progressbar tweak - timer.stop(); - - int remaining_val = progress.getMaximiumFunc() - progress.getValueFunc(); - - if (remaining_val > 0) { - QTimer timer1; - QEventLoop loop1; - - connect(&timer1, &QTimer::timeout, [&](){ - progress.setValueFunc(progress.getValueFunc() + 1); - if (progress.getValueFunc() >= progress.getMaximiumFunc()) { - loop1.quit(); - } - }); - - timer1.start(5); - loop1.exec(); - } - } - - - if (button.setVisibleFunc) { - button.setVisibleFunc(true); - } - if (page.setEnabledFunc) { - page.setEnabledFunc(true); - } - if (info.setTextFunc) { - info.setTextFunc(tr("Amnezia server installed")); - } - - return true; -} - -ErrorCode UiLogic::doInstallAction(const std::function &action, - const PageFunc &page, - const ProgressFunc &progress, - const ButtonFunc &button, - const LabelFunc &info) -{ - progress.setVisibleFunc(true); - if (page.setEnabledFunc) { - page.setEnabledFunc(false); - } - if (button.setVisibleFunc) { - button.setVisibleFunc(false); - } - if (info.setVisibleFunc) { - info.setVisibleFunc(true); - } - if (info.setTextFunc) { - info.setTextFunc(tr("Please wait, configuring process may take up to 5 minutes")); - } - - QTimer timer; - connect(&timer, &QTimer::timeout, [progress](){ - progress.setValueFunc(progress.getValueFunc() + 1); - }); - - progress.setValueFunc(0); - timer.start(1000); - - ErrorCode e = action(); - qDebug() << "doInstallAction finished with code" << e; - - if (e) { - if (page.setEnabledFunc) { - page.setEnabledFunc(true); - } - if (button.setVisibleFunc) { - button.setVisibleFunc(true); - } - if (info.setVisibleFunc) { - info.setVisibleFunc(false); - } - QMessageBox::warning(nullptr, APPLICATION_NAME, - tr("Error occurred while configuring server.") + "\n" + - errorString(e)); - - progress.setVisibleFunc(false); - return e; - } - - // just ui progressbar tweak - timer.stop(); - - int remaining_val = progress.getMaximiumFunc() - progress.getValueFunc(); - - if (remaining_val > 0) { - QTimer timer1; - QEventLoop loop1; - - connect(&timer1, &QTimer::timeout, [&](){ - progress.setValueFunc(progress.getValueFunc() + 1); - if (progress.getValueFunc() >= progress.getMaximiumFunc()) { - loop1.quit(); - } - }); - - timer1.start(5); - loop1.exec(); - } - - - progress.setVisibleFunc(false); - if (button.setVisibleFunc) { - button.setVisibleFunc(true); - } - if (page.setEnabledFunc) { - page.setEnabledFunc(true); - } - if (info.setTextFunc) { - info.setTextFunc(tr("Operation finished")); - } - return ErrorCode::NoError; -} - PageProtocolLogicBase *UiLogic::protocolLogic(Proto p) { PageProtocolLogicBase *logic = m_protocolLogicMap.value(p); diff --git a/client/ui/uilogic.h b/client/ui/uilogic.h index 82f2d6ea..4cc006dd 100644 --- a/client/ui/uilogic.h +++ b/client/ui/uilogic.h @@ -136,38 +136,6 @@ private slots: private: PageEnumNS::Page currentPage(); - struct ProgressFunc { - std::function setVisibleFunc; - std::function setValueFunc; - std::function getValueFunc; - std::function getMaximiumFunc; - std::function setTextVisibleFunc; - std::function setTextFunc; - }; - struct PageFunc { - std::function setEnabledFunc; - }; - struct ButtonFunc { - std::function setVisibleFunc; - }; - struct LabelFunc { - std::function setVisibleFunc; - std::function setTextFunc; - }; - - bool installContainers(ServerCredentials credentials, - QMap &containers, - const PageFunc& page, - const ProgressFunc& progress, - const ButtonFunc& button, - const LabelFunc& info); - - ErrorCode doInstallAction(const std::function &action, - const PageFunc& page, - const ProgressFunc& progress, - const ButtonFunc& button, - const LabelFunc& info); - public: Q_INVOKABLE PageProtocolLogicBase *protocolLogic(Proto p);