471 lines
14 KiB
C++
471 lines
14 KiB
C++
#include "networktestwidget.h"
|
|
#include "overlaydialogswidget.h"
|
|
#include <QScrollArea>
|
|
#include <QDateTime>
|
|
#include <QDebug>
|
|
|
|
// 样式常量定义
|
|
const QString NetworkTestWidget::BUTTON_STYLE = R"(
|
|
QPushButton {
|
|
background-color: #f5f5f5;
|
|
color: #333333;
|
|
border: 1px solid #ddd;
|
|
border-radius: 6px;
|
|
padding: 8px 16px;
|
|
font-size: 14px;
|
|
font-weight: 500;
|
|
min-height: 36px;
|
|
}
|
|
QPushButton:hover {
|
|
background-color: #e8e8e8;
|
|
border-color: #ccc;
|
|
}
|
|
QPushButton:pressed {
|
|
background-color: #d0d0d0;
|
|
}
|
|
QPushButton:disabled {
|
|
background-color: #f0f0f0;
|
|
color: #999;
|
|
}
|
|
)";
|
|
|
|
const QString NetworkTestWidget::PRIMARY_BUTTON_STYLE = R"(
|
|
QPushButton {
|
|
background-color: #2196F3;
|
|
color: white;
|
|
border: none;
|
|
border-radius: 6px;
|
|
padding: 8px 16px;
|
|
font-size: 14px;
|
|
font-weight: 500;
|
|
min-height: 36px;
|
|
}
|
|
QPushButton:hover {
|
|
background-color: #1976D2;
|
|
}
|
|
QPushButton:pressed {
|
|
background-color: #1565C0;
|
|
}
|
|
QPushButton:disabled {
|
|
background-color: #90CAF9;
|
|
}
|
|
)";
|
|
|
|
const QString NetworkTestWidget::INPUT_STYLE = R"(
|
|
QLineEdit {
|
|
background-color: white;
|
|
border: 1px solid #ddd;
|
|
border-radius: 6px;
|
|
padding: 8px 12px;
|
|
font-size: 14px;
|
|
min-height: 36px;
|
|
}
|
|
QLineEdit:focus {
|
|
border-color: #2196F3;
|
|
}
|
|
)";
|
|
|
|
const QString NetworkTestWidget::GROUP_STYLE = R"(
|
|
QGroupBox {
|
|
background-color: white;
|
|
border: 1px solid #e0e0e0;
|
|
border-radius: 8px;
|
|
margin-top: 16px;
|
|
padding-top: 16px;
|
|
font-size: 14px;
|
|
font-weight: 600;
|
|
}
|
|
QGroupBox::title {
|
|
subcontrol-origin: margin;
|
|
left: 16px;
|
|
padding: 0 8px;
|
|
color: #333;
|
|
}
|
|
)";
|
|
|
|
NetworkTestWidget::NetworkTestWidget(QWidget *parent)
|
|
: QWidget(parent), m_testStep(0)
|
|
{
|
|
setupUI();
|
|
|
|
m_testTimer = new QTimer(this);
|
|
connect(m_testTimer, &QTimer::timeout, this, [this]()
|
|
{
|
|
m_testStep++;
|
|
m_progressBar->setValue(m_testStep * 10);
|
|
|
|
if (m_testStep >= 10) {
|
|
m_testTimer->stop();
|
|
m_progressBar->setValue(100);
|
|
} });
|
|
}
|
|
|
|
void NetworkTestWidget::setupUI()
|
|
{
|
|
QVBoxLayout *mainLayout = new QVBoxLayout(this);
|
|
mainLayout->setContentsMargins(0, 0, 0, 0);
|
|
mainLayout->setSpacing(0);
|
|
|
|
// 标题栏
|
|
mainLayout->addWidget(createTitleBar());
|
|
|
|
// 内容区域
|
|
QScrollArea *scrollArea = new QScrollArea;
|
|
scrollArea->setWidgetResizable(true);
|
|
scrollArea->setFrameShape(QFrame::NoFrame);
|
|
scrollArea->setStyleSheet("QScrollArea { background-color: #f5f5f5; }");
|
|
|
|
QWidget *contentWidget = new QWidget;
|
|
contentWidget->setStyleSheet("background-color: #f5f5f5;");
|
|
QVBoxLayout *contentLayout = new QVBoxLayout(contentWidget);
|
|
contentLayout->setContentsMargins(20, 20, 20, 20);
|
|
contentLayout->setSpacing(16);
|
|
|
|
contentLayout->addWidget(createTestPanel());
|
|
contentLayout->addWidget(createResultPanel(), 1);
|
|
|
|
scrollArea->setWidget(contentWidget);
|
|
mainLayout->addWidget(scrollArea, 1);
|
|
}
|
|
|
|
QWidget *NetworkTestWidget::createTitleBar()
|
|
{
|
|
QWidget *titleBar = new QWidget;
|
|
titleBar->setFixedHeight(60);
|
|
titleBar->setStyleSheet("background: qlineargradient(x1:0, y1:0, x2:1, y2:0, stop:0 #1976D2, stop:1 #1565C0);");
|
|
|
|
QHBoxLayout *layout = new QHBoxLayout(titleBar);
|
|
layout->setContentsMargins(16, 0, 16, 0);
|
|
|
|
// 返回按钮
|
|
m_backBtn = new QPushButton("← 返回");
|
|
m_backBtn->setCursor(Qt::PointingHandCursor);
|
|
m_backBtn->setStyleSheet(R"(
|
|
QPushButton {
|
|
background: rgba(255,255,255,0.2);
|
|
color: white;
|
|
border: none;
|
|
border-radius: 6px;
|
|
padding: 8px 16px;
|
|
font-size: 14px;
|
|
}
|
|
QPushButton:hover {
|
|
background: rgba(255,255,255,0.3);
|
|
}
|
|
)");
|
|
connect(m_backBtn, &QPushButton::clicked, this, &NetworkTestWidget::backRequested);
|
|
layout->addWidget(m_backBtn);
|
|
|
|
// 标题(居中)
|
|
m_titleLabel = new QLabel("网络测试");
|
|
m_titleLabel->setStyleSheet("color: white; font-size: 18px; font-weight: bold;");
|
|
m_titleLabel->setAlignment(Qt::AlignCenter);
|
|
layout->addWidget(m_titleLabel, 1);
|
|
|
|
// 右侧占位,保持标题居中
|
|
QWidget *spacer = new QWidget;
|
|
spacer->setFixedWidth(m_backBtn->sizeHint().width());
|
|
layout->addWidget(spacer);
|
|
|
|
return titleBar;
|
|
}
|
|
|
|
QWidget *NetworkTestWidget::createTestPanel()
|
|
{
|
|
QGroupBox *group = new QGroupBox("测试设置");
|
|
group->setStyleSheet(GROUP_STYLE);
|
|
|
|
QVBoxLayout *layout = new QVBoxLayout(group);
|
|
layout->setContentsMargins(16, 24, 16, 16);
|
|
layout->setSpacing(16);
|
|
|
|
// Ping测试
|
|
QHBoxLayout *pingLayout = new QHBoxLayout;
|
|
QLabel *pingLabel = new QLabel("Ping主机:");
|
|
pingLabel->setFixedWidth(80);
|
|
pingLabel->setStyleSheet("font-size: 14px; color: #333;");
|
|
pingLayout->addWidget(pingLabel);
|
|
|
|
m_hostEdit = new QLineEdit;
|
|
m_hostEdit->setStyleSheet(INPUT_STYLE);
|
|
m_hostEdit->setText("www.baidu.com");
|
|
m_hostEdit->setPlaceholderText("输入主机名或IP地址");
|
|
pingLayout->addWidget(m_hostEdit, 1);
|
|
|
|
m_pingBtn = new QPushButton("Ping测试");
|
|
m_pingBtn->setStyleSheet(PRIMARY_BUTTON_STYLE);
|
|
m_pingBtn->setFixedWidth(100);
|
|
m_pingBtn->setCursor(Qt::PointingHandCursor);
|
|
connect(m_pingBtn, &QPushButton::clicked, this, &NetworkTestWidget::onPingTest);
|
|
pingLayout->addWidget(m_pingBtn);
|
|
|
|
layout->addLayout(pingLayout);
|
|
|
|
// 服务器连接测试
|
|
QHBoxLayout *serverLayout = new QHBoxLayout;
|
|
QLabel *serverLabel = new QLabel("服务器:");
|
|
serverLabel->setFixedWidth(80);
|
|
serverLabel->setStyleSheet("font-size: 14px; color: #333;");
|
|
serverLayout->addWidget(serverLabel);
|
|
|
|
m_serverEdit = new QLineEdit;
|
|
m_serverEdit->setStyleSheet(INPUT_STYLE);
|
|
m_serverEdit->setText("192.168.1.100");
|
|
m_serverEdit->setPlaceholderText("服务器地址");
|
|
serverLayout->addWidget(m_serverEdit, 1);
|
|
|
|
QLabel *portLabel = new QLabel("端口:");
|
|
portLabel->setStyleSheet("font-size: 14px; color: #333;");
|
|
serverLayout->addWidget(portLabel);
|
|
|
|
m_portEdit = new QLineEdit;
|
|
m_portEdit->setStyleSheet(INPUT_STYLE);
|
|
m_portEdit->setFixedWidth(80);
|
|
m_portEdit->setText("8080");
|
|
serverLayout->addWidget(m_portEdit);
|
|
|
|
m_serverTestBtn = new QPushButton("连接测试");
|
|
m_serverTestBtn->setStyleSheet(PRIMARY_BUTTON_STYLE);
|
|
m_serverTestBtn->setFixedWidth(100);
|
|
m_serverTestBtn->setCursor(Qt::PointingHandCursor);
|
|
connect(m_serverTestBtn, &QPushButton::clicked, this, &NetworkTestWidget::onServerTest);
|
|
serverLayout->addWidget(m_serverTestBtn);
|
|
|
|
layout->addLayout(serverLayout);
|
|
|
|
// 其他测试按钮
|
|
QHBoxLayout *otherLayout = new QHBoxLayout;
|
|
|
|
m_dnsTestBtn = new QPushButton("DNS解析测试");
|
|
m_dnsTestBtn->setStyleSheet(BUTTON_STYLE);
|
|
m_dnsTestBtn->setCursor(Qt::PointingHandCursor);
|
|
connect(m_dnsTestBtn, &QPushButton::clicked, this, &NetworkTestWidget::onDnsTest);
|
|
otherLayout->addWidget(m_dnsTestBtn);
|
|
|
|
m_speedTestBtn = new QPushButton("网速测试");
|
|
m_speedTestBtn->setStyleSheet(BUTTON_STYLE);
|
|
m_speedTestBtn->setCursor(Qt::PointingHandCursor);
|
|
connect(m_speedTestBtn, &QPushButton::clicked, this, &NetworkTestWidget::onSpeedTest);
|
|
otherLayout->addWidget(m_speedTestBtn);
|
|
|
|
otherLayout->addStretch();
|
|
|
|
layout->addLayout(otherLayout);
|
|
|
|
return group;
|
|
}
|
|
|
|
QWidget *NetworkTestWidget::createResultPanel()
|
|
{
|
|
QGroupBox *group = new QGroupBox("测试结果");
|
|
group->setStyleSheet(GROUP_STYLE);
|
|
|
|
QVBoxLayout *layout = new QVBoxLayout(group);
|
|
layout->setContentsMargins(16, 24, 16, 16);
|
|
layout->setSpacing(12);
|
|
|
|
// 进度条
|
|
m_progressBar = new QProgressBar;
|
|
m_progressBar->setFixedHeight(6);
|
|
m_progressBar->setRange(0, 100);
|
|
m_progressBar->setValue(0);
|
|
m_progressBar->setTextVisible(false);
|
|
m_progressBar->setStyleSheet(R"(
|
|
QProgressBar {
|
|
background-color: #e0e0e0;
|
|
border-radius: 3px;
|
|
}
|
|
QProgressBar::chunk {
|
|
background-color: #4CAF50;
|
|
border-radius: 3px;
|
|
}
|
|
)");
|
|
layout->addWidget(m_progressBar);
|
|
|
|
// 日志显示
|
|
m_logEdit = new QTextEdit;
|
|
m_logEdit->setReadOnly(true);
|
|
m_logEdit->setStyleSheet(R"(
|
|
QTextEdit {
|
|
background-color: #1e1e1e;
|
|
color: #d4d4d4;
|
|
border: 1px solid #ddd;
|
|
border-radius: 6px;
|
|
padding: 12px;
|
|
font-family: 'Courier New', monospace;
|
|
font-size: 13px;
|
|
}
|
|
)");
|
|
m_logEdit->setMinimumHeight(300);
|
|
layout->addWidget(m_logEdit, 1);
|
|
|
|
// 清除按钮
|
|
QHBoxLayout *buttonLayout = new QHBoxLayout;
|
|
buttonLayout->addStretch();
|
|
|
|
m_clearBtn = new QPushButton("清除日志");
|
|
m_clearBtn->setStyleSheet(BUTTON_STYLE);
|
|
m_clearBtn->setFixedWidth(100);
|
|
m_clearBtn->setCursor(Qt::PointingHandCursor);
|
|
connect(m_clearBtn, &QPushButton::clicked, this, &NetworkTestWidget::onClearLog);
|
|
buttonLayout->addWidget(m_clearBtn);
|
|
|
|
layout->addLayout(buttonLayout);
|
|
|
|
// 添加初始日志
|
|
appendLog("网络测试工具已就绪", "#4CAF50");
|
|
appendLog("请选择测试项目开始测试...", "#888");
|
|
|
|
return group;
|
|
}
|
|
|
|
void NetworkTestWidget::appendLog(const QString &message, const QString &color)
|
|
{
|
|
QString timestamp = QDateTime::currentDateTime().toString("hh:mm:ss");
|
|
QString html = QString("<span style='color: #888;'>[%1]</span> <span style='color: %2;'>%3</span><br>")
|
|
.arg(timestamp, color, message);
|
|
m_logEdit->insertHtml(html);
|
|
m_logEdit->moveCursor(QTextCursor::End);
|
|
}
|
|
|
|
void NetworkTestWidget::onPingTest()
|
|
{
|
|
QString host = m_hostEdit->text().trimmed();
|
|
if (host.isEmpty())
|
|
{
|
|
OverlayDialog::warning(window(), "提示", "请输入要Ping的主机名或IP地址");
|
|
return;
|
|
}
|
|
|
|
m_pingBtn->setEnabled(false);
|
|
m_progressBar->setValue(0);
|
|
m_testStep = 0;
|
|
|
|
appendLog(QString("开始Ping测试: %1").arg(host), "#2196F3");
|
|
|
|
m_testTimer->start(200);
|
|
|
|
// 模拟Ping测试
|
|
QTimer::singleShot(2000, this, [this, host]()
|
|
{
|
|
m_testTimer->stop();
|
|
m_progressBar->setValue(100);
|
|
m_pingBtn->setEnabled(true);
|
|
|
|
// 模拟结果
|
|
appendLog(QString("正在解析主机 %1...").arg(host), "#888");
|
|
appendLog(QString("目标IP: 110.242.68.66"), "#888");
|
|
appendLog("", "#888");
|
|
appendLog("来自 110.242.68.66 的回复: 字节=64 时间=15ms TTL=52", "#4CAF50");
|
|
appendLog("来自 110.242.68.66 的回复: 字节=64 时间=14ms TTL=52", "#4CAF50");
|
|
appendLog("来自 110.242.68.66 的回复: 字节=64 时间=16ms TTL=52", "#4CAF50");
|
|
appendLog("来自 110.242.68.66 的回复: 字节=64 时间=15ms TTL=52", "#4CAF50");
|
|
appendLog("", "#888");
|
|
appendLog("Ping统计: 已发送=4, 已接收=4, 丢失=0 (0% 丢失)", "#4CAF50");
|
|
appendLog("往返时间: 最短=14ms, 最长=16ms, 平均=15ms", "#888");
|
|
appendLog("", "#888");
|
|
appendLog("✓ Ping测试完成", "#4CAF50"); });
|
|
}
|
|
|
|
void NetworkTestWidget::onSpeedTest()
|
|
{
|
|
m_speedTestBtn->setEnabled(false);
|
|
m_progressBar->setValue(0);
|
|
m_testStep = 0;
|
|
|
|
appendLog("开始网速测试...", "#2196F3");
|
|
|
|
m_testTimer->start(300);
|
|
|
|
QTimer::singleShot(3000, this, [this]()
|
|
{
|
|
m_testTimer->stop();
|
|
m_progressBar->setValue(100);
|
|
m_speedTestBtn->setEnabled(true);
|
|
|
|
appendLog("正在测试下载速度...", "#888");
|
|
appendLog("下载速度: 45.6 Mbps", "#4CAF50");
|
|
appendLog("正在测试上传速度...", "#888");
|
|
appendLog("上传速度: 12.3 Mbps", "#4CAF50");
|
|
appendLog("网络延迟: 18ms", "#888");
|
|
appendLog("抖动: 2ms", "#888");
|
|
appendLog("", "#888");
|
|
appendLog("✓ 网速测试完成", "#4CAF50"); });
|
|
}
|
|
|
|
void NetworkTestWidget::onDnsTest()
|
|
{
|
|
m_dnsTestBtn->setEnabled(false);
|
|
m_progressBar->setValue(0);
|
|
m_testStep = 0;
|
|
|
|
appendLog("开始DNS解析测试...", "#2196F3");
|
|
|
|
m_testTimer->start(150);
|
|
|
|
QTimer::singleShot(1500, this, [this]()
|
|
{
|
|
m_testTimer->stop();
|
|
m_progressBar->setValue(100);
|
|
m_dnsTestBtn->setEnabled(true);
|
|
|
|
appendLog("DNS服务器: 114.114.114.114", "#888");
|
|
appendLog("", "#888");
|
|
appendLog("www.baidu.com -> 110.242.68.66 (8ms)", "#4CAF50");
|
|
appendLog("www.google.com -> 142.250.80.46 (25ms)", "#4CAF50");
|
|
appendLog("www.github.com -> 20.205.243.166 (45ms)", "#4CAF50");
|
|
appendLog("", "#888");
|
|
appendLog("✓ DNS解析测试完成", "#4CAF50"); });
|
|
}
|
|
|
|
void NetworkTestWidget::onServerTest()
|
|
{
|
|
QString server = m_serverEdit->text().trimmed();
|
|
QString port = m_portEdit->text().trimmed();
|
|
|
|
if (server.isEmpty())
|
|
{
|
|
OverlayDialog::warning(window(), "提示", "请输入服务器地址");
|
|
return;
|
|
}
|
|
|
|
m_serverTestBtn->setEnabled(false);
|
|
m_progressBar->setValue(0);
|
|
m_testStep = 0;
|
|
|
|
appendLog(QString("开始连接测试: %1:%2").arg(server, port), "#2196F3");
|
|
|
|
m_testTimer->start(200);
|
|
|
|
QTimer::singleShot(2000, this, [this, server, port]()
|
|
{
|
|
m_testTimer->stop();
|
|
m_progressBar->setValue(100);
|
|
m_serverTestBtn->setEnabled(true);
|
|
|
|
// 随机模拟成功或超时
|
|
bool success = (QDateTime::currentMSecsSinceEpoch() % 3) != 0;
|
|
|
|
if (success) {
|
|
appendLog(QString("正在连接 %1:%2...").arg(server, port), "#888");
|
|
appendLog("TCP握手成功", "#4CAF50");
|
|
appendLog("连接延迟: 25ms", "#888");
|
|
appendLog("服务器响应: HTTP 200 OK", "#4CAF50");
|
|
appendLog("", "#888");
|
|
appendLog("✓ 服务器连接测试成功", "#4CAF50");
|
|
} else {
|
|
appendLog(QString("正在连接 %1:%2...").arg(server, port), "#888");
|
|
appendLog("连接超时 (5000ms)", "#f44336");
|
|
appendLog("", "#888");
|
|
appendLog("✗ 服务器连接测试失败", "#f44336");
|
|
appendLog("请检查服务器地址和端口是否正确", "#ff9800");
|
|
} });
|
|
}
|
|
|
|
void NetworkTestWidget::onClearLog()
|
|
{
|
|
m_logEdit->clear();
|
|
m_progressBar->setValue(0);
|
|
appendLog("日志已清除", "#888");
|
|
}
|