mirror of
https://gitee.com/spark-store-project/spark-store
synced 2025-11-05 16:42:20 +08:00
chore:下载metalink
This commit is contained in:
parent
c0e670f6c1
commit
a2aadf44e3
0
CMakeLists.txt
Normal file
0
CMakeLists.txt
Normal file
@ -9,8 +9,8 @@ set(CMAKE_AUTORCC ON)
|
||||
set(CMAKE_CXX_STANDARD 17)
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||
|
||||
find_package(QT NAMES Qt6 Qt5 REQUIRED COMPONENTS Widgets)
|
||||
find_package(Qt${QT_VERSION_MAJOR} REQUIRED COMPONENTS Widgets)
|
||||
find_package(QT NAMES Qt6 Qt5 REQUIRED COMPONENTS Widgets Network)
|
||||
find_package(Qt${QT_VERSION_MAJOR} REQUIRED COMPONENTS Widgets Network)
|
||||
|
||||
set(PROJECT_SOURCES
|
||||
main.cpp
|
||||
@ -47,7 +47,7 @@ else()
|
||||
endif()
|
||||
endif()
|
||||
|
||||
target_link_libraries(Spark-Update-Tool PRIVATE Qt${QT_VERSION_MAJOR}::Widgets)
|
||||
target_link_libraries(Spark-Update-Tool PRIVATE Qt${QT_VERSION_MAJOR}::Widgets Qt${QT_VERSION_MAJOR}::Network)
|
||||
|
||||
# Qt for iOS sets MACOSX_BUNDLE_GUI_IDENTIFIER automatically since Qt 6.1.
|
||||
# If you are developing for iOS or macOS you should consider setting an
|
||||
|
||||
@ -5,6 +5,7 @@
|
||||
#include <QProgressBar>
|
||||
#include <QPushButton>
|
||||
#include <QApplication> // 包含 QApplication 头文件
|
||||
#include <QDir> // 添加 QDir 头文件
|
||||
|
||||
AppDelegate::AppDelegate(QObject *parent) : QStyledItemDelegate(parent), m_downloadManager(new DownloadManager(this))
|
||||
{
|
||||
@ -128,23 +129,32 @@ bool AppDelegate::editorEvent(QEvent *event, QAbstractItemModel *model, const QS
|
||||
// 取消按钮区域
|
||||
QRect cancelButtonRect(rect.right() - 70, rect.top() + (rect.height() - 20) / 2, 60, 20);
|
||||
if (cancelButtonRect.contains(mouseEvent->pos())) {
|
||||
// 修正方法调用,假设 DownloadManager 有 killProcess 方法
|
||||
if (m_downloadManager->isRunning()) {
|
||||
m_downloadManager->killProcess();
|
||||
m_isDownloading = false;
|
||||
emit updateDisplay(); // 触发重绘
|
||||
}
|
||||
// 修正方法调用,假设 DownloadManager 有 cancelDownload 方法
|
||||
m_downloadManager->cancelDownload();
|
||||
m_isDownloading = false;
|
||||
emit updateDisplay(); // 触发重绘
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
// 更新按钮区域
|
||||
QRect buttonRect(rect.right() - 80, rect.top() + (rect.height() - 30) / 2, 70, 30);
|
||||
if (buttonRect.contains(mouseEvent->pos())) {
|
||||
// 修改这里:使用Qt::UserRole +1获取包名
|
||||
QString packageName = index.data(Qt::UserRole + 1).toString();
|
||||
QString downloadUrl = index.data(Qt::UserRole + 7).toString();
|
||||
|
||||
qDebug() << "从模型中获取的包名:" << packageName;
|
||||
qDebug() << "从模型中获取的下载 URL:" << downloadUrl; // 检查模型中是否正确传递 URL
|
||||
|
||||
if (downloadUrl.isEmpty()) {
|
||||
qWarning() << "下载 URL 为空,无法开始下载,包名:" << packageName;
|
||||
return false;
|
||||
}
|
||||
|
||||
QString outputPath = QString("%1/%2.metalink").arg(QDir::tempPath(), packageName);
|
||||
|
||||
m_isDownloading = true;
|
||||
m_progress = 0;
|
||||
m_downloadManager->startDownload(packageName);
|
||||
m_downloadManager->startDownload(downloadUrl, outputPath);
|
||||
emit updateDisplay(); // 触发重绘
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -14,29 +14,49 @@ QVariant AppListModel::data(const QModelIndex &index, int role) const
|
||||
if (!index.isValid() || index.row() >= m_data.size())
|
||||
return QVariant();
|
||||
|
||||
const QJsonObject obj = m_data.at(index.row()).toObject();
|
||||
|
||||
const QVariantMap &map = m_data.at(index.row()); // 直接访问 QVariantMap
|
||||
switch (role) {
|
||||
case Qt::DisplayRole:
|
||||
return obj["name"].toString();
|
||||
return map.value("name");
|
||||
case Qt::UserRole + 1: // 包名
|
||||
return obj["package"].toString();
|
||||
return map.value("package");
|
||||
case Qt::UserRole + 2: // 当前版本
|
||||
return obj["current_version"].toString();
|
||||
return map.value("current_version");
|
||||
case Qt::UserRole + 3: // 新版本
|
||||
return obj["new_version"].toString();
|
||||
return map.value("new_version");
|
||||
case Qt::UserRole + 4: // 图标路径
|
||||
return obj["icon"].toString();
|
||||
return map.value("icon");
|
||||
case Qt::UserRole + 5: // 文件大小
|
||||
return obj["size"].toVariant();
|
||||
return map.value("size");
|
||||
case Qt::UserRole + 6: // 描述
|
||||
return map.value("description");
|
||||
case Qt::UserRole + 7: // 下载 URL
|
||||
return map.value("download_url"); // 返回下载 URL
|
||||
default:
|
||||
return QVariant();
|
||||
}
|
||||
}
|
||||
|
||||
void AppListModel::setUpdateData(const QJsonArray &data)
|
||||
void AppListModel::setUpdateData(const QJsonArray &updateInfo)
|
||||
{
|
||||
beginResetModel();
|
||||
m_data = data;
|
||||
m_data.clear(); // 清空 QList<QVariantMap>
|
||||
|
||||
for (const auto &item : updateInfo) {
|
||||
QJsonObject obj = item.toObject();
|
||||
QVariantMap map;
|
||||
map["package"] = obj["package"].toString();
|
||||
map["name"] = obj["name"].toString();
|
||||
map["current_version"] = obj["current_version"].toString();
|
||||
map["new_version"] = obj["new_version"].toString();
|
||||
map["icon"] = obj["icon"].toString();
|
||||
map["size"] = obj["size"].toString();
|
||||
map["download_url"] = obj["download_url"].toString(); // 确保设置下载 URL
|
||||
m_data.append(map); // 添加到 QList<QVariantMap>
|
||||
|
||||
qDebug() << "设置到模型的包名:" << map["package"].toString();
|
||||
qDebug() << "设置到模型的下载 URL:" << map["download_url"].toString(); // 检查设置的数据
|
||||
}
|
||||
|
||||
endResetModel();
|
||||
}
|
||||
|
||||
@ -20,7 +20,7 @@ public:
|
||||
void setUpdateData(const QJsonArray &data);
|
||||
|
||||
private:
|
||||
QJsonArray m_data;
|
||||
QList<QVariantMap> m_data; // 修改类型为 QList<QVariantMap>
|
||||
};
|
||||
|
||||
#endif // APPLISTMODEL_H
|
||||
|
||||
@ -381,9 +381,14 @@ QJsonArray aptssUpdater::getUpdateInfoAsJson()
|
||||
}
|
||||
|
||||
// 在构建JSON对象时添加新字段(在jsonObj中添加):
|
||||
jsonObj["download_url"] = packageInfo[packageName]["url"];
|
||||
if (packageInfo[packageName].contains("url")) {
|
||||
jsonObj["download_url"] = packageInfo[packageName]["url"];
|
||||
qDebug() << "生成的下载 URL:" << packageInfo[packageName]["url"]; // 检查生成的 URL
|
||||
} else {
|
||||
qWarning() << "未找到下载 URL,包名:" << packageName;
|
||||
jsonObj["download_url"] = ""; // 设置为空字符串以避免崩溃
|
||||
}
|
||||
jsonObj["sha512"] = packageInfo[packageName]["sha512"];
|
||||
|
||||
jsonArray.append(jsonObj);
|
||||
}
|
||||
qDebug()<<jsonArray;
|
||||
|
||||
@ -1,80 +1,68 @@
|
||||
#include "downloadmanager.h"
|
||||
#include <QDebug> // 包含 QDebug 头文件
|
||||
#include <QFile>
|
||||
#include <QDebug>
|
||||
|
||||
DownloadManager::DownloadManager(QObject *parent) : QObject(parent), m_process(new QProcess(this))
|
||||
DownloadManager::DownloadManager(QObject *parent) : QObject(parent) {}
|
||||
|
||||
void DownloadManager::startDownload(const QString &url, const QString &outputPath)
|
||||
{
|
||||
m_progressRegex = QRegularExpression(R"(\((\d+)%\))");
|
||||
connect(m_process, &QProcess::readyReadStandardOutput, this, &DownloadManager::onProcessReadyRead);
|
||||
connect(m_process, QOverload<int, QProcess::ExitStatus>::of(&QProcess::finished), this, &DownloadManager::onProcessFinished);
|
||||
qDebug() << "接收到的下载 URL:" << url; // 检查 URL 是否正确传递
|
||||
|
||||
// 验证 URL 是否包含协议
|
||||
QUrl metalinkUrl(url + ".metalink");
|
||||
if (!metalinkUrl.isValid() || metalinkUrl.scheme().isEmpty()) {
|
||||
qWarning() << "无效的 URL:" << metalinkUrl.toString();
|
||||
emit downloadFinished(false);
|
||||
return;
|
||||
}
|
||||
|
||||
QNetworkRequest request(metalinkUrl);
|
||||
m_reply = m_networkManager.get(request);
|
||||
|
||||
connect(m_reply, &QNetworkReply::downloadProgress, this, &DownloadManager::onDownloadProgress);
|
||||
connect(m_reply, &QNetworkReply::finished, this, &DownloadManager::onDownloadFinished);
|
||||
|
||||
// 保存路径
|
||||
m_reply->setProperty("outputPath", outputPath);
|
||||
}
|
||||
|
||||
DownloadManager::~DownloadManager()
|
||||
void DownloadManager::onDownloadProgress(qint64 bytesReceived, qint64 bytesTotal)
|
||||
{
|
||||
if (m_process->state() == QProcess::Running) {
|
||||
m_process->kill();
|
||||
// 原代码
|
||||
// m_process->waitForFinished();
|
||||
|
||||
// 修改后增加超时处理
|
||||
if (!m_process->waitForFinished(5000)) {
|
||||
qWarning() << "进程终止超时";
|
||||
}
|
||||
if (bytesTotal > 0) {
|
||||
int progress = static_cast<int>((bytesReceived * 100) / bytesTotal);
|
||||
emit downloadProgress(progress);
|
||||
}
|
||||
}
|
||||
|
||||
void DownloadManager::startDownload(const QString &appName)
|
||||
void DownloadManager::onDownloadFinished()
|
||||
{
|
||||
// 输出开始下载的日志
|
||||
QString program = "aptss";
|
||||
QStringList arguments;
|
||||
arguments << "download" << "--print-uris" << appName;
|
||||
|
||||
qDebug() << "执行命令:" << program << arguments.join(" ");
|
||||
m_process->start(program, arguments);
|
||||
}
|
||||
|
||||
void DownloadManager::onProcessReadyRead()
|
||||
{
|
||||
static QString buffer; // 缓存未处理的输出
|
||||
buffer += QString::fromUtf8(m_process->readAllStandardOutput());
|
||||
|
||||
const QStringList lines = buffer.split(QRegularExpression("[\r\n]"), Qt::SkipEmptyParts);
|
||||
|
||||
for (const QString &line : lines) {
|
||||
QRegularExpressionMatch match = m_progressRegex.match(line);
|
||||
if (match.hasMatch()) {
|
||||
int progress = match.captured(1).toInt();
|
||||
qDebug() << "匹配进度:" << progress << "% => " << line;
|
||||
emit downloadProgress(progress);
|
||||
if (m_reply->error() == QNetworkReply::NoError) {
|
||||
QString outputPath = m_reply->property("outputPath").toString();
|
||||
QFile file(outputPath);
|
||||
if (file.open(QIODevice::WriteOnly)) {
|
||||
file.write(m_reply->readAll());
|
||||
file.close();
|
||||
qDebug() << "文件已保存到路径:" << outputPath; // 输出保存路径
|
||||
emit downloadFinished(true);
|
||||
} else {
|
||||
// qDebug() << "未匹配行:" << line;
|
||||
qWarning() << "无法保存文件到路径:" << outputPath;
|
||||
emit downloadFinished(false);
|
||||
}
|
||||
}
|
||||
|
||||
// 如果最后不是完整的一行,保留最后一部分
|
||||
if (!buffer.endsWith('\n') && !buffer.endsWith('\r')) {
|
||||
buffer = lines.last();
|
||||
} else {
|
||||
buffer.clear();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void DownloadManager::onProcessFinished(int exitCode, QProcess::ExitStatus exitStatus)
|
||||
{
|
||||
bool success = (exitStatus == QProcess::NormalExit && exitCode == 0);
|
||||
emit downloadFinished(success);
|
||||
}
|
||||
|
||||
bool DownloadManager::isRunning() const
|
||||
{
|
||||
return m_process->state() == QProcess::Running;
|
||||
}
|
||||
|
||||
void DownloadManager::killProcess()
|
||||
{
|
||||
if (m_process->state() == QProcess::Running) {
|
||||
m_process->kill();
|
||||
m_process->waitForFinished();
|
||||
qWarning() << "下载失败:" << m_reply->errorString();
|
||||
emit downloadFinished(false);
|
||||
}
|
||||
|
||||
m_reply->deleteLater();
|
||||
m_reply = nullptr;
|
||||
}
|
||||
|
||||
void DownloadManager::cancelDownload()
|
||||
{
|
||||
if (m_reply) {
|
||||
m_reply->abort(); // 取消当前下载
|
||||
m_reply->deleteLater();
|
||||
m_reply = nullptr;
|
||||
emit downloadFinished(false); // 发送下载失败信号
|
||||
}
|
||||
}
|
||||
|
||||
@ -2,30 +2,28 @@
|
||||
#define DOWNLOADMANAGER_H
|
||||
|
||||
#include <QObject>
|
||||
#include <QProcess>
|
||||
#include <QRegularExpression>
|
||||
#include <QNetworkAccessManager>
|
||||
#include <QNetworkReply>
|
||||
|
||||
class DownloadManager : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit DownloadManager(QObject *parent = nullptr);
|
||||
~DownloadManager();
|
||||
|
||||
void startDownload(const QString &appName);
|
||||
bool isRunning() const; // 声明 isRunning 方法
|
||||
void killProcess(); // 声明 killProcess 方法
|
||||
void startDownload(const QString &url, const QString &outputPath);
|
||||
void cancelDownload(); // 添加取消下载的方法
|
||||
|
||||
signals:
|
||||
void downloadProgress(int progress);
|
||||
void downloadFinished(bool success);
|
||||
void downloadProgress(int progress); // 下载进度信号
|
||||
void downloadFinished(bool success); // 下载完成信号
|
||||
|
||||
private slots:
|
||||
void onProcessReadyRead();
|
||||
void onProcessFinished(int exitCode, QProcess::ExitStatus exitStatus);
|
||||
void onDownloadProgress(qint64 bytesReceived, qint64 bytesTotal);
|
||||
void onDownloadFinished();
|
||||
|
||||
private:
|
||||
QProcess *m_process;
|
||||
QRegularExpression m_progressRegex;
|
||||
QNetworkAccessManager m_networkManager;
|
||||
QNetworkReply *m_reply = nullptr;
|
||||
};
|
||||
|
||||
#endif // DOWNLOADMANAGER_H
|
||||
|
||||
@ -151,7 +151,12 @@ void MainWindow::checkUpdates()
|
||||
aptssUpdater updater;
|
||||
QJsonArray updateInfo = updater.getUpdateInfoAsJson();
|
||||
m_model->setUpdateData(updateInfo);
|
||||
|
||||
|
||||
for (const auto &item : updateInfo) {
|
||||
QJsonObject obj = item.toObject();
|
||||
qDebug() << "模型设置的包名:" << obj["package"].toString();
|
||||
qDebug() << "模型设置的下载 URL:" << obj["download_url"].toString(); // 检查模型数据
|
||||
}
|
||||
}
|
||||
|
||||
MainWindow::~MainWindow()
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user