|
|
|
|
@ -1,5 +1,6 @@
|
|
|
|
|
// statuspage.cpp — Status page (NTP + connections) in settings
|
|
|
|
|
#include "statuspage.h" |
|
|
|
|
#include "../transport/utun_node.h" |
|
|
|
|
|
|
|
|
|
extern "C" { |
|
|
|
|
#include "../transport/gui_bridge.h" |
|
|
|
|
@ -10,6 +11,8 @@ extern "C" {
|
|
|
|
|
#include <QHBoxLayout> |
|
|
|
|
#include <QLabel> |
|
|
|
|
#include <QFont> |
|
|
|
|
#include <QTimer> |
|
|
|
|
#include <QDateTime> |
|
|
|
|
|
|
|
|
|
static StatusPage* g_activeStatusPage = nullptr; |
|
|
|
|
|
|
|
|
|
@ -18,13 +21,35 @@ static void statusRefreshCallback(const char* text, int len) {
|
|
|
|
|
g_activeStatusPage->setText(QString::fromUtf8(text, len)); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
StatusPage::StatusPage(QWidget* parent) |
|
|
|
|
StatusPage::StatusPage(UtunNode* node, QWidget* parent) |
|
|
|
|
: QWidget(parent) |
|
|
|
|
, m_node(node) |
|
|
|
|
{ |
|
|
|
|
auto* layout = new QVBoxLayout(this); |
|
|
|
|
layout->setSpacing(8); |
|
|
|
|
layout->setContentsMargins(0, 0, 0, 0); |
|
|
|
|
|
|
|
|
|
/* ── clock block ── */ |
|
|
|
|
m_clockFrame = new QFrame(this); |
|
|
|
|
m_clockFrame->setFrameStyle(QFrame::StyledPanel | QFrame::Sunken); |
|
|
|
|
m_clockFrame->setStyleSheet( |
|
|
|
|
"QFrame { border: 1px solid palette(mid); border-radius: 6px;" |
|
|
|
|
" padding: 10px; background: palette(alternate-base); }"); |
|
|
|
|
|
|
|
|
|
auto* clockLayout = new QVBoxLayout(m_clockFrame); |
|
|
|
|
clockLayout->setContentsMargins(12, 8, 12, 8); |
|
|
|
|
|
|
|
|
|
m_clockLabel = new QLabel("--:--:--", m_clockFrame); |
|
|
|
|
QFont clockFont("monospace", 22); |
|
|
|
|
clockFont.setBold(true); |
|
|
|
|
m_clockLabel->setFont(clockFont); |
|
|
|
|
m_clockLabel->setAlignment(Qt::AlignCenter); |
|
|
|
|
m_clockLabel->setStyleSheet("border: none; color: palette(text);"); |
|
|
|
|
clockLayout->addWidget(m_clockLabel); |
|
|
|
|
|
|
|
|
|
layout->addWidget(m_clockFrame); |
|
|
|
|
|
|
|
|
|
/* ── System Status section ── */ |
|
|
|
|
auto* title = new QLabel("System Status", this); |
|
|
|
|
title->setStyleSheet("font-weight: bold; font-size: 13px;"); |
|
|
|
|
layout->addWidget(title); |
|
|
|
|
@ -50,15 +75,43 @@ StatusPage::StatusPage(QWidget* parent)
|
|
|
|
|
btnLayout->addWidget(m_refreshBtn); |
|
|
|
|
layout->addLayout(btnLayout); |
|
|
|
|
|
|
|
|
|
m_clockTimer = new QTimer(this); |
|
|
|
|
m_clockTimer->setSingleShot(true); |
|
|
|
|
m_clockTimer->setTimerType(Qt::PreciseTimer); |
|
|
|
|
connect(m_clockTimer, &QTimer::timeout, this, &StatusPage::updateClock); |
|
|
|
|
|
|
|
|
|
g_activeStatusPage = this; |
|
|
|
|
gui_bridge_set_status_refresh_cb(statusRefreshCallback); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
StatusPage::~StatusPage() { |
|
|
|
|
m_clockTimer->stop(); |
|
|
|
|
if (g_activeStatusPage == this) g_activeStatusPage = nullptr; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void StatusPage::updateClock() { |
|
|
|
|
if (!m_node) return; |
|
|
|
|
|
|
|
|
|
qint64 nowMs = QDateTime::currentMSecsSinceEpoch(); |
|
|
|
|
int64_t offsetUs = m_node->ntpOffsetUs(); |
|
|
|
|
bool synced = m_node->ntpSynced(); |
|
|
|
|
|
|
|
|
|
qint64 correctedMs = nowMs - (offsetUs / 1000); |
|
|
|
|
QDateTime corrected = QDateTime::fromMSecsSinceEpoch(correctedMs).toLocalTime(); |
|
|
|
|
|
|
|
|
|
QString t = corrected.toString("HH:mm:ss"); |
|
|
|
|
|
|
|
|
|
if (synced) |
|
|
|
|
m_clockLabel->setText(QString("%1 [NTP ✓]").arg(t)); |
|
|
|
|
else |
|
|
|
|
m_clockLabel->setText(QString("%1 [LOCAL]").arg(t)); |
|
|
|
|
|
|
|
|
|
int msToNext = 1000 - (corrected.time().msec()); |
|
|
|
|
m_clockTimer->start(msToNext); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void StatusPage::refreshStatus() { |
|
|
|
|
updateClock(); |
|
|
|
|
m_textEdit->setPlainText("Loading..."); |
|
|
|
|
gui_bridge_post_uasync_fn(chat_core_collect_status_trampoline, NULL); |
|
|
|
|
} |
|
|
|
|
|