Cockatrice/cockatrice/src/client/latency_status_widget.cpp
BruebachL e806085681
[QtUtils] Use makeLayout() for zero-margin layouts (#7620)
* [QtUtils] Add parent lookup, layout clearing, scroll area and monospace helpers

* [QtUtils] Adopt shared Qt helpers across the client

* [QtUtils] Add layout creation and relayout helpers

* Swap parameter order (spacing before margin) and remove static from relayout()

* [QtUtils] Use relayout() after rebuilding dynamic layouts

* [QtUtils] Use makeLayout() for zero-margin layouts

* Consolidate setSpacing() calls into makeLayout() using new parameter order

---------

Co-authored-by: Lukas Brübach <Bruebach.Lukas@bdosecurity.de>
2026-10-24 19:06:18 +02:00

114 lines
3.4 KiB
C++

/**
* @file latency_status_widget.cpp
* @ingroup Client
*/
#include "latency_status_widget.h"
#include "latency_graph_widget.h"
#include "latency_tracker.h"
#include <QEvent>
#include <QHBoxLayout>
#include <QLabel>
#include <QObject>
#include <QPoint>
#include <QVBoxLayout>
#include <libcockatrice/utility/qt_utils.h>
#include <qnamespace.h>
LatencyStatusWidget::LatencyStatusWidget(QWidget *parent) : QWidget(parent)
{
pingLabel = new QLabel(this);
pingLabel->setAccessibleName(tr("Ping"));
latencyGraph = new LatencyGraphWidget(this);
latencyGraph->setFixedSize(90, 14);
auto *layout = QtUtils::makeLayout<QHBoxLayout>(this, 4);
layout->addWidget(latencyGraph);
layout->addWidget(pingLabel);
// Clicking anywhere in the area opens the detail view.
for (QObject *child : QList<QObject *>{pingLabel, latencyGraph}) {
child->installEventFilter(this);
}
setCursor(Qt::PointingHandCursor);
hide();
}
void LatencyStatusWidget::updateData(const LatencyTracker::Stats &stats, const QList<int> &samplesMs)
{
latestSamples = samplesMs;
latencyGraph->setSamples(samplesMs);
if (popup && popup->isVisible() && detailGraph) {
detailGraph->setSamples(samplesMs);
}
if (stats.sampleCount == 0) {
hide();
return;
}
const QString statsStr = statsText(stats);
pingLabel->setText(tr("Ping: %1 ms").arg(stats.lastMs));
pingLabel->setToolTip(statsStr);
pingLabel->setAccessibleDescription(statsStr);
if (popup && popup->isVisible() && detailLabel) {
detailLabel->setText(statsStr);
}
show();
}
bool LatencyStatusWidget::eventFilter(QObject *watched, QEvent *event)
{
if ((watched == pingLabel || watched == latencyGraph) && event->type() == QEvent::MouseButtonPress) {
togglePopup();
return true;
}
return QWidget::eventFilter(watched, event);
}
void LatencyStatusWidget::togglePopup()
{
if (!popup) {
popup = new QWidget(this, Qt::Popup | Qt::FramelessWindowHint);
auto *layout = new QVBoxLayout(popup);
layout->setContentsMargins(8, 8, 8, 8);
detailLabel = new QLabel(popup);
detailLabel->setAccessibleName(tr("Connection latency details"));
detailLabel->setTextInteractionFlags(Qt::TextSelectableByMouse);
detailGraph = new LatencyGraphWidget(popup);
detailGraph->setFixedSize(280, 80);
layout->addWidget(detailLabel, 0, Qt::AlignLeft);
layout->addWidget(detailGraph, 0, Qt::AlignHCenter);
}
if (popup->isVisible()) {
popup->hide();
return;
}
// Qt::Popup closes itself on any outside click, so just position and show.
if (latestSamples.isEmpty()) {
return;
}
detailGraph->setSamples(latestSamples);
detailLabel->setText(pingLabel->toolTip());
popup->adjustSize();
const QPoint anchor = mapToGlobal(QPoint(width() / 2, 0));
popup->move(anchor.x() - popup->width() / 2, anchor.y() - popup->height() - 6);
popup->show();
}
QString LatencyStatusWidget::statsText(const LatencyTracker::Stats &stats) const
{
return tr("Connection quality over the last %n sample(s):", "", stats.sampleCount) + "\n" +
tr("Last: %1 ms").arg(stats.lastMs) + "\n" + tr("Median: %1 ms").arg(stats.medianMs) + "\n" +
tr("95th percentile: %1 ms").arg(stats.p95Ms) + "\n" + tr("Maximum: %1 ms").arg(stats.maxMs);
}