diff --git a/spark-update-tool/src/appdelegate.cpp b/spark-update-tool/src/appdelegate.cpp index b0a987c6..ff2e24fc 100644 --- a/spark-update-tool/src/appdelegate.cpp +++ b/spark-update-tool/src/appdelegate.cpp @@ -9,6 +9,7 @@ #include #include #include +#include AppDelegate::AppDelegate(QObject *parent) : QStyledItemDelegate(parent), m_downloadManager(new DownloadManager(this)), m_installProcess(nullptr) { @@ -379,7 +380,24 @@ bool AppDelegate::editorEvent(QEvent *event, QAbstractItemModel *model, if (m_downloads.contains(packageName) && !m_downloads[packageName].isDownloading) { 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包 QDir tempDir(QDir::tempPath()); QStringList debs = tempDir.entryList(QStringList() << QString("%1_*.deb").arg(packageName), QDir::Files); @@ -392,7 +410,7 @@ bool AppDelegate::editorEvent(QEvent *event, QAbstractItemModel *model, debPath = tempDir.absoluteFilePath(debs.first()); } } - + // 触发下载流程(无论是否存在deb包,都尝试续传) QString downloadUrl = index.data(Qt::UserRole + 7).toString(); QString outputPath = QString("%1/%2.metalink").arg(QDir::tempPath(), packageName); @@ -410,17 +428,77 @@ bool AppDelegate::editorEvent(QEvent *event, QAbstractItemModel *model, void AppDelegate::startDownloadForAll() { 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) { + QModelIndex index = m_model->index(row, 0); + // 检查应用是否被忽略 bool isIgnored = index.data(Qt::UserRole + 8).toBool(); if (isIgnored) { qDebug() << "跳过被忽略的应用:" << index.data(Qt::UserRole + 1).toString(); continue; } - + 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)) continue; QString downloadUrl = index.data(Qt::UserRole + 7).toString(); @@ -485,15 +563,18 @@ void AppDelegate::startNextInstall() { } } - // 如果是APM包,先检查APM中是否存在对应的包,再卸载APTSS版本 - if (source == "apm") { + // 检查是否为迁移场景 + bool isMigration = m_migrationPackages.contains(packageName); + + // 如果是APM包或者是迁移场景,先检查APM中是否存在对应的包,再卸载APTSS版本 + if (source == "apm" || isMigration) { // 检查APM中是否存在对应的包 QProcess checkProcess; QStringList checkArgs; checkArgs << "list" << packageName; checkProcess.start("apm", checkArgs); checkProcess.waitForFinished(30000); // 30秒超时 - + QString checkOutput = checkProcess.readAllStandardOutput(); if (checkOutput.contains(packageName)) { // APM中存在对应的包,卸载APTSS版本 @@ -849,19 +930,75 @@ void AppDelegate::updateSpinner() { // 新增:更新选中应用的方法 void AppDelegate::startDownloadForSelected() { 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) { + QModelIndex index = m_model->index(row, 0); + QString packageName = index.data(Qt::UserRole + 1).toString(); + // 检查应用是否被忽略 bool isIgnored = index.data(Qt::UserRole + 8).toBool(); if (isIgnored) { qDebug() << "跳过被忽略的应用:" << packageName; continue; } - + // 只下载选中的应用 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)) continue; QString downloadUrl = index.data(Qt::UserRole + 7).toString(); diff --git a/spark-update-tool/src/appdelegate.h b/spark-update-tool/src/appdelegate.h index ac3f69ab..bfc4d780 100644 --- a/spark-update-tool/src/appdelegate.h +++ b/spark-update-tool/src/appdelegate.h @@ -58,6 +58,9 @@ private: // 复选框相关成员变量 QSet m_selectedPackages; + // 迁移包集合(用户确认要迁移的包) + QSet m_migrationPackages; + QQueue m_installQueue; bool m_isInstalling = false; QProcess *m_installProcess = nullptr; diff --git a/spark-update-tool/src/applistmodel.cpp b/spark-update-tool/src/applistmodel.cpp index ed01f050..a08f96f8 100644 --- a/spark-update-tool/src/applistmodel.cpp +++ b/spark-update-tool/src/applistmodel.cpp @@ -36,6 +36,12 @@ QVariant AppListModel::data(const QModelIndex &index, int role) const return map.value("ignored"); case Qt::UserRole + 9: // 包来源 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: return QVariant(); } @@ -58,6 +64,9 @@ void AppListModel::setUpdateData(const QJsonArray &updateInfo) map["download_url"] = obj["download_url"].toString(); // 确保设置下载 URL map["ignored"] = obj["ignored"].toBool(); // 设置忽略状态 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 qDebug() << "设置到模型的包名:" << map["package"].toString() << "忽略状态:" << map["ignored"].toBool() << "来源:" << map["source"].toString(); diff --git a/spark-update-tool/src/aptssupdater.cpp b/spark-update-tool/src/aptssupdater.cpp index 3946a9d2..faf62fce 100644 --- a/spark-update-tool/src/aptssupdater.cpp +++ b/spark-update-tool/src/aptssupdater.cpp @@ -603,7 +603,7 @@ QJsonArray aptssUpdater::mergeUpdateInfo() { QJsonArray aptssInfo = getUpdateInfoAsJson(); QJsonArray apmInfo = getApmUpdateInfoAsJson(); - + // 创建包名到更新信息的映射 QHash aptssMap; for (const QJsonValue &value : aptssInfo) { @@ -612,7 +612,7 @@ QJsonArray aptssUpdater::mergeUpdateInfo() obj["source"] = "aptss"; aptssMap[packageName] = obj; } - + QHash apmMap; for (const QJsonValue &value : apmInfo) { QJsonObject obj = value.toObject(); @@ -620,44 +620,54 @@ QJsonArray aptssUpdater::mergeUpdateInfo() obj["source"] = "apm"; apmMap[packageName] = obj; } - + QJsonArray mergedArray; - + // 处理只在aptss中存在的包 for (const QString &packageName : aptssMap.keys()) { if (!apmMap.contains(packageName)) { mergedArray.append(aptssMap[packageName]); } } - + // 处理只在apm中存在的包 for (const QString &packageName : apmMap.keys()) { if (!aptssMap.contains(packageName)) { mergedArray.append(apmMap[packageName]); } } - + // 处理在两者中都存在的包 for (const QString &packageName : aptssMap.keys()) { if (apmMap.contains(packageName)) { QJsonObject aptssObj = aptssMap[packageName]; QJsonObject apmObj = apmMap[packageName]; - + // 比较版本 QString aptssVersion = aptssObj["new_version"].toString(); QString apmVersion = apmObj["new_version"].toString(); - - // 这里简化处理,实际应该使用版本比较函数 + + // 检查是否为迁移场景:APM版本更新,且当前包是通过aptss安装的 + // 通过检查aptss中是否有当前版本号来判断是否通过aptss安装 if (apmVersion > aptssVersion) { - // APM版本更高,使用APM版本 - mergedArray.append(apmObj); + // 迁移场景:Spark -> APM + 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 { - // APTSS版本更高或相同,不展示该包 - qDebug() << "APTSS版本更高,不展示APM包:" << packageName; + // 非迁移场景:同时展示两个来源的更新 + mergedArray.append(aptssObj); + mergedArray.append(apmObj); } } } - + qDebug()<<"合并后的更新信息:"<