feat: show connection retry status in status area

This commit is contained in:
sithlord48 2026-03-25 00:28:37 -04:00 committed by Chris Rizzitello
parent 468c3b76de
commit 1565971479
13 changed files with 109 additions and 28 deletions

View file

@ -162,7 +162,10 @@ void ClientApp::handleClientRestart(const Event &, EventQueueTimer *timer)
void ClientApp::scheduleClientRestart(double retryTime) 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 // install a timer and handler to retry later
EventQueueTimer *timer = getEvents()->newOneShotTimer(retryTime, nullptr); EventQueueTimer *timer = getEvents()->newOneShotTimer(retryTime, nullptr);
getEvents()->addHandler(EventTypes::Timer, timer, [this, timer](const auto &e) { handleClientRestart(e, timer); }); getEvents()->addHandler(EventTypes::Timer, timer, [this, timer](const auto &e) { handleClientRestart(e, timer); });
@ -214,8 +217,8 @@ void ClientApp::handleClientRefused(const Event &e)
} else { } else {
LOG_WARN("failed to connect to server: %s", info->m_what.c_str()); LOG_WARN("failed to connect to server: %s", info->m_what.c_str());
if (!m_suspended) { if (!m_suspended) {
m_retryCount++;
scheduleClientRestart(retryTime()); scheduleClientRestart(retryTime());
m_retryCount++;
} }
} }
} }
@ -292,10 +295,12 @@ bool ClientApp::startClient()
} catch (ScreenOpenFailureException &e) { } catch (ScreenOpenFailureException &e) {
LOG_CRIT("failed to start client: %s", e.what()); LOG_CRIT("failed to start client: %s", e.what());
closeClientScreen(clientScreen); closeClientScreen(clientScreen);
m_retryCount = 0;
return false; return false;
} catch (BaseException &e) { } catch (BaseException &e) {
LOG_CRIT("failed to start client: %s", e.what()); LOG_CRIT("failed to start client: %s", e.what());
closeClientScreen(clientScreen); closeClientScreen(clientScreen);
m_retryCount = 0;
return false; return false;
} }
@ -309,6 +314,7 @@ void ClientApp::stopClient()
closeClientScreen(m_clientScreen); closeClientScreen(m_clientScreen);
m_client = nullptr; m_client = nullptr;
m_clientScreen = nullptr; m_clientScreen = nullptr;
m_retryCount = 0;
} }
int ClientApp::mainLoop() int ClientApp::mainLoop()

View file

