mirror of
https://gitee.com/spark-store-project/spark-store
synced 2026-04-26 09:20:18 +08:00
feat(迁移功能): 添加包迁移功能支持
实现从aptss到apm的包迁移功能 - 添加迁移包集合存储用户确认的迁移项 - 在数据模型中添加迁移相关字段 - 修改合并逻辑以识别迁移场景 - 添加迁移确认对话框 - 处理迁移安装时的特殊逻辑
This commit is contained in:
@@ -9,6 +9,7 @@
|
|||||||
#include <QMouseEvent>
|
#include <QMouseEvent>
|
||||||
#include <QFile>
|
#include <QFile>
|
||||||
#include <QEventLoop>
|
#include <QEventLoop>
|
||||||
|
#include <QMessageBox>
|
||||||
|
|
||||||
AppDelegate::AppDelegate(QObject *parent)
|
AppDelegate::AppDelegate(QObject *parent)
|
||||||
: QStyledItemDelegate(parent), m_downloadManager(new DownloadManager(this)), m_installProcess(nullptr) {
|
: QStyledItemDelegate(parent), m_downloadManager(new DownloadManager(this)), m_installProcess(nullptr) {
|
||||||
@@ -380,6 +381,23 @@ bool AppDelegate::editorEvent(QEvent *event, QAbstractItemModel *model,
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 检查是否为迁移项
|
||||||
|
bool isMigration = index.data(Qt::UserRole + 10).toBool();
|
||||||
|
if (isMigration) {
|
||||||
|
QString migrationTarget = index.data(Qt::UserRole + 12).toString();
|
||||||
|
QMessageBox::StandardButton reply = QMessageBox::question(
|
||||||
|
nullptr,
|
||||||
|
"确认迁移",
|
||||||
|
QString("此更新将把应用替换为 %1 版本,是否继续?").arg(migrationTarget.toUpper()),
|
||||||
|
QMessageBox::Yes | QMessageBox::No
|
||||||
|
);
|
||||||
|
if (reply != QMessageBox::Yes) {
|
||||||
|
return true; // 用户取消,不执行更新
|
||||||
|
}
|
||||||
|
// 用户确认,标记为迁移安装
|
||||||
|
m_migrationPackages.insert(packageName);
|
||||||
|
}
|
||||||
|
|
||||||
// 检查/tmp目录下是否已经存在deb包
|
// 检查/tmp目录下是否已经存在deb包
|
||||||
QDir tempDir(QDir::tempPath());
|
QDir tempDir(QDir::tempPath());
|
||||||
QStringList debs = tempDir.entryList(QStringList() << QString("%1_*.deb").arg(packageName), QDir::Files);
|
QStringList debs = tempDir.entryList(QStringList() << QString("%1_*.deb").arg(packageName), QDir::Files);
|
||||||
@@ -410,6 +428,58 @@ bool AppDelegate::editorEvent(QEvent *event, QAbstractItemModel *model,
|
|||||||
|
|
||||||
void AppDelegate::startDownloadForAll() {
|
void AppDelegate::startDownloadForAll() {
|
||||||
if (!m_model) return;
|
if (!m_model) return;
|
||||||
|
|
||||||
|
// 收集所有迁移项,准备批量提示
|
||||||
|
QStringList migrationPackages;
|
||||||
|
for (int row = 0; row < m_model->rowCount(); ++row) {
|
||||||
|
QModelIndex index = m_model->index(row, 0);
|
||||||
|
|
||||||
|
// 检查应用是否被忽略
|
||||||
|
bool isIgnored = index.data(Qt::UserRole + 8).toBool();
|
||||||
|
if (isIgnored) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 检查是否为迁移项
|
||||||
|
bool isMigration = index.data(Qt::UserRole + 10).toBool();
|
||||||
|
if (isMigration) {
|
||||||
|
QString packageName = index.data(Qt::UserRole + 1).toString();
|
||||||
|
QString migrationTarget = index.data(Qt::UserRole + 12).toString();
|
||||||
|
migrationPackages.append(QString("%1 → %2").arg(packageName, migrationTarget.toUpper()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 如果有迁移项,弹出批量确认对话框
|
||||||
|
if (!migrationPackages.isEmpty()) {
|
||||||
|
QString message = "以下应用更新后将替换为新的版本来源:\n\n";
|
||||||
|
message += migrationPackages.join("\n");
|
||||||
|
message += "\n\n是否继续更新这些应用?";
|
||||||
|
|
||||||
|
QMessageBox::StandardButton reply = QMessageBox::question(
|
||||||
|
nullptr,
|
||||||
|
"确认迁移",
|
||||||
|
message,
|
||||||
|
QMessageBox::Yes | QMessageBox::No | QMessageBox::Cancel
|
||||||
|
);
|
||||||
|
|
||||||
|
if (reply == QMessageBox::Cancel) {
|
||||||
|
return; // 完全取消更新全部
|
||||||
|
}
|
||||||
|
|
||||||
|
// 如果用户点击 Yes,将所有迁移项加入迁移集合
|
||||||
|
if (reply == QMessageBox::Yes) {
|
||||||
|
for (int row = 0; row < m_model->rowCount(); ++row) {
|
||||||
|
QModelIndex index = m_model->index(row, 0);
|
||||||
|
bool isMigration = index.data(Qt::UserRole + 10).toBool();
|
||||||
|
if (isMigration) {
|
||||||
|
QString packageName = index.data(Qt::UserRole + 1).toString();
|
||||||
|
m_migrationPackages.insert(packageName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// 如果用户点击 No,跳过迁移项,继续更新其他应用
|
||||||
|
}
|
||||||
|
|
||||||
for (int row = 0; row < m_model->rowCount(); ++row) {
|
for (int row = 0; row < m_model->rowCount(); ++row) {
|
||||||
QModelIndex index = m_model->index(row, 0);
|
QModelIndex index = m_model->index(row, 0);
|
||||||
|
|
||||||
@@ -421,6 +491,14 @@ void AppDelegate::startDownloadForAll() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
QString packageName = index.data(Qt::UserRole + 1).toString();
|
QString packageName = index.data(Qt::UserRole + 1).toString();
|
||||||
|
|
||||||
|
// 检查是否为迁移项且用户未确认
|
||||||
|
bool isMigration = index.data(Qt::UserRole + 10).toBool();
|
||||||
|
if (isMigration && !m_migrationPackages.contains(packageName)) {
|
||||||
|
qDebug() << "跳过未确认的迁移项:" << packageName;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if (m_downloads.contains(packageName) && (m_downloads[packageName].isDownloading || m_downloads[packageName].isInstalled))
|
if (m_downloads.contains(packageName) && (m_downloads[packageName].isDownloading || m_downloads[packageName].isInstalled))
|
||||||
continue;
|
continue;
|
||||||
QString downloadUrl = index.data(Qt::UserRole + 7).toString();
|
QString downloadUrl = index.data(Qt::UserRole + 7).toString();
|
||||||
@@ -485,8 +563,11 @@ void AppDelegate::startNextInstall() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 如果是APM包,先检查APM中是否存在对应的包,再卸载APTSS版本
|
// 检查是否为迁移场景
|
||||||
if (source == "apm") {
|
bool isMigration = m_migrationPackages.contains(packageName);
|
||||||
|
|
||||||
|
// 如果是APM包或者是迁移场景,先检查APM中是否存在对应的包,再卸载APTSS版本
|
||||||
|
if (source == "apm" || isMigration) {
|
||||||
// 检查APM中是否存在对应的包
|
// 检查APM中是否存在对应的包
|
||||||
QProcess checkProcess;
|
QProcess checkProcess;
|
||||||
QStringList checkArgs;
|
QStringList checkArgs;
|
||||||
@@ -849,6 +930,55 @@ void AppDelegate::updateSpinner() {
|
|||||||
// 新增:更新选中应用的方法
|
// 新增:更新选中应用的方法
|
||||||
void AppDelegate::startDownloadForSelected() {
|
void AppDelegate::startDownloadForSelected() {
|
||||||
if (!m_model) return;
|
if (!m_model) return;
|
||||||
|
|
||||||
|
// 首先检查选中的应用中是否有迁移项
|
||||||
|
QStringList selectedMigrationPackages;
|
||||||
|
for (int row = 0; row < m_model->rowCount(); ++row) {
|
||||||
|
QModelIndex index = m_model->index(row, 0);
|
||||||
|
QString packageName = index.data(Qt::UserRole + 1).toString();
|
||||||
|
|
||||||
|
if (m_selectedPackages.contains(packageName)) {
|
||||||
|
bool isMigration = index.data(Qt::UserRole + 10).toBool();
|
||||||
|
if (isMigration && !m_migrationPackages.contains(packageName)) {
|
||||||
|
QString migrationTarget = index.data(Qt::UserRole + 12).toString();
|
||||||
|
selectedMigrationPackages.append(QString("%1 → %2").arg(packageName, migrationTarget.toUpper()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 如果有未确认的迁移项,弹出确认对话框
|
||||||
|
if (!selectedMigrationPackages.isEmpty()) {
|
||||||
|
QString message = "以下选中的应用更新后将替换为新的版本来源:\n\n";
|
||||||
|
message += selectedMigrationPackages.join("\n");
|
||||||
|
message += "\n\n是否继续更新这些应用?";
|
||||||
|
|
||||||
|
QMessageBox::StandardButton reply = QMessageBox::question(
|
||||||
|
nullptr,
|
||||||
|
"确认迁移",
|
||||||
|
message,
|
||||||
|
QMessageBox::Yes | QMessageBox::No | QMessageBox::Cancel
|
||||||
|
);
|
||||||
|
|
||||||
|
if (reply == QMessageBox::Cancel) {
|
||||||
|
return; // 完全取消更新
|
||||||
|
}
|
||||||
|
|
||||||
|
// 如果用户点击 Yes,将选中的迁移项加入迁移集合
|
||||||
|
if (reply == QMessageBox::Yes) {
|
||||||
|
for (int row = 0; row < m_model->rowCount(); ++row) {
|
||||||
|
QModelIndex index = m_model->index(row, 0);
|
||||||
|
QString packageName = index.data(Qt::UserRole + 1).toString();
|
||||||
|
if (m_selectedPackages.contains(packageName)) {
|
||||||
|
bool isMigration = index.data(Qt::UserRole + 10).toBool();
|
||||||
|
if (isMigration) {
|
||||||
|
m_migrationPackages.insert(packageName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// 如果用户点击 No,继续更新其他应用,跳过未确认的迁移项
|
||||||
|
}
|
||||||
|
|
||||||
for (int row = 0; row < m_model->rowCount(); ++row) {
|
for (int row = 0; row < m_model->rowCount(); ++row) {
|
||||||
QModelIndex index = m_model->index(row, 0);
|
QModelIndex index = m_model->index(row, 0);
|
||||||
QString packageName = index.data(Qt::UserRole + 1).toString();
|
QString packageName = index.data(Qt::UserRole + 1).toString();
|
||||||
@@ -862,6 +992,13 @@ void AppDelegate::startDownloadForSelected() {
|
|||||||
|
|
||||||
// 只下载选中的应用
|
// 只下载选中的应用
|
||||||
if (m_selectedPackages.contains(packageName)) {
|
if (m_selectedPackages.contains(packageName)) {
|
||||||
|
// 检查是否为迁移项且用户未确认
|
||||||
|
bool isMigration = index.data(Qt::UserRole + 10).toBool();
|
||||||
|
if (isMigration && !m_migrationPackages.contains(packageName)) {
|
||||||
|
qDebug() << "跳过未确认的迁移项:" << packageName;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if (m_downloads.contains(packageName) && (m_downloads[packageName].isDownloading || m_downloads[packageName].isInstalled))
|
if (m_downloads.contains(packageName) && (m_downloads[packageName].isDownloading || m_downloads[packageName].isInstalled))
|
||||||
continue;
|
continue;
|
||||||
QString downloadUrl = index.data(Qt::UserRole + 7).toString();
|
QString downloadUrl = index.data(Qt::UserRole + 7).toString();
|
||||||
|
|||||||
@@ -58,6 +58,9 @@ private:
|
|||||||
// 复选框相关成员变量
|
// 复选框相关成员变量
|
||||||
QSet<QString> m_selectedPackages;
|
QSet<QString> m_selectedPackages;
|
||||||
|
|
||||||
|
// 迁移包集合(用户确认要迁移的包)
|
||||||
|
QSet<QString> m_migrationPackages;
|
||||||
|
|
||||||
QQueue<QString> m_installQueue;
|
QQueue<QString> m_installQueue;
|
||||||
bool m_isInstalling = false;
|
bool m_isInstalling = false;
|
||||||
QProcess *m_installProcess = nullptr;
|
QProcess *m_installProcess = nullptr;
|
||||||
|
|||||||
@@ -36,6 +36,12 @@ QVariant AppListModel::data(const QModelIndex &index, int role) const
|
|||||||
return map.value("ignored");
|
return map.value("ignored");
|
||||||
case Qt::UserRole + 9: // 包来源
|
case Qt::UserRole + 9: // 包来源
|
||||||
return map.value("source");
|
return map.value("source");
|
||||||
|
case Qt::UserRole + 10: // 是否为迁移项
|
||||||
|
return map.value("is_migration");
|
||||||
|
case Qt::UserRole + 11: // 迁移源
|
||||||
|
return map.value("migration_source");
|
||||||
|
case Qt::UserRole + 12: // 迁移目标
|
||||||
|
return map.value("migration_target");
|
||||||
default:
|
default:
|
||||||
return QVariant();
|
return QVariant();
|
||||||
}
|
}
|
||||||
@@ -58,6 +64,9 @@ void AppListModel::setUpdateData(const QJsonArray &updateInfo)
|
|||||||
map["download_url"] = obj["download_url"].toString(); // 确保设置下载 URL
|
map["download_url"] = obj["download_url"].toString(); // 确保设置下载 URL
|
||||||
map["ignored"] = obj["ignored"].toBool(); // 设置忽略状态
|
map["ignored"] = obj["ignored"].toBool(); // 设置忽略状态
|
||||||
map["source"] = obj["source"].toString(); // 设置包来源
|
map["source"] = obj["source"].toString(); // 设置包来源
|
||||||
|
map["is_migration"] = obj["is_migration"].toBool(); // 设置是否为迁移项
|
||||||
|
map["migration_source"] = obj["migration_source"].toString(); // 设置迁移源
|
||||||
|
map["migration_target"] = obj["migration_target"].toString(); // 设置迁移目标
|
||||||
m_data.append(map); // 添加到 QList<QVariantMap>
|
m_data.append(map); // 添加到 QList<QVariantMap>
|
||||||
|
|
||||||
qDebug() << "设置到模型的包名:" << map["package"].toString() << "忽略状态:" << map["ignored"].toBool() << "来源:" << map["source"].toString();
|
qDebug() << "设置到模型的包名:" << map["package"].toString() << "忽略状态:" << map["ignored"].toBool() << "来源:" << map["source"].toString();
|
||||||
|
|||||||
@@ -647,13 +647,23 @@ QJsonArray aptssUpdater::mergeUpdateInfo()
|
|||||||
QString aptssVersion = aptssObj["new_version"].toString();
|
QString aptssVersion = aptssObj["new_version"].toString();
|
||||||
QString apmVersion = apmObj["new_version"].toString();
|
QString apmVersion = apmObj["new_version"].toString();
|
||||||
|
|
||||||
// 这里简化处理,实际应该使用版本比较函数
|
// 检查是否为迁移场景:APM版本更新,且当前包是通过aptss安装的
|
||||||
|
// 通过检查aptss中是否有当前版本号来判断是否通过aptss安装
|
||||||
if (apmVersion > aptssVersion) {
|
if (apmVersion > aptssVersion) {
|
||||||
// APM版本更高,使用APM版本
|
// 迁移场景:Spark -> APM
|
||||||
mergedArray.append(apmObj);
|
QJsonObject migrationObj = apmObj;
|
||||||
|
migrationObj["is_migration"] = true;
|
||||||
|
migrationObj["migration_source"] = "aptss";
|
||||||
|
migrationObj["migration_target"] = "apm";
|
||||||
|
migrationObj["aptss_version"] = aptssVersion;
|
||||||
|
mergedArray.append(migrationObj);
|
||||||
|
|
||||||
|
// 同时保留aptss的更新项(如果aptss也有更新)
|
||||||
|
mergedArray.append(aptssObj);
|
||||||
} else {
|
} else {
|
||||||
// APTSS版本更高或相同,不展示该包
|
// 非迁移场景:同时展示两个来源的更新
|
||||||
qDebug() << "APTSS版本更高,不展示APM包:" << packageName;
|
mergedArray.append(aptssObj);
|
||||||
|
mergedArray.append(apmObj);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user