新增qt程序ota
This commit is contained in:
parent
5bf62c410a
commit
faae203eb1
@ -20,12 +20,14 @@ set(SOURCES
|
||||
src/mainwindow.cpp
|
||||
src/mqttclient.cpp
|
||||
src/lightstripmanager.cpp
|
||||
src/updatesettingsdialog.cpp
|
||||
)
|
||||
|
||||
set(HEADERS
|
||||
src/mainwindow.h
|
||||
src/mqttclient.h
|
||||
src/lightstripmanager.h
|
||||
src/updatesettingsdialog.h
|
||||
)
|
||||
|
||||
add_executable(QtDemo ${SOURCES} ${HEADERS}
|
||||
|
||||
@ -1,12 +1,13 @@
|
||||
#include "mainwindow.h"
|
||||
#include "lightstripmanager.h"
|
||||
#include "updatesettingsdialog.h"
|
||||
#include <QDateTime>
|
||||
#include <QJsonObject>
|
||||
#include <QJsonDocument>
|
||||
//#include <QNetworkAccessManager>
|
||||
//#include <QNetworkRequest>
|
||||
//#include <QNetworkReply>
|
||||
//#include <QFileInfo>
|
||||
#include <QNetworkAccessManager>
|
||||
#include <QNetworkRequest>
|
||||
#include <QNetworkReply>
|
||||
#include <QFileInfo>
|
||||
#include <QDir>
|
||||
#include <QStandardPaths>
|
||||
#include <QMessageBox>
|
||||
@ -15,12 +16,24 @@
|
||||
#include <QDebug>
|
||||
#include <QScreen>
|
||||
#include <QGuiApplication>
|
||||
#include <QProgressDialog>
|
||||
#include <QFile>
|
||||
#include <QProcess>
|
||||
#include <QInputDialog>
|
||||
|
||||
MainWindow::MainWindow(QWidget *parent)
|
||||
: QMainWindow(parent), otaOperationPending(false), isUpgradeOperation(true)
|
||||
{
|
||||
// 初始化设置对象
|
||||
settings = new QSettings("TuxiApp", "LightStripSN", this);
|
||||
|
||||
// 初始化更新相关变量
|
||||
currentVersion = "1.3.0"; // 当前程序版本
|
||||
updateServerUrl = settings->value("updateServerUrl", "http://180.163.74.83:8001/version").toString();
|
||||
updateNetworkManager = new QNetworkAccessManager(this);
|
||||
updateCheckReply = nullptr;
|
||||
updateDownloadReply = nullptr;
|
||||
downloadedUpdatePath = "";
|
||||
|
||||
setupUI();
|
||||
|
||||
@ -98,7 +111,7 @@ void MainWindow::showVersionUpdateInfo()
|
||||
*/
|
||||
|
||||
void MainWindow::setupUI() {
|
||||
setWindowTitle("兔喜Test1.2 Author:Zhangzhenghao Email:zzh9953477@gmail.com");
|
||||
setWindowTitle("兔喜Test1.5 Author:Zhangzhenghao Email:zzh9953477@gmail.com");
|
||||
|
||||
// 参考qt_bak的合理尺寸设置,增加竖向高度
|
||||
setMinimumSize(850, 720); // 增加最小高度
|
||||
@ -333,6 +346,27 @@ void MainWindow::setupUI() {
|
||||
"}"
|
||||
);
|
||||
snHeaderLayout->addWidget(searchLightStripBtn);
|
||||
|
||||
// 添加清除按钮
|
||||
clearSnBtn = new QPushButton("清除列表", this);
|
||||
clearSnBtn->setMinimumHeight(26);
|
||||
clearSnBtn->setMinimumWidth(80);
|
||||
clearSnBtn->setStyleSheet(
|
||||
"QPushButton { "
|
||||
" background-color: #f44336; "
|
||||
" color: white; "
|
||||
" padding: 4px 10px; "
|
||||
" font-weight: bold; "
|
||||
" border-radius: 6px; "
|
||||
" font-size: 12px; "
|
||||
" border: none; "
|
||||
"} "
|
||||
"QPushButton:hover { "
|
||||
" background-color: #d32f2f; "
|
||||
"}"
|
||||
);
|
||||
snHeaderLayout->addWidget(clearSnBtn);
|
||||
|
||||
snLayout->addLayout(snHeaderLayout);
|
||||
|
||||
// 打开管理器按钮
|
||||
@ -1415,6 +1449,17 @@ void MainWindow::createMenus()
|
||||
|
||||
QAction *useGuideAction = helpMenu->addAction("使用说明(&U)");
|
||||
connect(useGuideAction, &QAction::triggered, this, &MainWindow::showUseGuide);
|
||||
|
||||
// 添加分隔线
|
||||
helpMenu->addSeparator();
|
||||
|
||||
// 添加手动检查更新菜单项
|
||||
QAction *checkUpdateAction = helpMenu->addAction("检查更新(&C)");
|
||||
connect(checkUpdateAction, &QAction::triggered, this, &MainWindow::checkForUpdates);
|
||||
|
||||
// 添加更新设置菜单项
|
||||
QAction *updateSettingsAction = helpMenu->addAction("更新设置(&S)");
|
||||
connect(updateSettingsAction, &QAction::triggered, this, &MainWindow::onUpdateSettingsClicked);
|
||||
}
|
||||
|
||||
void MainWindow::showAbout()
|
||||
@ -1457,3 +1502,272 @@ QString MainWindow::getTextColorForTheme() const {
|
||||
// 如果背景较暗(亮度小于0.5),使用白色文字;否则使用黑色文字
|
||||
return (luminance < 0.5) ? "white" : "black";
|
||||
}
|
||||
|
||||
// 更新功能实现
|
||||
void MainWindow::checkForUpdates()
|
||||
{
|
||||
if (updateCheckReply) {
|
||||
updateCheckReply->abort();
|
||||
updateCheckReply = nullptr;
|
||||
}
|
||||
|
||||
QNetworkRequest request{QUrl(updateServerUrl)};
|
||||
request.setHeader(QNetworkRequest::ContentTypeHeader, "application/json");
|
||||
|
||||
updateCheckReply = updateNetworkManager->get(request);
|
||||
connect(updateCheckReply, &QNetworkReply::finished, this, &MainWindow::onUpdateCheckFinished);
|
||||
}
|
||||
|
||||
void MainWindow::onUpdateCheckFinished()
|
||||
{
|
||||
if (!updateCheckReply) return;
|
||||
|
||||
if (updateCheckReply->error() == QNetworkReply::NoError) {
|
||||
QByteArray data = updateCheckReply->readAll();
|
||||
QJsonDocument doc = QJsonDocument::fromJson(data);
|
||||
QJsonObject obj = doc.object();
|
||||
|
||||
QString latestVersion = obj["version"].toString();
|
||||
QString downloadUrl = obj["downloadUrl"].toString();
|
||||
QString changelog = obj["changelog"].toString();
|
||||
|
||||
if (compareVersions(currentVersion, latestVersion) < 0) {
|
||||
showUpdateDialog(latestVersion, downloadUrl, changelog);
|
||||
} else {
|
||||
QMessageBox::information(this, "检查更新", "当前已是最新版本!");
|
||||
}
|
||||
} else {
|
||||
QMessageBox::warning(this, "检查更新失败",
|
||||
QString("无法连接到更新服务器:%1").arg(updateCheckReply->errorString()));
|
||||
}
|
||||
|
||||
updateCheckReply->deleteLater();
|
||||
updateCheckReply = nullptr;
|
||||
}
|
||||
|
||||
void MainWindow::showUpdateDialog(const QString &version, const QString &downloadUrl, const QString &changelog)
|
||||
{
|
||||
QMessageBox msgBox(this);
|
||||
msgBox.setWindowTitle("发现新版本");
|
||||
msgBox.setText(QString("发现新版本 %1").arg(version));
|
||||
msgBox.setDetailedText(changelog);
|
||||
msgBox.setStandardButtons(QMessageBox::Yes | QMessageBox::No);
|
||||
|
||||
QAbstractButton *yesButton = msgBox.button(QMessageBox::Yes);
|
||||
QAbstractButton *noButton = msgBox.button(QMessageBox::No);
|
||||
if (yesButton) yesButton->setText("立即更新");
|
||||
if (noButton) noButton->setText("稍后更新");
|
||||
|
||||
if (msgBox.exec() == QMessageBox::Yes) {
|
||||
downloadUpdate(downloadUrl);
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::downloadUpdate(const QString &downloadUrl)
|
||||
{
|
||||
if (updateDownloadReply) {
|
||||
updateDownloadReply->abort();
|
||||
updateDownloadReply = nullptr;
|
||||
}
|
||||
|
||||
QNetworkRequest request{QUrl(downloadUrl)};
|
||||
updateDownloadReply = updateNetworkManager->get(request);
|
||||
|
||||
connect(updateDownloadReply, &QNetworkReply::downloadProgress,
|
||||
this, &MainWindow::onUpdateDownloadProgress);
|
||||
connect(updateDownloadReply, &QNetworkReply::finished,
|
||||
this, &MainWindow::onUpdateDownloadFinished);
|
||||
|
||||
// 显示下载进度对话框
|
||||
QProgressDialog *progressDialog = new QProgressDialog("正在下载更新...", "取消", 0, 100, this);
|
||||
progressDialog->setWindowModality(Qt::WindowModal);
|
||||
progressDialog->show();
|
||||
|
||||
connect(progressDialog, &QProgressDialog::canceled, [this]() {
|
||||
if (updateDownloadReply) {
|
||||
updateDownloadReply->abort();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void MainWindow::onUpdateDownloadProgress(qint64 bytesReceived, qint64 bytesTotal)
|
||||
{
|
||||
if (bytesTotal > 0) {
|
||||
int progress = static_cast<int>((bytesReceived * 100) / bytesTotal);
|
||||
// 更新进度条
|
||||
QProgressDialog *progressDialog = findChild<QProgressDialog*>();
|
||||
if (progressDialog) {
|
||||
progressDialog->setValue(progress);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::onUpdateDownloadFinished()
|
||||
{
|
||||
if (!updateDownloadReply) return;
|
||||
|
||||
QProgressDialog *progressDialog = findChild<QProgressDialog*>();
|
||||
if (progressDialog) {
|
||||
progressDialog->close();
|
||||
progressDialog->deleteLater();
|
||||
}
|
||||
|
||||
if (updateDownloadReply->error() == QNetworkReply::NoError) {
|
||||
// 保存下载的文件
|
||||
QByteArray data = updateDownloadReply->readAll();
|
||||
QString fileName = QUrl(updateDownloadReply->url()).fileName();
|
||||
downloadedUpdatePath = QStandardPaths::writableLocation(QStandardPaths::TempLocation) + "/" + fileName;
|
||||
|
||||
QFile file(downloadedUpdatePath);
|
||||
if (file.open(QIODevice::WriteOnly)) {
|
||||
file.write(data);
|
||||
file.close();
|
||||
|
||||
QMessageBox msgBox(this);
|
||||
msgBox.setWindowTitle("下载完成");
|
||||
msgBox.setText("更新包下载完成,是否立即安装?");
|
||||
msgBox.setStandardButtons(QMessageBox::Yes | QMessageBox::No);
|
||||
|
||||
QAbstractButton *yesButton = msgBox.button(QMessageBox::Yes);
|
||||
QAbstractButton *noButton = msgBox.button(QMessageBox::No);
|
||||
if (yesButton) yesButton->setText("立即安装");
|
||||
if (noButton) noButton->setText("稍后安装");
|
||||
|
||||
if (msgBox.exec() == QMessageBox::Yes) {
|
||||
installUpdate();
|
||||
}
|
||||
} else {
|
||||
QMessageBox::critical(this, "下载失败", "无法保存更新文件!");
|
||||
}
|
||||
} else {
|
||||
QMessageBox::warning(this, "下载失败",
|
||||
QString("下载更新失败:%1").arg(updateDownloadReply->errorString()));
|
||||
}
|
||||
|
||||
updateDownloadReply->deleteLater();
|
||||
updateDownloadReply = nullptr;
|
||||
}
|
||||
|
||||
void MainWindow::installUpdate()
|
||||
{
|
||||
if (downloadedUpdatePath.isEmpty() || !QFile::exists(downloadedUpdatePath)) {
|
||||
QMessageBox::warning(this, "安装失败", "找不到更新文件!");
|
||||
return;
|
||||
}
|
||||
|
||||
// 根据文件类型执行不同的安装逻辑
|
||||
if (downloadedUpdatePath.endsWith(".deb")) {
|
||||
// Debian包安装
|
||||
QProcess::startDetached("pkexec", QStringList() << "dpkg" << "-i" << downloadedUpdatePath);
|
||||
} else if (downloadedUpdatePath.endsWith(".rpm")) {
|
||||
// RPM包安装
|
||||
QProcess::startDetached("pkexec", QStringList() << "rpm" << "-i" << downloadedUpdatePath);
|
||||
} else if (downloadedUpdatePath.endsWith(".AppImage")) {
|
||||
// AppImage替换
|
||||
QString currentPath = QCoreApplication::applicationFilePath();
|
||||
QString backupPath = currentPath + ".backup";
|
||||
|
||||
// 备份当前程序
|
||||
QFile::copy(currentPath, backupPath);
|
||||
|
||||
// 替换程序文件
|
||||
QFile::remove(currentPath);
|
||||
QFile::copy(downloadedUpdatePath, currentPath);
|
||||
QFile::setPermissions(currentPath, QFile::ReadOwner | QFile::WriteOwner | QFile::ExeOwner |
|
||||
QFile::ReadGroup | QFile::ExeGroup |
|
||||
QFile::ReadOther | QFile::ExeOther);
|
||||
|
||||
QMessageBox::information(this, "安装完成", "更新安装完成,请重启程序!");
|
||||
QApplication::quit();
|
||||
} else {
|
||||
// 普通可执行文件替换(如QtDemo)
|
||||
QString currentPath = QCoreApplication::applicationFilePath();
|
||||
QString currentDir = QFileInfo(currentPath).absolutePath();
|
||||
QString currentFileName = QFileInfo(currentPath).fileName();
|
||||
QString backupPath = currentPath + ".backup";
|
||||
QString tempPath = currentPath + ".new";
|
||||
|
||||
// 备份当前程序
|
||||
QFile::copy(currentPath, backupPath);
|
||||
|
||||
// 先将新文件复制到临时位置
|
||||
if (!QFile::copy(downloadedUpdatePath, tempPath)) {
|
||||
QMessageBox::warning(this, "安装失败", "无法复制更新文件!");
|
||||
return;
|
||||
}
|
||||
|
||||
// 设置临时文件权限
|
||||
QFile::setPermissions(tempPath, QFile::ReadOwner | QFile::WriteOwner | QFile::ExeOwner |
|
||||
QFile::ReadGroup | QFile::ExeGroup |
|
||||
QFile::ReadOther | QFile::ExeOther);
|
||||
|
||||
// 创建更新脚本
|
||||
QString scriptPath = currentDir + "/update_and_restart.sh";
|
||||
QFile scriptFile(scriptPath);
|
||||
if (scriptFile.open(QIODevice::WriteOnly | QIODevice::Text)) {
|
||||
QTextStream out(&scriptFile);
|
||||
out << "#!/bin/bash\n";
|
||||
out << "sleep 2\n"; // 等待当前进程完全退出
|
||||
out << "# 移除旧文件并重命名新文件\n";
|
||||
out << "rm -f \"" << currentPath << "\"\n";
|
||||
out << "mv \"" << tempPath << "\" \"" << currentPath << "\"\n";
|
||||
out << "chmod +x \"" << currentPath << "\"\n";
|
||||
out << "cd \"" << currentDir << "\"\n";
|
||||
out << "# 启动新程序\n";
|
||||
out << "nohup ./" << currentFileName << " > /dev/null 2>&1 &\n";
|
||||
out << "# 清理脚本文件\n";
|
||||
out << "sleep 1\n";
|
||||
out << "rm -f \"" << scriptPath << "\"\n";
|
||||
scriptFile.close();
|
||||
|
||||
// 设置脚本可执行权限
|
||||
QFile::setPermissions(scriptPath, QFile::ReadOwner | QFile::WriteOwner | QFile::ExeOwner |
|
||||
QFile::ReadGroup | QFile::ExeGroup |
|
||||
QFile::ReadOther | QFile::ExeOther);
|
||||
|
||||
// 启动更新脚本并退出当前程序
|
||||
QProcess::startDetached("/bin/bash", QStringList() << scriptPath);
|
||||
QMessageBox::information(this, "安装完成", "更新安装完成,程序将自动重启!");
|
||||
|
||||
// 延迟退出,确保脚本有时间启动
|
||||
QTimer::singleShot(500, []() {
|
||||
QApplication::quit();
|
||||
});
|
||||
} else {
|
||||
QMessageBox::warning(this, "安装失败", "无法创建更新脚本!");
|
||||
QFile::remove(tempPath); // 清理临时文件
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int MainWindow::compareVersions(const QString &version1, const QString &version2)
|
||||
{
|
||||
QStringList v1Parts = version1.split('.');
|
||||
QStringList v2Parts = version2.split('.');
|
||||
|
||||
int maxParts = qMax(v1Parts.size(), v2Parts.size());
|
||||
|
||||
for (int i = 0; i < maxParts; ++i) {
|
||||
int v1Part = (i < v1Parts.size()) ? v1Parts[i].toInt() : 0;
|
||||
int v2Part = (i < v2Parts.size()) ? v2Parts[i].toInt() : 0;
|
||||
|
||||
if (v1Part < v2Part) return -1;
|
||||
if (v1Part > v2Part) return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void MainWindow::onUpdateSettingsClicked()
|
||||
{
|
||||
UpdateSettingsDialog dialog(this);
|
||||
if (dialog.exec() == QDialog::Accepted) {
|
||||
// 更新本地设置
|
||||
updateServerUrl = dialog.getUpdateServerUrl();
|
||||
settings->setValue("updateServerUrl", updateServerUrl);
|
||||
settings->setValue("autoCheckUpdates", dialog.isAutoCheckEnabled());
|
||||
settings->setValue("checkInterval", dialog.getCheckInterval());
|
||||
|
||||
QMessageBox::information(this, "设置保存", "更新设置已保存!");
|
||||
}
|
||||
}
|
||||
|
||||
@ -62,6 +62,13 @@ private slots:
|
||||
void onClearSnListClicked();
|
||||
void onLightStripManagerClosed();
|
||||
void onDeviceSnChanged(); // 新增:设备SN变化槽函数
|
||||
|
||||
// 更新相关槽函数
|
||||
void checkForUpdates();
|
||||
void onUpdateCheckFinished();
|
||||
void onUpdateDownloadProgress(qint64 bytesReceived, qint64 bytesTotal);
|
||||
void onUpdateDownloadFinished();
|
||||
void onUpdateSettingsClicked();
|
||||
|
||||
private:
|
||||
void setupUI();
|
||||
@ -77,6 +84,12 @@ private:
|
||||
void sendSearchLightStripCommand();
|
||||
void openLightStripManager(); // 添加这个声明
|
||||
|
||||
// 更新相关函数
|
||||
void showUpdateDialog(const QString &version, const QString &downloadUrl, const QString &changelog);
|
||||
void downloadUpdate(const QString &downloadUrl);
|
||||
void installUpdate();
|
||||
int compareVersions(const QString &version1, const QString &version2);
|
||||
|
||||
// 新增:公共接口
|
||||
QString getDeviceSn() const;
|
||||
QString getTextColorForTheme() const;
|
||||
@ -142,6 +155,14 @@ private:
|
||||
// MQTT客户端
|
||||
MqttClient *mqttClient;
|
||||
|
||||
// 更新相关成员变量
|
||||
QString currentVersion;
|
||||
QString updateServerUrl;
|
||||
QNetworkAccessManager *updateNetworkManager;
|
||||
QNetworkReply *updateCheckReply;
|
||||
QNetworkReply *updateDownloadReply;
|
||||
QString downloadedUpdatePath;
|
||||
|
||||
// 数据管理
|
||||
QSet<QString> uniqueSnSet;
|
||||
QList<QCheckBox*> lightStripCheckBoxes; // 添加复选框列表
|
||||
|
||||
249
src/updatesettingsdialog.cpp
Normal file
249
src/updatesettingsdialog.cpp
Normal file
@ -0,0 +1,249 @@
|
||||
#include "updatesettingsdialog.h"
|
||||
#include <QMessageBox>
|
||||
#include <QNetworkAccessManager>
|
||||
#include <QNetworkRequest>
|
||||
#include <QNetworkReply>
|
||||
#include <QUrl>
|
||||
#include <QTimer>
|
||||
#include <QSpinBox>
|
||||
|
||||
UpdateSettingsDialog::UpdateSettingsDialog(QWidget *parent)
|
||||
: QDialog(parent),
|
||||
serverUrlEdit(nullptr),
|
||||
autoCheckBox(nullptr),
|
||||
checkIntervalEdit(nullptr),
|
||||
testBtn(nullptr),
|
||||
resetBtn(nullptr),
|
||||
okBtn(nullptr),
|
||||
cancelBtn(nullptr),
|
||||
settings(nullptr)
|
||||
{
|
||||
settings = new QSettings("TuxiApp", "LightStripSN", this);
|
||||
setupUI();
|
||||
loadSettings();
|
||||
}
|
||||
|
||||
UpdateSettingsDialog::~UpdateSettingsDialog()
|
||||
{
|
||||
}
|
||||
|
||||
void UpdateSettingsDialog::setupUI()
|
||||
{
|
||||
qDebug() << "开始设置UpdateSettingsDialog UI...";
|
||||
|
||||
setWindowTitle("更新设置");
|
||||
setFixedSize(400, 300);
|
||||
setModal(true);
|
||||
|
||||
QVBoxLayout *mainLayout = new QVBoxLayout(this);
|
||||
if (!mainLayout) {
|
||||
qDebug() << "错误: 无法创建主布局";
|
||||
return;
|
||||
}
|
||||
|
||||
// 服务器设置组
|
||||
QGroupBox *serverGroup = new QGroupBox("服务器设置", this);
|
||||
if (!serverGroup) {
|
||||
qDebug() << "错误: 无法创建服务器设置组";
|
||||
return;
|
||||
}
|
||||
|
||||
QFormLayout *serverLayout = new QFormLayout(serverGroup);
|
||||
if (!serverLayout) {
|
||||
qDebug() << "错误: 无法创建服务器布局";
|
||||
return;
|
||||
}
|
||||
|
||||
serverUrlEdit = new QLineEdit(this);
|
||||
if (!serverUrlEdit) {
|
||||
qDebug() << "错误: 无法创建服务器URL编辑框";
|
||||
return;
|
||||
}
|
||||
serverUrlEdit->setPlaceholderText("http://180.163.74.83:8001/version");
|
||||
serverLayout->addRow("更新服务器地址:", serverUrlEdit);
|
||||
|
||||
QHBoxLayout *testLayout = new QHBoxLayout();
|
||||
testBtn = new QPushButton("测试连接", this);
|
||||
resetBtn = new QPushButton("恢复默认", this);
|
||||
|
||||
if (!testBtn || !resetBtn) {
|
||||
qDebug() << "错误: 无法创建测试或重置按钮";
|
||||
return;
|
||||
}
|
||||
|
||||
testLayout->addWidget(testBtn);
|
||||
testLayout->addWidget(resetBtn);
|
||||
testLayout->addStretch();
|
||||
serverLayout->addRow("", testLayout);
|
||||
|
||||
mainLayout->addWidget(serverGroup);
|
||||
|
||||
// 自动检查设置组
|
||||
QGroupBox *autoGroup = new QGroupBox("自动检查设置", this);
|
||||
QFormLayout *autoLayout = new QFormLayout(autoGroup);
|
||||
|
||||
autoCheckBox = new QCheckBox("启用自动检查更新", this);
|
||||
autoLayout->addRow(autoCheckBox);
|
||||
|
||||
checkIntervalEdit = new QLineEdit(this);
|
||||
checkIntervalEdit->setPlaceholderText("24");
|
||||
QLabel *intervalLabel = new QLabel("检查间隔(小时):", this);
|
||||
autoLayout->addRow(intervalLabel, checkIntervalEdit);
|
||||
|
||||
// 当自动检查被禁用时,禁用间隔设置
|
||||
connect(autoCheckBox, &QCheckBox::toggled, [this, intervalLabel](bool checked) {
|
||||
checkIntervalEdit->setEnabled(checked);
|
||||
intervalLabel->setEnabled(checked);
|
||||
});
|
||||
|
||||
mainLayout->addWidget(autoGroup);
|
||||
|
||||
// 按钮布局
|
||||
QHBoxLayout *buttonLayout = new QHBoxLayout();
|
||||
buttonLayout->addStretch();
|
||||
|
||||
okBtn = new QPushButton("确定", this);
|
||||
cancelBtn = new QPushButton("取消", this);
|
||||
|
||||
buttonLayout->addWidget(okBtn);
|
||||
buttonLayout->addWidget(cancelBtn);
|
||||
|
||||
mainLayout->addLayout(buttonLayout);
|
||||
|
||||
// 连接信号槽
|
||||
connect(okBtn, &QPushButton::clicked, this, &UpdateSettingsDialog::onOkClicked);
|
||||
connect(cancelBtn, &QPushButton::clicked, this, &UpdateSettingsDialog::onCancelClicked);
|
||||
connect(testBtn, &QPushButton::clicked, this, &UpdateSettingsDialog::onTestConnectionClicked);
|
||||
connect(resetBtn, &QPushButton::clicked, this, &UpdateSettingsDialog::onResetToDefaultClicked);
|
||||
|
||||
qDebug() << "UpdateSettingsDialog UI设置完成";
|
||||
}
|
||||
|
||||
|
||||
void UpdateSettingsDialog::loadSettings()
|
||||
{
|
||||
QString defaultUrl = "http://180.163.74.83:8001/version";
|
||||
serverUrlEdit->setText(settings->value("updateServerUrl", defaultUrl).toString());
|
||||
autoCheckBox->setChecked(settings->value("autoCheckUpdates", true).toBool());
|
||||
checkIntervalEdit->setText(settings->value("checkInterval", 24).toString());
|
||||
|
||||
// 触发复选框状态变化以更新UI
|
||||
emit autoCheckBox->toggled(autoCheckBox->isChecked());
|
||||
}
|
||||
|
||||
void UpdateSettingsDialog::saveSettings()
|
||||
{
|
||||
settings->setValue("updateServerUrl", serverUrlEdit->text().trimmed());
|
||||
settings->setValue("autoCheckUpdates", autoCheckBox->isChecked());
|
||||
settings->setValue("checkInterval", checkIntervalEdit->text().toInt());
|
||||
settings->sync();
|
||||
}
|
||||
|
||||
QString UpdateSettingsDialog::getUpdateServerUrl() const
|
||||
{
|
||||
return serverUrlEdit->text().trimmed();
|
||||
}
|
||||
|
||||
bool UpdateSettingsDialog::isAutoCheckEnabled() const
|
||||
{
|
||||
return autoCheckBox->isChecked();
|
||||
}
|
||||
|
||||
int UpdateSettingsDialog::getCheckInterval() const
|
||||
{
|
||||
return checkIntervalEdit->text().toInt();
|
||||
}
|
||||
|
||||
void UpdateSettingsDialog::onOkClicked()
|
||||
{
|
||||
// 验证输入
|
||||
QString url = serverUrlEdit->text().trimmed();
|
||||
if (url.isEmpty()) {
|
||||
QMessageBox::warning(this, "输入错误", "请输入更新服务器地址!");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!url.startsWith("http://") && !url.startsWith("https://")) {
|
||||
QMessageBox::warning(this, "输入错误", "服务器地址必须以 http:// 或 https:// 开头!");
|
||||
return;
|
||||
}
|
||||
|
||||
int interval = checkIntervalEdit->text().toInt();
|
||||
if (autoCheckBox->isChecked() && (interval < 1 || interval > 168)) {
|
||||
QMessageBox::warning(this, "输入错误", "检查间隔必须在1-168小时之间!");
|
||||
return;
|
||||
}
|
||||
|
||||
saveSettings();
|
||||
accept();
|
||||
}
|
||||
|
||||
void UpdateSettingsDialog::onCancelClicked()
|
||||
{
|
||||
reject();
|
||||
}
|
||||
|
||||
void UpdateSettingsDialog::onTestConnectionClicked()
|
||||
{
|
||||
QString url = serverUrlEdit->text().trimmed();
|
||||
if (url.isEmpty()) {
|
||||
QMessageBox::warning(this, "测试失败", "请先输入服务器地址!");
|
||||
return;
|
||||
}
|
||||
|
||||
testConnection();
|
||||
}
|
||||
|
||||
void UpdateSettingsDialog::onResetToDefaultClicked()
|
||||
{
|
||||
int ret = QMessageBox::question(this, "确认重置",
|
||||
"确定要恢复默认设置吗?",
|
||||
QMessageBox::Yes | QMessageBox::No);
|
||||
if (ret == QMessageBox::Yes) {
|
||||
serverUrlEdit->setText("http://180.163.74.83:8001/version");
|
||||
autoCheckBox->setChecked(true);
|
||||
checkIntervalEdit->setText("24");
|
||||
}
|
||||
}
|
||||
|
||||
void UpdateSettingsDialog::testConnection()
|
||||
{
|
||||
testBtn->setEnabled(false);
|
||||
testBtn->setText("测试中...");
|
||||
|
||||
QNetworkAccessManager *manager = new QNetworkAccessManager(this);
|
||||
QNetworkRequest request;
|
||||
request.setUrl(QUrl(serverUrlEdit->text().trimmed()));
|
||||
request.setRawHeader("User-Agent", "LightStripSN-Updater/1.0");
|
||||
|
||||
// 设置超时
|
||||
QTimer *timer = new QTimer(this);
|
||||
timer->setSingleShot(true);
|
||||
|
||||
QNetworkReply *reply = manager->get(request);
|
||||
|
||||
connect(timer, &QTimer::timeout, [this, reply]() {
|
||||
reply->abort();
|
||||
testBtn->setEnabled(true);
|
||||
testBtn->setText("测试连接");
|
||||
QMessageBox::warning(this, "连接超时", "连接服务器超时,请检查网络或服务器地址!");
|
||||
});
|
||||
|
||||
connect(reply, &QNetworkReply::finished, [this, reply, timer]() {
|
||||
timer->stop();
|
||||
testBtn->setEnabled(true);
|
||||
testBtn->setText("测试连接");
|
||||
|
||||
if (reply->error() == QNetworkReply::NoError) {
|
||||
QMessageBox::information(this, "连接成功", "服务器连接正常!");
|
||||
} else {
|
||||
QMessageBox::warning(this, "连接失败",
|
||||
QString("连接失败: %1").arg(reply->errorString()));
|
||||
}
|
||||
|
||||
reply->deleteLater();
|
||||
timer->deleteLater();
|
||||
});
|
||||
|
||||
timer->start(10000); // 10秒超时
|
||||
}
|
||||
51
src/updatesettingsdialog.h
Normal file
51
src/updatesettingsdialog.h
Normal file
@ -0,0 +1,51 @@
|
||||
#ifndef UPDATESETTINGSDIALOG_H
|
||||
#define UPDATESETTINGSDIALOG_H
|
||||
|
||||
#include <QDialog>
|
||||
#include <QLineEdit>
|
||||
#include <QPushButton>
|
||||
#include <QVBoxLayout>
|
||||
#include <QHBoxLayout>
|
||||
#include <QFormLayout>
|
||||
#include <QLabel>
|
||||
#include <QGroupBox>
|
||||
#include <QCheckBox>
|
||||
#include <QSettings>
|
||||
#include <QSpinBox>
|
||||
|
||||
class UpdateSettingsDialog : public QDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit UpdateSettingsDialog(QWidget *parent = nullptr);
|
||||
~UpdateSettingsDialog();
|
||||
|
||||
QString getUpdateServerUrl() const;
|
||||
bool isAutoCheckEnabled() const;
|
||||
int getCheckInterval() const;
|
||||
|
||||
private slots:
|
||||
void onOkClicked();
|
||||
void onCancelClicked();
|
||||
void onTestConnectionClicked();
|
||||
void onResetToDefaultClicked();
|
||||
|
||||
private:
|
||||
void setupUI();
|
||||
void loadSettings();
|
||||
void saveSettings();
|
||||
void testConnection();
|
||||
|
||||
QLineEdit *serverUrlEdit;
|
||||
QCheckBox *autoCheckBox;
|
||||
QLineEdit *checkIntervalEdit;
|
||||
QPushButton *testBtn;
|
||||
QPushButton *resetBtn;
|
||||
QPushButton *okBtn;
|
||||
QPushButton *cancelBtn;
|
||||
|
||||
QSettings *settings;
|
||||
};
|
||||
|
||||
#endif // UPDATESETTINGSDIALOG_H
|
||||
Loading…
Reference in New Issue
Block a user