@ -276,6 +276,7 @@ void MainWindow::connectSlots()
); );
connect(&m_clientConnection, &ClientConnection::requestShowError, this, &MainWindow::showClientError); connect(&m_clientConnection, &ClientConnection::requestShowError, this, &MainWindow::showClientError);
connect(&m_clientConnection, &ClientConnection::updateTimeoutDelay, this, &MainWindow::updateTimeoutDelay);
if (Settings::value(Settings::Gui::AutoStartCore).toBool()) { if (Settings::value(Settings::Gui::AutoStartCore).toBool()) {
connect(ui->btnToggleCore, &QPushButton::clicked, m_actionStopCore, &QAction::trigger, Qt::UniqueConnection); 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); ui->lblIpAddresses->setToolTip(toolTipText);
} }
void MainWindow::updateTimeoutDelay(int newDelay)
{
m_statusBar->setConnectionInterval(newDelay);
}
bool MainWindow::canRunCore() const bool MainWindow::canRunCore() const
{ {
const auto mode = m_coreProcess.mode(); const auto mode = m_coreProcess.mode();

View file

@ -160,6 +160,7 @@ private:
void remoteHostChanged(const QString &newRemoteHost); void remoteHostChanged(const QString &newRemoteHost);
void handleNewClientPromptRequest(const QString &clientName, bool usePeerAuth); void handleNewClientPromptRequest(const QString &clientName, bool usePeerAuth);
void updateIpLabel(const QStringList &addresses); void updateIpLabel(const QStringList &addresses);
void updateTimeoutDelay(int newDelay);
bool canRunCore() const; bool canRunCore() const;
/** /**

View file

@ -21,6 +21,12 @@ void ClientConnection::handleLogLine(const QString &logLine)
return; 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")) { if (logLine.contains("connected to server")) {
m_supressMessage = true; m_supressMessage = true;
return; return;

View file

@ -36,6 +36,7 @@ Q_SIGNALS:
* @param address of the host * @param address of the host
*/ */
void requestShowError(deskflow::client::ErrorType error, const QString &address); void requestShowError(deskflow::client::ErrorType error, const QString &address);
void updateTimeoutDelay(int newTimeout);
private: private:
void showMessage(const QString &logLine); void showMessage(const QString &logLine);

View file

@ -11,13 +11,15 @@
#include <QEvent> #include <QEvent>
#include <QLabel> #include <QLabel>
#include <QPushButton> #include <QPushButton>
#include <QTimer>
StatusBar::StatusBar(QWidget *parent) StatusBar::StatusBar(QWidget *parent)
: QStatusBar{parent}, : QStatusBar{parent},
m_btnFingerprint{new QPushButton(this)}, m_btnFingerprint{new QPushButton(this)},
m_lblSecurityIcon{new QLabel(this)}, m_lblSecurityIcon{new QLabel(this)},
m_lblStatus{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 btnHeight = height() - 2;
static const auto btnSize = QSize(btnHeight, btnHeight); static const auto btnSize = QSize(btnHeight, btnHeight);
@ -47,6 +49,10 @@ StatusBar::StatusBar(QWidget *parent)
insertPermanentWidget(3, m_btnUpdate); insertPermanentWidget(3, m_btnUpdate);
connect(m_btnUpdate, &QPushButton::clicked, this, &StatusBar::requestUpdateVersion); 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(); updateText();
adjustSize(); adjustSize();
} }
@ -54,22 +60,28 @@ StatusBar::StatusBar(QWidget *parent)
// clang-format off // clang-format off
void StatusBar::setStatus(ConnectionState connectionState, ProcessState processState, bool isServer) void StatusBar::setStatus(ConnectionState connectionState, ProcessState processState, bool isServer)
{ {
if (m_retryTimer->isActive())
m_retryTimer->stop();
setSecurityIconVisible(false); setSecurityIconVisible(false);
switch (processState) { switch (processState) {
using enum ProcessState; using enum ProcessState;
case Starting: case Starting:
m_connectionInterval = -1;
m_lblStatus->setText(tr("%1 is starting...").arg(kAppName)); m_lblStatus->setText(tr("%1 is starting...").arg(kAppName));
break; break;
case RetryPending: case RetryPending:
m_connectionInterval = -1;
m_lblStatus->setText(tr("%1 will retry in a moment...").arg(kAppName)); m_lblStatus->setText(tr("%1 will retry in a moment...").arg(kAppName));
break; break;
case Stopping: case Stopping:
m_connectionInterval = -1;
m_lblStatus->setText(tr("%1 is stopping...").arg(kAppName)); m_lblStatus->setText(tr("%1 is stopping...").arg(kAppName));
break; break;
case Stopped: case Stopped:
m_connectionInterval = -1;
m_lblStatus->setText(tr("%1 is not running").arg(kAppName)); m_lblStatus->setText(tr("%1 is not running").arg(kAppName));
break; break;
@ -86,11 +98,14 @@ void StatusBar::setStatus(ConnectionState connectionState, ProcessState processS
} }
case Connecting: case Connecting:
m_lblStatus->setText(tr("%1 is connecting...").arg(kAppName)); updateTimerLabel();
if (Settings::value(Settings::Client::DynamicConnectionRetry).toBool())
m_retryTimer->start();
break; break;
case Connected: { case Connected: {
setSecurityIconVisible(true); setSecurityIconVisible(true);
m_connectionInterval = -1;
if (!isServer) { if (!isServer) {
m_lblStatus->setText(tr("%1 is connected as client of %2") m_lblStatus->setText(tr("%1 is connected as client of %2")
.arg(kAppName, Settings::value(Settings::Client::RemoteHost).toString())); .arg(kAppName, Settings::value(Settings::Client::RemoteHost).toString()));
@ -100,6 +115,7 @@ void StatusBar::setStatus(ConnectionState connectionState, ProcessState processS
case Disconnected: case Disconnected:
m_lblStatus->setText(tr("%1 is disconnected").arg(kAppName)); m_lblStatus->setText(tr("%1 is disconnected").arg(kAppName));
m_connectionInterval = -1;
break; break;
} }
} }
@ -132,6 +148,11 @@ void StatusBar::setSecurityIconVisible(bool visible)
m_lblSecurityIcon->setVisible(visible); m_lblSecurityIcon->setVisible(visible);
} }
void StatusBar::setConnectionInterval(int newInterval)
{
m_connectionInterval = newInterval;
}
bool StatusBar::securityIconVisible() const bool StatusBar::securityIconVisible() const
{ {
return m_lblSecurityIcon->isVisible(); return m_lblSecurityIcon->isVisible();
@ -162,6 +183,18 @@ void StatusBar::updateText()
setSecurityLevel(m_securityLevel); 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) void StatusBar::setSecurityIcon(bool encrypted)
{ {
const auto icon = QIcon::fromTheme(encrypted ? QIcon::ThemeIcon::SecurityHigh : QIcon::ThemeIcon::SecurityLow); const auto icon = QIcon::fromTheme(encrypted ? QIcon::ThemeIcon::SecurityHigh : QIcon::ThemeIcon::SecurityLow);

View file

@ -24,6 +24,7 @@ public:
void setStatus(ConnectionState connectionState, ProcessState processState, bool isServer); void setStatus(ConnectionState connectionState, ProcessState processState, bool isServer);
void setServerClients(const QStringList &clients); void setServerClients(const QStringList &clients);
void setSecurityIconVisible(bool visible); void setSecurityIconVisible(bool visible);
void setConnectionInterval(int newInterval);
bool securityIconVisible() const; bool securityIconVisible() const;
void updateSecurityInfo(bool encrypted); void updateSecurityInfo(bool encrypted);
void setSecurityIcon(bool encrypted); void setSecurityIcon(bool encrypted);
@ -40,10 +41,13 @@ protected:
private: private:
void updateText(); void updateText();
void updateTimerLabel();
QPushButton *m_btnFingerprint = nullptr; QPushButton *m_btnFingerprint = nullptr;
QLabel *m_lblSecurityIcon = nullptr; QLabel *m_lblSecurityIcon = nullptr;
QLabel *m_lblStatus = nullptr; QLabel *m_lblStatus = nullptr;
QPushButton *m_btnUpdate = nullptr; QPushButton *m_btnUpdate = nullptr;
bool m_encrypted = false; bool m_encrypted = false;
QString m_securityLevel; QString m_securityLevel;
int m_connectionInterval = -1;
QTimer *m_retryTimer = nullptr;
}; };

View file

@ -1348,10 +1348,6 @@ Al habilitar esta opción, se deshabilitará la interfaz gráfica de usuario (GU
<source>%1 is waiting for clients</source> <source>%1 is waiting for clients</source>
<translation type="unfinished">%1 está esperando clientes</translation> <translation type="unfinished">%1 está esperando clientes</translation>
</message> </message>
<message>
<source>%1 is connecting...</source>
<translation type="unfinished">%1 se está conectando...</translation>
</message>
<message> <message>
<source>%1 is connected as client of %2</source> <source>%1 is connected as client of %2</source>
<translation type="unfinished">%1 está conectado como cliente de %2</translation> <translation type="unfinished">%1 está conectado como cliente de %2</translation>
@ -1386,6 +1382,14 @@ Al habilitar esta opción, se deshabilitará la interfaz gráfica de usuario (GU
<source>Update available</source> <source>Update available</source>
<translation type="unfinished">Actualización disponible</translation> <translation type="unfinished">Actualización disponible</translation>
</message> </message>
<message>
<source>%1 is connecting...</source>
<translation>%1 se está conectando...</translation>
</message>
<message>
<source>%1 is waiting %2 seconds before the next retry</source>
<translation type="unfinished">%1 está esperando %2 segundos antes del siguiente reintento</translation>
</message>
<message> <message>
<source>%1 Encryption Enabled</source> <source>%1 Encryption Enabled</source>
<translation type="unfinished">%1 Cifrado habilitado</translation> <translation type="unfinished">%1 Cifrado habilitado</translation>

View file

@ -1348,10 +1348,6 @@ L&apos;abilitazione di questa impostazione disabiliterà l&apos;interfaccia graf
<source>%1 is waiting for clients</source> <source>%1 is waiting for clients</source>
<translation>%1 è in attesa di client</translation> <translation>%1 è in attesa di client</translation>
</message> </message>
<message>
<source>%1 is connecting...</source>
<translation>%1 è in connessione...</translation>
</message>
<message> <message>
<source>%1 is connected as client of %2</source> <source>%1 is connected as client of %2</source>
<translation>%1 è connesso come client di %2</translation> <translation>%1 è connesso come client di %2</translation>
@ -1386,6 +1382,14 @@ L&apos;abilitazione di questa impostazione disabiliterà l&apos;interfaccia graf
<source>Update available</source> <source>Update available</source>
<translation>Aggiornamento disponibile</translation> <translation>Aggiornamento disponibile</translation>
</message> </message>
<message>
<source>%1 is connecting...</source>
<translation>%1 è in connessione...</translation>
</message>
<message>
<source>%1 is waiting %2 seconds before the next retry</source>
<translation type="unfinished">%1 attende %2 secondi prima del prossimo tentativo</translation>
</message>
<message> <message>
<source>%1 Encryption Enabled</source> <source>%1 Encryption Enabled</source>
<translation>%1 Crittografia abilitata</translation> <translation>%1 Crittografia abilitata</translation>

View file

@ -1350,10 +1350,6 @@ Enabling this setting will disable the server config GUI.</source>
<source>%1 is waiting for clients</source> <source>%1 is waiting for clients</source>
<translation>%1 はクライアント接続を待機中</translation> <translation>%1 はクライアント接続を待機中</translation>
</message> </message>
<message>
<source>%1 is connecting...</source>
<translation>%1 は接続処理中…</translation>
</message>
<message> <message>
<source>%1 is connected as client of %2</source> <source>%1 is connected as client of %2</source>
<translation>%1 は %2 にクライアントとして接続中</translation> <translation>%1 は %2 にクライアントとして接続中</translation>
@ -1387,6 +1383,14 @@ Enabling this setting will disable the server config GUI.</source>
<source>Update available</source> <source>Update available</source>
<translation>ソフトウェア更新あり</translation> <translation>ソフトウェア更新あり</translation>
</message> </message>
<message>
<source>%1 is connecting...</source>
<translation>%1 は接続処理中…</translation>
</message>
<message>
<source>%1 is waiting %2 seconds before the next retry</source>
<translation type="unfinished">%1 は次の再試行まで %2 秒待機しています</translation>
</message>
<message> <message>
<source>%1 Encryption Enabled</source> <source>%1 Encryption Enabled</source>
<translation>%1 暗号化有効</translation> <translation>%1 暗号化有効</translation>

View file

@ -1348,10 +1348,6 @@ Enabling this setting will disable the server config GUI.</source>
<source>%1 is waiting for clients</source> <source>%1 is waiting for clients</source>
<translation>%1 클라이언트를 기다리는 중</translation> <translation>%1 클라이언트를 기다리는 중</translation>
</message> </message>
<message>
<source>%1 is connecting...</source>
<translation>%1 연결 중...</translation>
</message>
<message> <message>
<source>%1 is connected as client of %2</source> <source>%1 is connected as client of %2</source>
<translation>%1이(가) %2의 클라이언트로 연결되었습니다</translation> <translation>%1이(가) %2의 클라이언트로 연결되었습니다</translation>
@ -1385,6 +1381,14 @@ Enabling this setting will disable the server config GUI.</source>
<source>Update available</source> <source>Update available</source>
<translation>업데이트 사용 가능</translation> <translation>업데이트 사용 가능</translation>
</message> </message>
<message>
<source>%1 is connecting...</source>
<translation>%1 연결 중...</translation>
</message>
<message>
<source>%1 is waiting %2 seconds before the next retry</source>
<translation type="unfinished">%1이 다음 재시도까지 %2초 대기 중입니다</translation>
</message>
<message> <message>
<source>%1 Encryption Enabled</source> <source>%1 Encryption Enabled</source>
<translation>%1 암호화 사용</translation> <translation>%1 암호화 사용</translation>

View file

@ -1346,10 +1346,6 @@ Enabling this setting will disable the server config GUI.</source>
<source>%1 is waiting for clients</source> <source>%1 is waiting for clients</source>
<translation>%1 ожидает подключения клиентов</translation> <translation>%1 ожидает подключения клиентов</translation>
</message> </message>
<message>
<source>%1 is connecting...</source>
<translation>%1 подключается...</translation>
</message>
<message> <message>
<source>%1 is connected as client of %2</source> <source>%1 is connected as client of %2</source>
<translation>%1 подключен как клиент к %2</translation> <translation>%1 подключен как клиент к %2</translation>
@ -1385,6 +1381,14 @@ Enabling this setting will disable the server config GUI.</source>
<source>Update available</source> <source>Update available</source>
<translation>Доступно обновление</translation> <translation>Доступно обновление</translation>
</message> </message>
<message>
<source>%1 is connecting...</source>
<translation>%1 подключается...</translation>
</message>
<message>
<source>%1 is waiting %2 seconds before the next retry</source>
<translation type="unfinished">%1 ожидает %2 секунд перед следующей попыткой</translation>
</message>
<message> <message>
<source>%1 Encryption Enabled</source> <source>%1 Encryption Enabled</source>
<translation>Шифрование %1 включено</translation> <translation>Шифрование %1 включено</translation>

View file

@ -1350,10 +1350,6 @@ Enabling this setting will disable the server config GUI.</source>
<source>%1 is waiting for clients</source> <source>%1 is waiting for clients</source>
<translation>%1 正在等待客户端连接</translation> <translation>%1 正在等待客户端连接</translation>
</message> </message>
<message>
<source>%1 is connecting...</source>
<translation>%1 正在连接...</translation>
</message>
<message> <message>
<source>%1 is connected as client of %2</source> <source>%1 is connected as client of %2</source>
<translation>%1 已作为 %2 的客户端连接</translation> <translation>%1 已作为 %2 的客户端连接</translation>
@ -1387,6 +1383,14 @@ Enabling this setting will disable the server config GUI.</source>
<source>Update available</source> <source>Update available</source>
<translation>有可用更新</translation> <translation>有可用更新</translation>
</message> </message>
<message>
<source>%1 is connecting...</source>
<translation>%1 正在连接...</translation>
</message>
<message>
<source>%1 is waiting %2 seconds before the next retry</source>
<translation type="unfinished">%1 正在等待 %2 秒,然后进行下一次重试</translation>
</message>
<message> <message>
<source>%1 Encryption Enabled</source> <source>%1 Encryption Enabled</source>
<translation>%1 加密已启用</translation> <translation>%1 加密已启用</translation>