新增qt程序ota
This commit is contained in:
parent
5bf62c410a
commit
faae203eb1
@ -20,12 +20,14 @@ set(SOURCES
|
|||||||
src/mainwindow.cpp
|
src/mainwindow.cpp
|
||||||
src/mqttclient.cpp
|
src/mqttclient.cpp
|
||||||
src/lightstripmanager.cpp
|
src/lightstripmanager.cpp
|
||||||
|
src/updatesettingsdialog.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
set(HEADERS
|
set(HEADERS
|
||||||
src/mainwindow.h
|
src/mainwindow.h
|
||||||
src/mqttclient.h
|
src/mqttclient.h
|
||||||
src/lightstripmanager.h
|
src/lightstripmanager.h
|
||||||
|
src/updatesettingsdialog.h
|
||||||
)
|
)
|
||||||
|
|
||||||
add_executable(QtDemo ${SOURCES} ${HEADERS}
|
add_executable(QtDemo ${SOURCES} ${HEADERS}
|
||||||
|
|||||||
@ -1,12 +1,13 @@
|
|||||||
#include "mainwindow.h"
|
#include "mainwindow.h"
|
||||||
#include "lightstripmanager.h"
|
#include "lightstripmanager.h"
|
||||||
|
#include "updatesettingsdialog.h"
|
||||||
#include <QDateTime>
|
#include <QDateTime>
|
||||||
#include <QJsonObject>
|
#include <QJsonObject>
|
||||||
#include <QJsonDocument>
|
#include <QJsonDocument>
|
||||||
//#include <QNetworkAccessManager>
|
#include <QNetworkAccessManager>
|
||||||
//#include <QNetworkRequest>
|
#include <QNetworkRequest>
|
||||||
//#include <QNetworkReply>
|
#include <QNetworkReply>
|
||||||
//#include <QFileInfo>
|
#include <QFileInfo>
|
||||||
#include <QDir>
|
#include <QDir>
|
||||||
#include <QStandardPaths>
|
#include <QStandardPaths>
|
||||||
#include <QMessageBox>
|
#include <QMessageBox>
|
||||||
@ -15,12 +16,24 @@
|
|||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
#include <QScreen>
|
#include <QScreen>
|
||||||
#include <QGuiApplication>
|
#include <QGuiApplication>
|
||||||
|
#include <QProgressDialog>
|
||||||
|
#include <QFile>
|
||||||
|
#include <QProcess>
|
||||||
|
#include <QInputDialog>
|
||||||
|
|
||||||
MainWindow::MainWindow(QWidget *parent)
|
MainWindow::MainWindow(QWidget *parent)
|
||||||
: QMainWindow(parent), otaOperationPending(false), isUpgradeOperation(true)
|
: QMainWindow(parent), otaOperationPending(false), isUpgradeOperation(true)
|
||||||
{
|
{
|
||||||
// 初始化设置对象
|
// 初始化设置对象
|
||||||
settings = new QSettings("TuxiApp", "LightStripSN", this);
|
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();
|
setupUI();
|
||||||
|
|
||||||
@ -98,7 +111,7 @@ void MainWindow::showVersionUpdateInfo()
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
void MainWindow::setupUI() {
|
void MainWindow::setupUI() {
|
||||||
setWindowTitle("兔喜Test1.2 Author:Zhangzhenghao Email:zzh9953477@gmail.com");
|
setWindowTitle("兔喜Test1.5 Author:Zhangzhenghao Email:zzh9953477@gmail.com");
|
||||||
|
|
||||||
// 参考qt_bak的合理尺寸设置,增加竖向高度
|
// 参考qt_bak的合理尺寸设置,增加竖向高度
|
||||||
setMinimumSize(850, 720); // 增加最小高度
|
setMinimumSize(850, 720); // 增加最小高度
|
||||||
@ -333,6 +346,27 @@ void MainWindow::setupUI() {
|
|||||||
"}"
|
"}"
|
||||||
);
|
);
|
||||||
snHeaderLayout->addWidget(searchLightStripBtn);
|
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);
|
snLayout->addLayout(snHeaderLayout);
|
||||||
|
|
||||||
// 打开管理器按钮
|
// 打开管理器按钮
|
||||||
@ -1415,6 +1449,17 @@ void MainWindow::createMenus()
|
|||||||
|
|
||||||
QAction *useGuideAction = helpMenu->addAction("使用说明(&U)");
|
QAction *useGuideAction = helpMenu->addAction("使用说明(&U)");
|
||||||
connect(useGuideAction, &QAction::triggered, this, &MainWindow::showUseGuide);
|
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()
|
void MainWindow::showAbout()
|
||||||
@ -1457,3 +1502,272 @@ QString MainWindow::getTextColorForTheme() const {
|
|||||||
// 如果背景较暗(亮度小于0.5),使用白色文字;否则使用黑色文字
|
// 如果背景较暗(亮度小于0.5),使用白色文字;否则使用黑色文字
|
||||||
return (luminance < 0.5) ? "white" : "black";
|
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 onClearSnListClicked();
|
||||||
void onLightStripManagerClosed();
|
void onLightStripManagerClosed();
|
||||||
void onDeviceSnChanged(); // 新增:设备SN变化槽函数
|
void onDeviceSnChanged(); // 新增:设备SN变化槽函数
|
||||||
|
|
||||||
|
// 更新相关槽函数
|
||||||
|
void checkForUpdates();
|
||||||
|
void onUpdateCheckFinished();
|
||||||
|
void onUpdateDownloadProgress(qint64 bytesReceived, qint64 bytesTotal);
|
||||||
|
void onUpdateDownloadFinished();
|
||||||
|
void onUpdateSettingsClicked();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void setupUI();
|
void setupUI();
|
||||||
@ -77,6 +84,12 @@ private:
|
|||||||
void sendSearchLightStripCommand();
|
void sendSearchLightStripCommand();
|
||||||
void openLightStripManager(); // 添加这个声明
|
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 getDeviceSn() const;
|
||||||
QString getTextColorForTheme() const;
|
QString getTextColorForTheme() const;
|
||||||
@ -142,6 +155,14 @@ private:
|
|||||||
// MQTT客户端
|
// MQTT客户端
|
||||||
MqttClient *mqttClient;
|
MqttClient *mqttClient;
|
||||||
|
|
||||||
|
// 更新相关成员变量
|
||||||
|
QString currentVersion;
|
||||||
|
QString updateServerUrl;
|
||||||
|
QNetworkAccessManager *updateNetworkManager;
|
||||||
|
QNetworkReply *updateCheckReply;
|
||||||
|
QNetworkReply *updateDownloadReply;
|
||||||
|
QString downloadedUpdatePath;
|
||||||
|
|
||||||
// 数据管理
|
// 数据管理
|
||||||
QSet<QString> uniqueSnSet;
|
QSet<QString> uniqueSnSet;
|
||||||
QList<QCheckBox*> lightStripCheckBoxes; // 添加复选框列表
|
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