Seclient.cpp
#include "seclient.h"
#include "ui_seclient.h"
#include <QFileDialog>
#include <QMessageBox>
#include <QDir>
#include <QProcess>
#include <QDebug>
#include <QSettings>
#include "secupgrademodule.h"
Seclient::Seclient(QWidget *parent) :
QWidget(parent),
ui(new Ui::Seclient)
{
ui->setupUi(this);
this->setWindowTitle("独立客户端");
this->resize(800,500);
QFont f("黑体", 10, QFont::Black, false);
this->setWindowIcon(QIcon("C:/Users/liwencheng/Documents/data/up1.png"));
// 实例化SecUpgradeModule
this->secUpgradeModule = new SecUpgradeModule(this);
this->secUpgradeModule->hide();
// 去掉窗口边框
// this->setWindowFlags(Qt::FramelessWindowHint);
// 设置窗口为始终在顶层
// this->setWindowFlags(this->windowFlags() | Qt::WindowStaysOnTopHint);
// this->setStyleSheet("background-color: black;");
ui->checkUpdateButton->setFont(f);
// connect(ui->checkUpdateButton,&QPushButton::clicked,this,&MainWindow::on_checkUpdateButton_clicked);
// 返回信号
connect(secUpgradeModule,&SecUpgradeModule::return_signal,[this](){
ui->checkUpdateButton->show();
});
// connect(&updateConl, &UpdateConl::updateCompleted, this, &MainWindow::handleUpgradeRecordOnRestart);
}
Seclient::~Seclient()
{
delete ui;
}
void Seclient::on_checkUpdateButton_clicked()
{
qDebug() << u8"当前工作路径:" << QDir::currentPath();
// m_secClient = new MainWindow();
// 先确保 Update 和 tmp_Update 文件夹存在
QDir updateDir(DATA_PATH + "/Update");
if (!updateDir.exists())
{
updateDir.mkpath(".");
}
QDir tmpUpdateDir(DATA_PATH + "/tmp_Update");
if (!tmpUpdateDir.exists())
{
tmpUpdateDir.mkpath(".");
}
// // 调用独立升级系统的检查更新,结合配置文件判断
// bool hasUpdate = m_updateControl->checkForUpdates();
// if (hasUpdate)
// {
// m_updateControl->checkAndUpdate();
// qDebug()<<u8"已升级";
// // 检查是否是重启并处理升级记录
// m_secClient->handleUpgradeRecordOnRestart();
// }
// else
// {
// qDebug()<<u8"未升级";
// }
// m_secClient->show();
ui->checkUpdateButton->hide();
this->secUpgradeModule->show();
// //单例模式
// SecUpgradeModule* secUpgradeModule = SecUpgradeModule::getInstance();
// secUpgradeModule->show();
}
#ifndef SECLIENT_H
#define SECLIENT_H
#include <QWidget>
#include "secupgrademodule.h"
namespace Ui {
class Seclient;
}
class Seclient : public QWidget
{
Q_OBJECT
public:
explicit Seclient(QWidget *parent = 0);
~Seclient();
private slots:
void on_checkUpdateButton_clicked();
private:
Ui::Seclient *ui;
const QString DATA_PATH = "C:/Users/liwencheng/Documents/data";
SecUpgradeModule *secUpgradeModule;
};
#endif // SECLIENT_H
SecUpgradeModule.cpp
#include "secupgrademodule.h"
#include "ui_secupgrademodule.h"
#include <QNetworkRequest>
#include <QMessageBox>
//SecUpgradeModule* SecUpgradeModule::instance = nullptr;
//SecUpgradeModule* SecUpgradeModule::getInstance()
//{
if (instance == nullptr)
{
instance = new SecUpgradeModule();
}
return instance;
// 私有静态属性
static SecUpgradeModule* instance;
// //定义局部静态变量
// static SecUpgradeModule* instance = new SecUpgradeModule();
// return instance;
//}
SecUpgradeModule::SecUpgradeModule(QWidget *parent) :
QWidget(parent),
ui(new Ui::SecUpgradeModule)
{
ui->setupUi(this);
m_networkManager = new QNetworkAccessManager(this);
connect(m_networkManager, &QNetworkAccessManager::finished, this, &SecUpgradeModule::onNetworkReplyFinished);
// 初始化数据库连接
initDatabaseConnection();
// 初始化文件列表
initializePackageList();
// 初始化升级控制模块
m_upcontrol = new UpdateConl();
// UpdateStatus字段错误
connect(m_upcontrol, &UpdateConl::UpdateStatusFalse, this, &SecUpgradeModule::handleUpdateStatusFalse);
// 升级完成信号槽函数
connect(m_upcontrol, &UpdateConl::updateComplete, this, &SecUpgradeModule::handleUpdateComplete);
}
SecUpgradeModule::~SecUpgradeModule()
{
delete ui;
if(!m_upcontrol)
{
delete m_upcontrol;
m_upcontrol = nullptr;
}
}
void SecUpgradeModule::connectToOTA()
{
// 建立与OTA服务器的网络连接等逻辑,比如发送初始请求验证等
}
// 初始化文件列表
void SecUpgradeModule::initializePackageList()
{
// 检查 model 是否已经存在
if(!model)
{
model = new QStandardItemModel(0, 3, this);
model->setHeaderData(0, Qt::Horizontal, tr("文件名称"));
model->setHeaderData(1, Qt::Horizontal, tr(" 文件大小 "));
model->setHeaderData(2, Qt::Horizontal, tr("修改时间"));
ui->packageList->setModel(model);
}
// 加粗标题字体
QTableView *tableView = qobject_cast<QTableView*>(ui->packageList);
QFont headerFont = tableView->horizontalHeader()->font();
headerFont.setBold(true);
tableView->horizontalHeader()->setFont(headerFont);
// 初始化本地升级包列表
QDir tmpDir(DATA_PATH + "/tmp_Update/");
if (tmpDir.exists())
{
upgradePackages = tmpDir.entryList(QDir::Files);
model->removeRows(0, model->rowCount()); // 清除现有数据
for (const QString &package : upgradePackages)
{
QFileInfo fileInfo(DATA_PATH + "/tmp_Update/" + package);
QStandardItem *nameItem = new QStandardItem(package);
QStandardItem *sizeItem = new QStandardItem(QString::number(fileInfo.size() / 1024.0 / 1024.0, 'f', 2) + " M"); // 文件大小以KB为单位
QStandardItem *timeItem = new QStandardItem(fileInfo.lastModified().toString("yyyy-MM-dd HH:mm:ss"));
model->appendRow({nameItem, sizeItem, timeItem});
}
}
// 自适应列宽
ui->packageList->resizeColumnsToContents();
// 隐藏网格
ui->packageList->setShowGrid(false);
}
void SecUpgradeModule::downloadUpdatePackage(const QString &packageUrl)
{
QDir tmpUpdateDir("tmp_Update");
if (!tmpUpdateDir.exists()) {
tmpUpdateDir.mkpath("."); // 创建 tmp_Update 文件夹(如果不存在)
}
QString packageFileName = packageUrl.mid(packageUrl.lastIndexOf('/') + 1);
QString savePath = tmpUpdateDir.absoluteFilePath(packageFileName);
// 使用QNetworkAccessManager发起下载请求等操作
QNetworkRequest request(QUrl(packageUrl));
// m_networkManager->get(request);
}
void SecUpgradeModule::deleteUpdatePackage(const QString &packagePath)
{
// 实现删除本地文件的逻辑(使用文件操作相关函数)
QFile::remove(packagePath);
}
void SecUpgradeModule::selectUpgradeOption(int option)
{
// 根据传入的选项执行对应的升级相关逻辑
}
QList<QMap<QString, QString> > SecUpgradeModule::getLocalUpdatePackages()
{
QList<QMap<QString, QString>> packageList;
// 从 tmp_Update 文件夹获取升级包文件名列表
QDir tmpUpdateDir(DATA_PATH + "/tmp_Update");
QStringList fileNames = tmpUpdateDir.entryList(QDir::Files);
for (const QString &fileName : fileNames) {
QMap<QString, QString> packageInfo;
packageInfo["package_name"] = fileName;
// 从数据库查询对应升级包的详细信息,比如下载时间、更新说明等
QSqlQuery query;
query.prepare("SELECT download_time, update_description, is_updated FROM updates WHERE package_name = :package_name");
query.bindValue(":package_name", fileName);
if (query.exec() && query.next()) {
packageInfo["download_time"] = query.value(0).toString();
packageInfo["update_description"] = query.value(1).toString();
packageInfo["is_updated"] = query.value(2).toString();
}
packageList.append(packageInfo);
}
return packageList;
}
void SecUpgradeModule::onNetworkReplyFinished()
{
QNetworkReply *reply = qobject_cast<QNetworkReply *>(sender());
if (reply) {
if (reply->error() == QNetworkReply::NoError) {
// 处理下载成功等情况,比如保存文件到 tmp_Update 文件夹等
} else {
// 处理下载出错情况
}
reply->deleteLater();
}
}
void SecUpgradeModule::initDatabaseConnection()
{
QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE");
db.setDatabaseName("updates.db"); // 数据库文件名
if (!db.open())
{
qDebug() << "Error opening database";
}
}
// 文件更新状态
void SecUpgradeModule::showNotification(const bool success, const QString &upFileName)
{
if (success)
{
QMessageBox::information(this, "提醒", QString("升级成功:%1").arg(upFileName));
}
else
{
QMessageBox::information(this, "提醒", QString("升级失败:%1").arg(upFileName));
}
}
//选择上传文件到 tmp_Update
void SecUpgradeModule::on_uploadButton_clicked()
{
if(!this->m_filelist)
{
QMessageBox::warning(this, tr("错误"), tr("该选项仅在Tmp_Update列表下使用!"));
return;
}
// 构建文件过滤器,包含zip、tar.gz和.so文件
QString filter = tr("All Supported Files (*.zip *.tar.gz *.so);;ZIP Files (*.zip);;TAR.GZ Files (*.tar.gz);;SO Files (*.so)");
// QString filePath = QFileDialog::getOpenFileName(this, tr("上传升级包"), "C:/Users/liwencheng/Documents", filter);
// 支持多文件上传
QStringList filePaths = QFileDialog::getOpenFileNames(this, tr("上传升级包"), "D:/", filter, nullptr, QFileDialog::Options(QFileDialog::ExistingFiles));
if (!filePaths.isEmpty())
{
for (const QString& filePath : filePaths)
{
QFileInfo fileInfo(filePath);
QString newPath =DATA_PATH + "/tmp_Update/" + fileInfo.fileName();
if (!QFile::copy(filePath, newPath))
{
qWarning() << u8"复制失败!" << newPath;
QMessageBox::warning(this, tr("错误"), tr("文件复制失败,目标路径:") + newPath);
}
else
{
// 更新列表
QFileInfo fileInfo(filePath);
QStandardItem *nameItem = new QStandardItem(fileInfo.fileName());
QStandardItem *sizeItem = new QStandardItem(QString::number(fileInfo.size()));
QStandardItem *timeItem = new QStandardItem(fileInfo.lastModified().toString());
model->appendRow({nameItem, sizeItem, timeItem});
ui->packageList->resizeColumnsToContents();
ui->packageList->setShowGrid(false);
QMessageBox::information(this, tr("成功"), tr("文件上传成功,文件路径:") + newPath);
}
}
}
}
//删除 tmp_Update 的文件,更新列表
void SecUpgradeModule::on_deleteButton_clicked()
{
QModelIndex index = ui->packageList->currentIndex();
QString flie_list;
if (index.isValid())
{
// 获取当前行的第一列的索引
QModelIndex firstColumnIndex = model->index(index.row(), 0);
// 获取第一列的值(文件名)
QString packageName = model->itemData(firstColumnIndex).value(Qt::DisplayRole).toString();
// QString packageName = model->itemData(index).value(Qt::DisplayRole).toString();
if(this->m_filelist)
{
flie_list = "/tmp_Update/";
}
else
{
flie_list = "/Update/";
}
if(QFile::remove(DATA_PATH + flie_list + packageName))
{
// 更新列表
model->removeRow(index.row());
// 重置当前索引为无效
ui->packageList->setCurrentIndex(QModelIndex());
QMessageBox::information(this, tr("成功"), tr("成功删除文件:") + packageName);
}
else
{
QMessageBox::warning(this, tr("错误"), tr("文件删除失败:") + packageName, tr("请检查!"));
}
}
else
{
QMessageBox::warning(this, tr("错误"), tr("请选择要删除的文件!"));
}
}
//选择 tmp_Update 的文件, 表示要进行升级的包
void SecUpgradeModule::on_selectButton_clicked()
{
if(!this->m_filelist){
QMessageBox::warning(this, tr("错误"), tr("该选项仅在tmp_update列表下使用!"));
return;
}
QModelIndex index = ui->packageList->currentIndex();
if (index.isValid())
{
// 获取当前行的第一列的索引
QModelIndex firstColumnIndex = model->index(index.row(), 0);
// 获取第一列的值(文件名)
QString packageName = model->itemData(firstColumnIndex).value(Qt::DisplayRole).toString();
// QString packageName = model->itemData(index).value(Qt::DisplayRole).toString();
QFileInfo fileInfo(DATA_PATH + "/tmp_Update/" + packageName);
if (fileInfo.exists())
{
QString newPath =DATA_PATH + "/Update/" + fileInfo.fileName();
if(QFile::copy(fileInfo.absoluteFilePath(), newPath))
{
// 更新配置文件
UpdateConl::updateUpdateStatus(fileInfo.fileName(), "UpdateWaiting", "success", "updating");
QMessageBox::information(this, tr("成功"), tr("将要升级文件:") + fileInfo.fileName());
}
else
{
QMessageBox::warning(this, tr("错误"), tr("文件更新失败,请检查Update目录下是否有同名文件"));
UpdateConl::updateUpdateStatus(fileInfo.fileName(), "UpdateWaiting", "failed", "chose file failed");
}
}
}
else
{
QMessageBox::warning(this, tr("错误"), tr("请选择要升级的文件!"));
}
}
// 返回按钮
void SecUpgradeModule::on_returnButton_clicked()
{
// this->hide();
this->close();
emit return_signal();
}
// 立即升级
void SecUpgradeModule::on_nowupButton_clicked()
{
if(this->m_filelist)
{
QMessageBox::warning(this, tr("错误"), tr("该选项仅在Update列表下使用!"));
return;
}
if(model->rowCount() == 0){
QMessageBox::warning(this, tr("错误"), tr("Update列表下内容为空!"));
return;
}
m_upcontrol->isImmediateUpdateRequired();
if(!this->m_status)
{
return;
}
else
{
// 是否升级确认框
const QString title = QString::fromUtf8("更新提示");
const QString text = QString::fromUtf8("是否立即升级?");
int result = QMessageBox::information(this,title, text, QMessageBox::Yes | QMessageBox::No);
if (result == QMessageBox::Yes)
{
UpdateConfig configInfo = this->m_upcontrol->getConfigInfo();
QMessageBox::information(this, tr("提醒"), tr("即将开始升级:") + configInfo.fileName);
this->upFileName = configInfo.fileName;
this->m_upcontrol->checkAndUpdate();
qDebug()<<u8"已升级";
// 发送升级记录给日志审计模块
m_upcontrol->handleUpgradeRecordOnRestart();
}
}
}
// tmp_update 文件列表
void SecUpgradeModule::on_uploadButton_2_clicked()
{
this->m_filelist = true;
initializePackageList();
}
// update 文件列表
void SecUpgradeModule::on_uploadButton_3_clicked()
{
this->m_filelist = false;
// 检查 model 是否已经存在
if(!model)
{
model = new QStandardItemModel(0, 3, this);
model->setHeaderData(0, Qt::Horizontal, tr("文件名称"));
model->setHeaderData(1, Qt::Horizontal, tr(" 文件大小 "));
model->setHeaderData(2, Qt::Horizontal, tr("修改时间"));
ui->packageList->setModel(model);
// 加粗标题字体
QTableView *tableView = qobject_cast<QTableView*>(ui->packageList);
QFont headerFont = tableView->horizontalHeader()->font();
headerFont.setBold(true);
tableView->horizontalHeader()->setFont(headerFont);
}
// 初始化本地升级包列表
QDir tmpDir(DATA_PATH + "/Update/");
if (tmpDir.exists())
{
upgradePackages = tmpDir.entryList(QDir::Files);
model->removeRows(0, model->rowCount()); // 清除现有数据
for (const QString &package : upgradePackages)
{
QFileInfo fileInfo(DATA_PATH + "/tmp_Update/" + package);
QStandardItem *nameItem = new QStandardItem(package);
QStandardItem *sizeItem = new QStandardItem(QString::number(fileInfo.size() / 1024.0 / 1024.0, 'f', 2) + " M"); // 文件大小以KB为单位
QStandardItem *timeItem = new QStandardItem(fileInfo.lastModified().toString("yyyy-MM-dd HH:mm:ss"));
model->appendRow({nameItem, sizeItem, timeItem});
}
}
// 自适应列宽
ui->packageList->resizeColumnsToContents();
// 隐藏网格
ui->packageList->setShowGrid(false);
}
// 处理 UpdateStatus 字段错误
void SecUpgradeModule::handleUpdateStatusFalse(const QString &status)
{
this->m_status = false;
QMessageBox::information(this, "提示", QString("UpdateStatus 字段的值应为 UpdateWaiting 或 UpdateCompleted,当前值为: %1").arg(status));
}
// 升级完成信号槽函数
void SecUpgradeModule::handleUpdateComplete(int exitCode, QProcess::ExitStatus exitStatus)
{
if (exitStatus == QProcess::NormalExit)
{
if (exitCode == 0)
{
qDebug() << u8"批处理脚本执行成功";
qDebug() << "Parent window position: " << this->pos();
this->m_upcontrol->updateUpdateStatus(upFileName,"UpdateCompleted", "success", QString("exitCode:%1").arg(exitCode));
QMessageBox::information(nullptr, tr("提醒"), QString("升级成功:%1").arg(upFileName));
}
else
{
qDebug() << u8"批处理脚本执行失败,退出码: " << exitCode;
this->m_upcontrol->updateUpdateStatus(upFileName,"UpdateWaiting", "faile", QString("exitCode:%1").arg(exitCode));
QMessageBox::information(nullptr, tr("提醒"), QString("升级失败:%1").arg(upFileName));
}
}
else if (exitStatus == QProcess::CrashExit)
{
qDebug() << u8"批处理脚本执行过程中崩溃";
this->m_upcontrol->updateUpdateStatus(upFileName,"UpdateWaiting", "faile", "update is CrashExit");
}
}
#ifndef SECUPGRADEMODULE_H
#define SECUPGRADEMODULE_H
#include <QWidget>
#include <QObject>
#include <QNetworkAccessManager>
#include <QNetworkReply>
#include <QSqlDatabase>
#include <QSqlQuery>
#include <QDir>
#include <QFileDialog>
#include <QStandardItemModel>
#include "updateconl.h"
namespace Ui {
class SecUpgradeModule;
}
class SecUpgradeModule : public QWidget
{
Q_OBJECT
public:
explicit SecUpgradeModule(QWidget *parent = 0);
~SecUpgradeModule();
// // 共有静态方法
// static SecUpgradeModule* getInstance();
private:
Ui::SecUpgradeModule *ui;
// // 私有构造方法
// SecUpgradeModule(QWidget *parent = 0);
// 连接OTA服务器,初始化通信相关设置
void connectToOTA();
// 初始化文件列表
void initializePackageList();
// 下载指定的升级包,并保存到 tmp_Update 文件夹
void downloadUpdatePackage(const QString &packageUrl);
// 删除本地已下载的升级包(从 tmp_Update 文件夹删除)
void deleteUpdatePackage(const QString &packagePath);
// 选择要进行的升级操作(比如立即升级、稍后升级等)
void selectUpgradeOption(int option);
// 获取本地升级包列表信息(包含从数据库读取详细信息用于展示)
QList<QMap<QString, QString>> getLocalUpdatePackages();
QStandardItemModel *model = nullptr;
QStringList upgradePackages;
QNetworkAccessManager *m_networkManager;
// 初始化数据库连接
void initDatabaseConnection();
const QString DATA_PATH = "C:/Users/liwencheng/Documents/data";
//文件列表
bool m_filelist = true;
// status 状态
bool m_status = true;
// 升级文件名字
QString upFileName;
UpdateConl *m_upcontrol;
signals:
// 信号用于通知下载进度、通信状态等
void downloadProgress(int progress);
void connectionStatusChanged(const QString &status);
void return_signal();
private slots:
// 文件更新状态
void showNotification(const bool success, const QString& upFileName);
void onNetworkReplyFinished();
void on_uploadButton_clicked();
void on_deleteButton_clicked();
void on_selectButton_clicked();
void on_returnButton_clicked();
void on_nowupButton_clicked();
void on_uploadButton_2_clicked();
void on_uploadButton_3_clicked();
void handleUpdateStatusFalse(const QString &status);
void handleUpdateComplete(int exitCode, QProcess::ExitStatus exitStatus);
};
#endif // SECUPGRADEMODULE_H
#include "updateconl.h"
#include "ui_updateconl.h"
const QString UpdateConl::DATA_PATH = "C:/Users/liwencheng/Documents/data";
UpdateConl::UpdateConl(QWidget *parent) :
QWidget(parent),
ui(new Ui::UpdateConl)
{
ui->setupUi(this);
// m_checkTimer = new QTimer(this);
// m_reminderTimer = new QTimer(this);
// updateProcess = new QProcess(this);
updateProcess = new QProcess(static_cast<QObject*>(this));
// connect(updateProcess, QOverload<int, QProcess::ExitStatus>::of(&QProcess::finished),
// this, &UpdateConl::onProcessFinished);
// connect(m_checkTimer, &QTimer::timeout, this, &UpdateConl::checkUpdateIni);
connect(m_reminderTimer, &QTimer::timeout, this, &UpdateConl::showUpdateConfirmation);
connect(m_reminderTimer, &QTimer::timeout, this, &UpdateConl::on_reminderTimer_timeout);
m_checkTimer->start(10000); // 每20秒检查一次
// // 有升级可用包发现
// m_updateConfirmationShown = false;
}
UpdateConl::~UpdateConl()
{
delete ui;
}
// 更新 Update.ini 中的更新状态
void UpdateConl::updateUpdateStatus(const QString &file,const QString &status, const QString &result, const QString &msg)
{
QSettings settings(DATA_PATH + "/Update.ini", QSettings::IniFormat);
settings.setValue("FileName", file);
settings.setValue("UpdateStatus", status);
settings.setValue("UpdateResults", result);
settings.setValue("Msg", msg);
qDebug()<<u8"当前时间:"<<QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss");
settings.setValue("UpdateTime", QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss"));
}
//检查 UpdateStatus 字段是否是 UpdateWaiting
bool UpdateConl::isImmediateUpdateRequired()
{
QSettings settings(DATA_PATH + "/Update.ini", QSettings::IniFormat);
QString status = settings.value("UpdateStatus", "").toString();
if (!status.isEmpty() && status!= "UpdateWaiting" && status!= "UpdateCompleted")
{
// QMessageBox::information(this, "提示", QString("UpdateStatus 字段的值应为 UpdateWaiting 或 UpdateCompleted,当前值为: %1").arg(status));
emit UpdateStatusFalse(status);
}
return status == "UpdateWaiting";
}
// 执行更新操作,比如下载并安装依赖库、成果物更新等
void UpdateConl::checkAndUpdate()
{
if (isImmediateUpdateRequired())
{
UpdateConfig configInfo = getConfigInfo();
// 判断 Update 目录下是否包含 configInfo.fileName
QDir updateDir(DATA_PATH + "/Update/");
if (updateDir.exists() && updateDir.exists(configInfo.fileName))
{
// 解压升级包 校验升级包的完整性 TODO
// 执行更新脚本操作,依赖库、成果物更新
QDir scriptDir(DATA_PATH);
if (scriptDir.exists("update.bat"))
{
qDebug() << u8"即将开始升级";
upFileName = configInfo.fileName;
updateProcess->start("cmd.exe", QStringList() << "/c" << DATA_PATH + "/update.bat");
// if (!updateProcess->waitForFinished())
// {
// qDebug() << u8"Update script execution timeout.";
// }
// else
// {
// qWarning() << u8"========================waitForFinished 失败" ;
// }
// 启动外部更新脚本
qDebug() << u8"启动外部更新脚本";
// QProcess::startDetached("cmd.exe", QStringList() << "/c" << DATA_PATH + "/update.bat");
// QCoreApplication::quit();
// emit updateCompleted();
}
}
else
{
qWarning() << u8"Update 目录下不存在 " << configInfo.fileName;
}
}
}
// 获取配置文件信息
UpdateConfig UpdateConl::getConfigInfo()
{
UpdateConfig config;
QFile configFile(DATA_PATH + "/Update.ini");
if (configFile.open(QIODevice::ReadOnly | QIODevice::Text))
{
QTextStream in(&configFile);
QString line;
while (!in.atEnd())
{
line = in.readLine();
if (line.startsWith("FileName="))
{
config.fileName = line.mid(9);
}
else if (line.startsWith("UpdateStatus="))
{
config.updateStatus = line.mid(13);
}
}
configFile.close();
}
qDebug()<<u8"=====================================";
qDebug()<<u8"文件名:"<<config.fileName<<u8"更新状态:"<<config.updateStatus;
return config;
}
// 获取 Update.ini 的升级记录信息
void UpdateConl::handleUpgradeRecordOnRestart()
{
QSettings settings(DATA_PATH + "/Update.ini", QSettings::IniFormat);
QString status = settings.value("UpdateStatus", "").toString();
QString result = settings.value("UpdateResults", "").toString();
QString fileName = settings.value("FileName", "").toString();
QString updateTime = settings.value("UpdateTime", "").toString();
QString msg = settings.value("Msg", "").toString();
QMap<QString, QString> upgradeRecord;
upgradeRecord["FileName"] = fileName;
upgradeRecord["UpdateStatus"] = status;
upgradeRecord["UpdateResults"] = result;
upgradeRecord["UpdateTime"] = updateTime;
upgradeRecord["Msg"] = msg;
sendUpgradeRecordToAudit(upgradeRecord);
}
// 发送升级记录给日志审计模块
void UpdateConl::sendUpgradeRecordToAudit(const QMap<QString, QString> &record)
{
qDebug() << u8"发送升级记录给日志审计模块:" << record;
}
// 升级完成信号槽函数
void UpdateConl::onProcessFinished(int exitCode, QProcess::ExitStatus exitStatus)
{
emit updateComplete(exitCode, exitStatus);
// QCoreApplication::quit();
}
//获取 更新包 的绝对路径
QString UpdateConl::getUpdatePackagePath()
{
QSettings settings(DATA_PATH + "/Update.ini", QSettings::IniFormat);
QString fileName = settings.value("FileName", "").toString();
QDir updateDir(DATA_PATH + "/Update");
return updateDir.absoluteFilePath(fileName);
}
// 校验升级配置文件的UpdateStatus
void UpdateConl::checkUpdateIni()
{
if (checkForUpdates() && !m_updateConfirmationShown)
{
showUpdateConfirmation();
}
}
// 是否升级确认框
void UpdateConl::showUpdateConfirmation()
{
if(!m_updateConfirmationShown)
{
// int result = QMessageBox::question(this, "更新提示", "发现可用更新,是否立即升级?",
// QMessageBox::Yes | QMessageBox::No);
const QString title = QString::fromUtf8("更新提示");
const QString text = QString::fromUtf8("发现可用更新,是否立即升级?");
int result = QMessageBox::information(this,title, text, QMessageBox::Yes | QMessageBox::No);
// QMessageBox msgBox(QMessageBox::Information, title, text, QMessageBox::Yes | QMessageBox::No, this);
// msgBox.exec();
m_updateConfirmationShown = true;
handleUpdateConfirmation(result);
}
}
// 处理是否升级
void UpdateConl::handleUpdateConfirmation(int result)
{
if (result == QMessageBox::Yes)
{
checkAndUpdate();
qDebug()<<u8"已升级";
// 发送升级记录给日志审计模块
handleUpgradeRecordOnRestart();
m_checkTimer->stop();
m_updateConfirmationShown = false;
}
else
{
qDebug()<<u8"未升级";
m_checkTimer->stop();
// 若不升级1分钟后再次提醒
m_checkTimer->start(60000);
// m_reminderTimer->start(60000);
}
}
#ifndef UPDATECONL_H
#define UPDATECONL_H
#include <QWidget>
#include <QProcess>
#include <QTimer>
#include <QSettings> // 用于读取配置文件
#include <QDebug>
#include <QDir>
#include <QDateTime>
#include <QProcess>
#include <QMessageBox>
struct UpdateConfig
{
QString fileName;
QString updateStatus;
};
namespace Ui {
class UpdateConl;
}
class UpdateConl : public QWidget
{
Q_OBJECT
public:
explicit UpdateConl(QWidget *parent = 0);
~UpdateConl();
// 检查更新
bool checkForUpdates();
// 执行执行更新操作,如下载并安装依赖库、成果物更新等(调用外部的 update.sh 脚本)
void checkAndUpdate();
// 获取配置文件信息
UpdateConfig getConfigInfo();
// 获取 Update.ini 的升级记录信息
void handleUpgradeRecordOnRestart();
// 发送升级记录给日志审计模块
void sendUpgradeRecordToAudit(const QMap<QString, QString> &record);
// 更新 Update.ini 中的更新状态
static void updateUpdateStatus(const QString &file,const QString &status, const QString &result, const QString &msg = "");
static const QString DATA_PATH;
// 从配置文件读取是否需要立即更新的设置
bool isImmediateUpdateRequired();
signals:
// 信号用于通知更新进度、状态变化等
void updateProgress(int progress);
void updateCompleted();
//发送文件更新信号
void updateStatus(const bool success, const QString& upFileName);
void updateStatusChanged(const bool &status);
void customProcessFinished(const QString& fileName, int exitCode, QProcess::ExitStatus exitStatus);
void UpdateStatusFalse(const QString &status);
void updateComplete(int exitCode, QProcess::ExitStatus exitStatus);
public slots:
private slots:
// // 校验升级配置文件的 UpdateStatus
// void checkUpdateIni();
// // 是否升级确认框
// void showUpdateConfirmation();
// // 处理是否升级
// void handleUpdateConfirmation(int result);
private:
Ui::UpdateConl *ui;
QProcess *updateProcess;
void onProcessFinished(int exitCode, QProcess::ExitStatus exitStatus);
void onCustomProcessFinished(const QString& fileName, int exitCode, QProcess::ExitStatus exitStatus);
// 升级文件名字
QString upFileName;
// 有升级可用包发现
bool m_updateConfirmationShown;
// 根据配置文件中的文件名获取完整路径
QString getUpdatePackagePath();
QTimer *m_checkTimer;
QTimer *m_reminderTimer;
};
#endif // UPDATECONL_H