From 1565971479d57d893c9491eb91c52e16ae1394e8 Mon Sep 17 00:00:00 2001 From: sithlord48 Date: Wed, 25 Mar 2026 00:28:37 -0400 Subject: [PATCH] feat: show connection retry status in status area --- src/lib/deskflow/ClientApp.cpp | 10 ++++++-- src/lib/gui/MainWindow.cpp | 6 +++++ src/lib/gui/MainWindow.h | 1 + src/lib/gui/core/ClientConnection.cpp | 6 +++++ src/lib/gui/core/ClientConnection.h | 1 + src/lib/gui/widgets/StatusBar.cpp | 37 +++++++++++++++++++++++++-- src/lib/gui/widgets/StatusBar.h | 4 +++ translations/deskflow_es.ts | 12 ++++++--- translations/deskflow_it.ts | 12 ++++++--- translations/deskflow_ja.ts | 12 ++++++--- translations/deskflow_ko.ts | 12 ++++++--- translations/deskflow_ru.ts | 12 ++++++--- translations/deskflow_zh_CN.ts | 12 ++++++--- 13 files changed, 109 insertions(+), 28 deletions(-) diff --git a/src/lib/deskflow/ClientApp.cpp b/src/lib/deskflow/ClientApp.cpp index 70b9d1b43..7dcbf131b 100644 --- a/src/lib/deskflow/ClientApp.cpp +++ b/src/lib/deskflow/ClientApp.cpp @@ -162,7 +162,10 @@ void ClientApp::handleClientRestart(const Event &, EventQueueTimer *timer) void ClientApp::scheduleClientRestart(double retryTime) { - LOG_DEBUG("retry in %.0f seconds", retryTime); + if (Settings::value(Settings::Client::DynamicConnectionRetry).toBool()) + LOG_IPC("retry in %.0f seconds", retryTime); + else + LOG_DEBUG("retry in %.0f seconds", retryTime); // install a timer and handler to retry later EventQueueTimer *timer = getEvents()->newOneShotTimer(retryTime, nullptr); getEvents()->addHandler(EventTypes::Timer, timer, [this, timer](const auto &e) { handleClientRestart(e, timer); }); @@ -214,8 +217,8 @@ void ClientApp::handleClientRefused(const Event &e) } else { LOG_WARN("failed to connect to server: %s", info->m_what.c_str()); if (!m_suspended) { - m_retryCount++; scheduleClientRestart(retryTime()); + m_retryCount++; } } } @@ -292,10 +295,12 @@ bool ClientApp::startClient() } catch (ScreenOpenFailureException &e) { LOG_CRIT("failed to start client: %s", e.what()); closeClientScreen(clientScreen); + m_retryCount = 0; return false; } catch (BaseException &e) { LOG_CRIT("failed to start client: %s", e.what()); closeClientScreen(clientScreen); + m_retryCount = 0; return false; } @@ -309,6 +314,7 @@ void ClientApp::stopClient() closeClientScreen(m_clientScreen); m_client = nullptr; m_clientScreen = nullptr; + m_retryCount = 0; } int ClientApp::mainLoop() diff --git a/src/lib/gui/MainWindow.cpp b/src/lib/gui/MainWindow.cpp index 08d9275c1..9e36eca6b 100644 --- a/src/lib/gui/MainWindow.cpp +++ b/src/lib/gui/MainWindow.cpp @@ -276,6 +276,7 @@ void MainWindow::connectSlots() ); connect(&m_clientConnection, &ClientConnection::requestShowError, this, &MainWindow::showClientError); + connect(&m_clientConnection, &ClientConnection::updateTimeoutDelay, this, &MainWindow::updateTimeoutDelay); if (Settings::value(Settings::Gui::AutoStartCore).toBool()) { connect(ui->btnToggleCore, &QPushButton::clicked, m_actionStopCore, &QAction::trigger, Qt::UniqueConnection); @@ -1246,6 +1247,11 @@ void MainWindow::updateIpLabel(const QStringList &addresses) ui->lblIpAddresses->setToolTip(toolTipText); } +void MainWindow::updateTimeoutDelay(int newDelay) +{ + m_statusBar->setConnectionInterval(newDelay); +} + bool MainWindow::canRunCore() const { const auto mode = m_coreProcess.mode(); diff --git a/src/lib/gui/MainWindow.h b/src/lib/gui/MainWindow.h index 4dc5e3b2f..ec35a91d0 100644 --- a/src/lib/gui/MainWindow.h +++ b/src/lib/gui/MainWindow.h @@ -160,6 +160,7 @@ private: void remoteHostChanged(const QString &newRemoteHost); void handleNewClientPromptRequest(const QString &clientName, bool usePeerAuth); void updateIpLabel(const QStringList &addresses); + void updateTimeoutDelay(int newDelay); bool canRunCore() const; /** diff --git a/src/lib/gui/core/ClientConnection.cpp b/src/lib/gui/core/ClientConnection.cpp index 355496a18..1d2d2ae6c 100644 --- a/src/lib/gui/core/ClientConnection.cpp +++ b/src/lib/gui/core/ClientConnection.cpp @@ -21,6 +21,12 @@ void ClientConnection::handleLogLine(const QString &logLine) return; } + if (logLine.contains("retry in ") && Settings::value(Settings::Client::DynamicConnectionRetry).toBool()) { + auto line = logLine.mid(logLine.indexOf("in ") + 3); + int seconds = line.mid(0, line.indexOf(" ")).toInt(); + Q_EMIT updateTimeoutDelay(seconds); + return; + } if (logLine.contains("connected to server")) { m_supressMessage = true; return; diff --git a/src/lib/gui/core/ClientConnection.h b/src/lib/gui/core/ClientConnection.h index d31b17aa5..377cbeea0 100644 --- a/src/lib/gui/core/ClientConnection.h +++ b/src/lib/gui/core/ClientConnection.h @@ -36,6 +36,7 @@ Q_SIGNALS: * @param address of the host */ void requestShowError(deskflow::client::ErrorType error, const QString &address); + void updateTimeoutDelay(int newTimeout); private: void showMessage(const QString &logLine); diff --git a/src/lib/gui/widgets/StatusBar.cpp b/src/lib/gui/widgets/StatusBar.cpp index a52796543..cd22323d5 100644 --- a/src/lib/gui/widgets/StatusBar.cpp +++ b/src/lib/gui/widgets/StatusBar.cpp @@ -11,13 +11,15 @@ #include #include #include +#include StatusBar::StatusBar(QWidget *parent) : QStatusBar{parent}, m_btnFingerprint{new QPushButton(this)}, m_lblSecurityIcon{new QLabel(this)}, m_lblStatus{new QLabel(this)}, - m_btnUpdate{new QPushButton(this)} + m_btnUpdate{new QPushButton(this)}, + m_retryTimer{new QTimer(this)} { static const auto btnHeight = height() - 2; static const auto btnSize = QSize(btnHeight, btnHeight); @@ -47,6 +49,10 @@ StatusBar::StatusBar(QWidget *parent) insertPermanentWidget(3, m_btnUpdate); connect(m_btnUpdate, &QPushButton::clicked, this, &StatusBar::requestUpdateVersion); + m_retryTimer->setInterval(1000); + m_retryTimer->setSingleShot(false); + connect(m_retryTimer, &QTimer::timeout, this, &StatusBar::updateTimerLabel); + updateText(); adjustSize(); } @@ -54,22 +60,28 @@ StatusBar::StatusBar(QWidget *parent) // clang-format off void StatusBar::setStatus(ConnectionState connectionState, ProcessState processState, bool isServer) { + if (m_retryTimer->isActive()) + m_retryTimer->stop(); setSecurityIconVisible(false); switch (processState) { using enum ProcessState; case Starting: + m_connectionInterval = -1; m_lblStatus->setText(tr("%1 is starting...").arg(kAppName)); break; case RetryPending: + m_connectionInterval = -1; m_lblStatus->setText(tr("%1 will retry in a moment...").arg(kAppName)); break; case Stopping: + m_connectionInterval = -1; m_lblStatus->setText(tr("%1 is stopping...").arg(kAppName)); break; case Stopped: + m_connectionInterval = -1; m_lblStatus->setText(tr("%1 is not running").arg(kAppName)); break; @@ -86,11 +98,14 @@ void StatusBar::setStatus(ConnectionState connectionState, ProcessState processS } case Connecting: - m_lblStatus->setText(tr("%1 is connecting...").arg(kAppName)); + updateTimerLabel(); + if (Settings::value(Settings::Client::DynamicConnectionRetry).toBool()) + m_retryTimer->start(); break; case Connected: { setSecurityIconVisible(true); + m_connectionInterval = -1; if (!isServer) { m_lblStatus->setText(tr("%1 is connected as client of %2") .arg(kAppName, Settings::value(Settings::Client::RemoteHost).toString())); @@ -100,6 +115,7 @@ void StatusBar::setStatus(ConnectionState connectionState, ProcessState processS case Disconnected: m_lblStatus->setText(tr("%1 is disconnected").arg(kAppName)); + m_connectionInterval = -1; break; } } @@ -132,6 +148,11 @@ void StatusBar::setSecurityIconVisible(bool visible) m_lblSecurityIcon->setVisible(visible); } +void StatusBar::setConnectionInterval(int newInterval) +{ + m_connectionInterval = newInterval; +} + bool StatusBar::securityIconVisible() const { return m_lblSecurityIcon->isVisible(); @@ -162,6 +183,18 @@ void StatusBar::updateText() setSecurityLevel(m_securityLevel); } +void StatusBar::updateTimerLabel() +{ + QString text; + if (m_connectionInterval < 2 || !Settings::value(Settings::Client::DynamicConnectionRetry).toBool()) { + text = tr("%1 is connecting...").arg(kAppName); + } else { + text = tr("%1 is waiting %2 seconds before the next retry").arg(kAppName, QString::number(m_connectionInterval)); + m_connectionInterval--; + } + m_lblStatus->setText(text); +} + void StatusBar::setSecurityIcon(bool encrypted) { const auto icon = QIcon::fromTheme(encrypted ? QIcon::ThemeIcon::SecurityHigh : QIcon::ThemeIcon::SecurityLow); diff --git a/src/lib/gui/widgets/StatusBar.h b/src/lib/gui/widgets/StatusBar.h index 5d1e72784..a91af614d 100644 --- a/src/lib/gui/widgets/StatusBar.h +++ b/src/lib/gui/widgets/StatusBar.h @@ -24,6 +24,7 @@ public: void setStatus(ConnectionState connectionState, ProcessState processState, bool isServer); void setServerClients(const QStringList &clients); void setSecurityIconVisible(bool visible); + void setConnectionInterval(int newInterval); bool securityIconVisible() const; void updateSecurityInfo(bool encrypted); void setSecurityIcon(bool encrypted); @@ -40,10 +41,13 @@ protected: private: void updateText(); + void updateTimerLabel(); QPushButton *m_btnFingerprint = nullptr; QLabel *m_lblSecurityIcon = nullptr; QLabel *m_lblStatus = nullptr; QPushButton *m_btnUpdate = nullptr; bool m_encrypted = false; QString m_securityLevel; + int m_connectionInterval = -1; + QTimer *m_retryTimer = nullptr; }; diff --git a/translations/deskflow_es.ts b/translations/deskflow_es.ts index 432b4ca97..05dc0f82f 100644 --- a/translations/deskflow_es.ts +++ b/translations/deskflow_es.ts @@ -1348,10 +1348,6 @@ Al habilitar esta opción, se deshabilitará la interfaz gráfica de usuario (GU %1 is waiting for clients %1 está esperando clientes - - %1 is connecting... - %1 se está conectando... - %1 is connected as client of %2 %1 está conectado como cliente de %2 @@ -1386,6 +1382,14 @@ Al habilitar esta opción, se deshabilitará la interfaz gráfica de usuario (GU Update available Actualización disponible + + %1 is connecting... + %1 se está conectando... + + + %1 is waiting %2 seconds before the next retry + %1 está esperando %2 segundos antes del siguiente reintento + %1 Encryption Enabled %1 Cifrado habilitado diff --git a/translations/deskflow_it.ts b/translations/deskflow_it.ts index 388a433e1..f58928c6c 100644 --- a/translations/deskflow_it.ts +++ b/translations/deskflow_it.ts @@ -1348,10 +1348,6 @@ L'abilitazione di questa impostazione disabiliterà l'interfaccia graf %1 is waiting for clients %1 è in attesa di client - - %1 is connecting... - %1 è in connessione... - %1 is connected as client of %2 %1 è connesso come client di %2 @@ -1386,6 +1382,14 @@ L'abilitazione di questa impostazione disabiliterà l'interfaccia graf Update available Aggiornamento disponibile + + %1 is connecting... + %1 è in connessione... + + + %1 is waiting %2 seconds before the next retry + %1 attende %2 secondi prima del prossimo tentativo + %1 Encryption Enabled %1 Crittografia abilitata diff --git a/translations/deskflow_ja.ts b/translations/deskflow_ja.ts index 1400dec8a..1484e003d 100644 --- a/translations/deskflow_ja.ts +++ b/translations/deskflow_ja.ts @@ -1350,10 +1350,6 @@ Enabling this setting will disable the server config GUI. %1 is waiting for clients %1 はクライアント接続を待機中 - - %1 is connecting... - %1 は接続処理中… - %1 is connected as client of %2 %1 は %2 にクライアントとして接続中 @@ -1387,6 +1383,14 @@ Enabling this setting will disable the server config GUI. Update available ソフトウェア更新あり + + %1 is connecting... + %1 は接続処理中… + + + %1 is waiting %2 seconds before the next retry + %1 は次の再試行まで %2 秒待機しています + %1 Encryption Enabled %1 暗号化有効 diff --git a/translations/deskflow_ko.ts b/translations/deskflow_ko.ts index 8cb419243..e96f0cdbb 100644 --- a/translations/deskflow_ko.ts +++ b/translations/deskflow_ko.ts @@ -1348,10 +1348,6 @@ Enabling this setting will disable the server config GUI. %1 is waiting for clients %1 클라이언트를 기다리는 중 - - %1 is connecting... - %1 연결 중... - %1 is connected as client of %2 %1이(가) %2의 클라이언트로 연결되었습니다 @@ -1385,6 +1381,14 @@ Enabling this setting will disable the server config GUI. Update available 업데이트 사용 가능 + + %1 is connecting... + %1 연결 중... + + + %1 is waiting %2 seconds before the next retry + %1이 다음 재시도까지 %2초 대기 중입니다 + %1 Encryption Enabled %1 암호화 사용 diff --git a/translations/deskflow_ru.ts b/translations/deskflow_ru.ts index c10b07175..0f6f316aa 100644 --- a/translations/deskflow_ru.ts +++ b/translations/deskflow_ru.ts @@ -1346,10 +1346,6 @@ Enabling this setting will disable the server config GUI. %1 is waiting for clients %1 ожидает подключения клиентов - - %1 is connecting... - %1 подключается... - %1 is connected as client of %2 %1 подключен как клиент к %2 @@ -1385,6 +1381,14 @@ Enabling this setting will disable the server config GUI. Update available Доступно обновление + + %1 is connecting... + %1 подключается... + + + %1 is waiting %2 seconds before the next retry + %1 ожидает %2 секунд перед следующей попыткой + %1 Encryption Enabled Шифрование %1 включено diff --git a/translations/deskflow_zh_CN.ts b/translations/deskflow_zh_CN.ts index 5be1d8dc9..cd9fdf2c0 100644 --- a/translations/deskflow_zh_CN.ts +++ b/translations/deskflow_zh_CN.ts @@ -1350,10 +1350,6 @@ Enabling this setting will disable the server config GUI. %1 is waiting for clients %1 正在等待客户端连接 - - %1 is connecting... - %1 正在连接... - %1 is connected as client of %2 %1 已作为 %2 的客户端连接 @@ -1387,6 +1383,14 @@ Enabling this setting will disable the server config GUI. Update available 有可用更新 + + %1 is connecting... + %1 正在连接... + + + %1 is waiting %2 seconds before the next retry + %1 正在等待 %2 秒,然后进行下一次重试 + %1 Encryption Enabled %1 加密已启用