diff --git a/README.md b/README.md index 75dedee..889651f 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,6 @@ [![star](https://gitee.com/deepin-community-store/spark-store/badge/star.svg?theme=gvp)](https://gitee.com/deepin-community-store/spark-store/stargazers) [![fork](https://gitee.com/deepin-community-store/spark-store/badge/fork.svg?theme=gvp)](https://gitee.com/deepin-community-store/spark-store/members) -## You are informed that the aarch64 support is EXPERIMENTAL and there is NO GUARANTEE that this branch will be supported in the future Spark Store aims to collect Linux apps for the convieniece of Linux new comers @@ -35,6 +34,7 @@ If you are using Debian11/Ubuntu 20.04, you will need extra dependency package. --- #### Compile and developement + **dev branch is for development, Flamescion branch is for amd64 and Reason branch is for arrch64.** Although, for the most of the time, Flamescion branch is same as Reason. For Deepin V20/UOS 21/ Debian 11 diff --git a/README.zh.md b/README.zh.md index 2f7ed02..02c3fc0 100644 --- a/README.zh.md +++ b/README.zh.md @@ -2,7 +2,6 @@ [![star](https://gitee.com/deepin-community-store/spark-store/badge/star.svg?theme=gvp)](https://gitee.com/deepin-community-store/spark-store/stargazers) [![fork](https://gitee.com/deepin-community-store/spark-store/badge/fork.svg?theme=gvp)](https://gitee.com/deepin-community-store/spark-store/members) -## 请注意,aarch64的支持是实验性的,并未确认持续支持! 众所周知,国内的Linux应用比较少,wine应用难以获取,优质工具分散在民间各大论坛,无法形成合力,难以改善生态 @@ -33,6 +32,7 @@ --- #### 编译安装 + **dev分支用于开发,Flamescion分支是amd64,Reason分支是aarch64**。然而,绝大多数情况下,Flamescion和Reason的内容是一致的 Deepin V20/UOS 21 系统下, 安装依赖 diff --git a/debian/changelog b/debian/changelog index 73ae563..cb4d444 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,6 +1,11 @@ spark-store (4.2.7.3) stable; urgency=medium - * 修复:aptss透传错误码 + * 修复:aptss现在会正确地透传错误码而不是exit 0 + * 修复:下载时如果卡0%(无法下载metalink),会在超时后报错中断而不是一直傻等 + * 修复:排队下载时CPU占满单核的bug https://gitee.com/deepin-community-store/spark-store/issues/I7B91V + * 修复:在终端中打开的icon过大导致无法投稿到UOS + * 修复:v23下编译出错 + * 薪怎:支持崩溃日志收集系统 -- shenmo Sun, 5 Mar 2022 11:45:14 +0800 diff --git a/pkg/usr/share/icons/hicolor/scalable/apps/open-me-in-terminal.png b/pkg/usr/share/icons/hicolor/scalable/apps/open-me-in-terminal.png index 993a76a..0ae8e54 100644 Binary files a/pkg/usr/share/icons/hicolor/scalable/apps/open-me-in-terminal.png and b/pkg/usr/share/icons/hicolor/scalable/apps/open-me-in-terminal.png differ diff --git a/src/application.cpp b/src/application.cpp index cede3ef..b3e5965 100644 --- a/src/application.cpp +++ b/src/application.cpp @@ -2,6 +2,8 @@ #include "mainwindow-dtk.h" #include "utils/utils.h" +#include +#include #include #include #include diff --git a/src/backend/downloadworker.cpp b/src/backend/downloadworker.cpp index 8b70540..d6f92af 100644 --- a/src/backend/downloadworker.cpp +++ b/src/backend/downloadworker.cpp @@ -5,13 +5,16 @@ #include #include +#define DEFAULTURL "d.store.deepinos.org.cn" +#define MAXWAITTIME 200000 + DownloadController::DownloadController(QObject *parent) { Q_UNUSED(parent) // 初始化默认域名 domains.clear(); - domains.append("d.store.deepinos.org.cn"); + domains.append(DEFAULTURL); /* domains = { @@ -37,7 +40,8 @@ bool checkMeatlink(QString metaUrl) { metaStatus.remove(); } - system("curl -I -s --connect-timeout 5 " + metaUrl.toUtf8() + " -w %{http_code} |tail -n1 > /tmp/spark-store/metaStatus.txt"); + QString cmd = QString("curl -I -s --connect-timeout 5 %1 -w %{http_code} |tail -n1 > /tmp/spark-store/metaStatus.txt").arg(metaUrl); + system(cmd.toUtf8().data()); if (metaStatus.open(QFile::ReadOnly) && QString(metaStatus.readAll()).toUtf8() == "200") { metaStatus.remove(); @@ -68,9 +72,13 @@ void gennerateDomain(QVector &domains) } if (domains.size() == 0) { - domains.append("d.store.deepinos.org.cn"); + domains.append(DEFAULTURL); } } + else + { + domains.append(DEFAULTURL); + } } /** @@ -102,34 +110,36 @@ void DownloadController::startDownload(const QString &url) // qDebug() << domains << domains.size(); } - QString aria2Command = "-d"; - QString aria2Urls = ""; - QString aria2Verbose = "--summary-interval=1"; - QString aria2SizePerThreads = "--min-split-size=1M"; - QString aria2NoConfig = "--no-conf"; - QString aria2NoSeeds = "--seed-time=0"; + QString aria2Command = "-d"; //下载目录 + QString aria2Urls = ""; //下载地址 + QString aria2Verbose = "--summary-interval=1"; //显示下载速度 + QString aria2SizePerThreads = "--min-split-size=1M"; //最小分片大小 + QString aria2NoConfig = "--no-conf"; //不使用配置文件 + QString aria2NoSeeds = "--seed-time=0"; //不做种 QStringList command; - QString downloadDir = "/tmp/spark-store/"; - QString aria2ConnectionPerServer = "--max-connection-per-server=1"; - QString aria2ConnectionMax = "--max-concurrent-downloads=16"; - QString aria2DNSCommand = "--async-dns-server=119.29.29.29,223.5.5.5"; + QString downloadDir = "/tmp/spark-store/"; //下载目录 + QString aria2ConnectionPerServer = "--max-connection-per-server=1"; //每个服务器最大连接数 + QString aria2ConnectionMax = "--max-concurrent-downloads=16"; //最大同时下载数 - if (useMetalink) + + if (useMetalink) //如果是metalink { command.append(metaUrl.toUtf8()); } else { - for (int i = 0; i < domains.size(); i++) + for (int i = 0; i < domains.size(); i++) //遍历域名 { command.append(replaceDomain(url, domains.at(i)).replace("+","%2B").toUtf8()); //对+进行转译,避免oss出错 } } - qint64 downloadSizeRecord = 0; - QString speedInfo = ""; - QString percentInfo = ""; + qint64 downloadSizeRecord = 0; //下载大小记录 + qint8 failDownloadTimes = 0; // 记录重试次数 + const qint8 maxRetryTimes = 3; //最大重试次数 + QString speedInfo = ""; //显示下载速度 + QString percentInfo = ""; //显示下载进度 command.append(aria2Command.toUtf8()); command.append(downloadDir.toUtf8()); command.append(aria2Verbose.toUtf8()); @@ -137,7 +147,7 @@ void DownloadController::startDownload(const QString &url) command.append(aria2SizePerThreads.toUtf8()); command.append(aria2ConnectionPerServer.toUtf8()); command.append(aria2ConnectionMax.toUtf8()); - command.append(aria2DNSCommand.toUtf8()); + if (useMetalink) { command.append(aria2NoSeeds.toUtf8()); @@ -152,11 +162,30 @@ void DownloadController::startDownload(const QString &url) cmd.start(); cmd.waitForStarted(-1); //等待启动完成 + // Timer + QTimer *timeoutTimer = new QTimer(this); + timeoutTimer->setSingleShot(true); // 单次触发 + connect(timeoutTimer, &QTimer::timeout, [&]() { + if (failDownloadTimes < maxRetryTimes) { + qDebug() << "Download timeout, restarting..."; + // 重新启动下载任务的代码 + restartDownload(cmd, command); // 调用重新启动下载任务的函数 + failDownloadTimes += 1; + timeoutTimer->start(MAXWAITTIME); // 重新启动定时器 + } else{ + emit errorOccur(tr("Download Failed, please retry :(")); // 下载失败 + downloadSuccess = false; + cmd.close(); + cmd.terminate(); // 终止当前的下载进程 + cmd.waitForFinished(); // 等待进程结束 + } + }); + connect(&cmd, &QProcess::readyReadStandardOutput, [&]() { + timeoutTimer->start(MAXWAITTIME); // 重置超时计时器,15秒超时 //通过读取输出计算下载速度 QString message = cmd.readAllStandardOutput().data(); - // qDebug() << message; message = message.replace(" ", ""); QStringList list; qint64 downloadSize = 0; @@ -179,10 +208,10 @@ void DownloadController::startDownload(const QString &url) speedInfo = message.mid(speedPlace1 + 3, speedPlace2 - speedPlace1 - 3); speedInfo += "/s"; } - // qDebug() << percentInfo << speedInfo; if (downloadSize >= downloadSizeRecord) { downloadSizeRecord = downloadSize; + timeoutTimer->stop(); // 如果有进度,停止超时计时器 } if (percentInfo == "OK") { @@ -244,6 +273,15 @@ void DownloadController::stopDownload() pidNumber = -1; } +void DownloadController::restartDownload(QProcess &cmd, const QStringList &command) +{ + cmd.terminate(); // 终止当前的下载进程 + cmd.waitForFinished(); // 等待进程结束 + cmd.setArguments(command); // 重新设置参数 + cmd.start(); // 重新启动下载 + cmd.waitForStarted(-1); // 等待启动完成 +} + qint64 DownloadController::getFileSize(const QString &url) { // 已经无需使用 qtnetwork 再获取 filesize,完全交给 aria2 来计算进度。 为保证兼容性,故保留此函数。 diff --git a/src/backend/downloadworker.h b/src/backend/downloadworker.h index 6b7110e..1f3217a 100644 --- a/src/backend/downloadworker.h +++ b/src/backend/downloadworker.h @@ -3,6 +3,7 @@ #include #include +#include class DownloadController : public QObject { @@ -14,6 +15,7 @@ public: void setFilename(QString filename); void startDownload(const QString &url); void stopDownload(); + void restartDownload(QProcess &cmd, const QStringList &command); qint64 getFileSize(const QString& url); QString replaceDomain(const QString& url, const QString domain); diff --git a/src/main.cpp b/src/main.cpp index e0f6fa1..541e3ab 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -2,6 +2,14 @@ #include "mainwindow-dtk.h" #include "utils/utils.h" +#include +#include +#include +#include +#include +#include +#include + #include #include #include @@ -16,12 +24,97 @@ DCORE_USE_NAMESPACE DWIDGET_USE_NAMESPACE +static QString buildDateTime; + + +void crashHandler(int sig) { + void *array[50]; + size_t size = backtrace(array, 50); + if (size == 0) { + perror("backtrace"); + exit(1); + } + + time_t t = time(NULL); + struct tm tm = *localtime(&t); + char filename[128]; + snprintf(filename, sizeof(filename), "/tmp/spark_store_crash_log_%04d%02d%02d_%02d%02d%02d.txt", + tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec); + + std::ofstream logFile(filename, std::ios::out); + if (!logFile.is_open()) { + perror("ofstream"); + exit(1); + } + + logFile << "Please send this log to the developer. QQ Group: 872690351\n"; + logFile << "Build Date and Time: " << buildDateTime.toStdString() << "\n"; + + FILE *fp = popen("uname -m", "r"); + if (fp) { + char buffer[256]; + if (fgets(buffer, sizeof(buffer), fp) != NULL) { + // 移除换行符 + buffer[strcspn(buffer, "\n")] = 0; + logFile << "CPU Architecture: " << buffer << "\n"; + } + pclose(fp); + } else { + logFile << "Failed to gather CPU architecture info.\n"; + } + + + + + FILE *fp2 = popen("lsb_release -a", "r"); + if (fp2) { + char buffer[256]; + while (fgets(buffer, sizeof(buffer), fp2) != NULL) { + logFile << buffer; + } + pclose(fp2); + } else { + logFile << "Failed to gather distribution info.\n"; + } + + + logFile << "Error: signal " << sig << ":\n"; + for (size_t i = 0; i < size; i++) { + char **strings = backtrace_symbols(&array[i], 1); + if (strings != NULL && strings[0] != NULL) { + logFile << strings[0] << "\n"; + } else { + logFile << "Failed to get symbol.\n"; + } + free(strings); + } + + logFile.close(); + + char openCmd[256]; + snprintf(openCmd, sizeof(openCmd), "xdg-open %s", filename); + if (system(openCmd) == -1) { + perror("system"); + } + + fprintf(stderr, "Error: signal %d:\n", sig); + backtrace_symbols_fd(array, size, STDERR_FILENO); + + exit(1); +} + + int main(int argc, char *argv[]) { + // 崩溃处理 + signal(SIGSEGV, crashHandler); // 注册SIGSEGV处理函数 + + // Get build time static const QDate buildDate = QLocale(QLocale::English).toDate(QString(__DATE__).replace(" ", " 0"), "MMM dd yyyy"); static const QTime buildTime = QTime::fromString(__TIME__, "hh:mm:ss"); - static const QString buildDateTime = buildDate.toString("yyyy.MM.dd") + "-" + buildTime.toString("hh:mm:ss"); + buildDateTime = buildDate.toString("yyyy.MM.dd") + "-" + buildTime.toString("hh:mm:ss"); + // NOTE: 提前设置组织名称和应用名称,避免配置文件位置错误 DApplication::setOrganizationName("spark-union"); diff --git a/src/widgets/big_image.cpp b/src/widgets/big_image.cpp index 2549b59..95944e1 100644 --- a/src/widgets/big_image.cpp +++ b/src/widgets/big_image.cpp @@ -17,7 +17,8 @@ big_image::big_image(DBlurEffectWidget *parent) : DBlurEffectWidget(parent), layout->addWidget(m_image); layout->setMargin(0); - // m_image->setParent(this); + // Make sure the image has a parent so that it will be freed. + m_image->setParent(this); // m_image->setMaximumSize(1360,768); m_image->setAlignment(Qt::AlignCenter); } diff --git a/src/widgets/downloadlistwidget.cpp b/src/widgets/downloadlistwidget.cpp index 89fa8ba..f253fb6 100644 --- a/src/widgets/downloadlistwidget.cpp +++ b/src/widgets/downloadlistwidget.cpp @@ -169,6 +169,7 @@ void DownloadListWidget::httpFinished() // 完成下载 { while (downloaditemlist[nowDownload - 1]->readyInstall() == -1) // 安装当前应用,堵塞安装,后面的下载suspend { + QThread::msleep(500); // 休眠500ms,减少CPU负担 continue; } downloaditemlist[nowDownload - 1]->free = true; @@ -179,17 +180,15 @@ void DownloadListWidget::httpFinished() // 完成下载 // 如果有排队则下载下一个 qDebug() << "Download: 切换下一个下载..."; nowDownload += 1; - while (downloaditemlist[nowDownload - 1]->close) + while (nowDownload <= allDownload && downloaditemlist[nowDownload - 1]->close) { nowDownload += 1; - if (nowDownload >= allDownload) - { - nowDownload = allDownload; - return; - } } - QString fileName = downloaditemlist[nowDownload - 1]->getName(); - startRequest(urList.at(nowDownload - 1), fileName); + if (nowDownload <= allDownload) + { + QString fileName = downloaditemlist[nowDownload - 1]->getName(); + startRequest(urList.at(nowDownload - 1), fileName); + } } }); } @@ -236,19 +235,23 @@ void DownloadListWidget::on_pushButton_clicked() void DownloadListWidget::slotInstallFinished(bool success) { // NOTE: 仅在安装成功后判断是否需要退出后台 - if (success) { - toDownload -= 1; // 安装完以后减少待安装数目 - qDebug() << "Download: 还没有下载的数目:" << toDownload; + if (!success) { + qDebug() << "Download: install failed"; + return; + } - if (toDownload == 0) + if (toDownload > 0) { + toDownload -= 1; + qDebug() << "Download: toDownload" << toDownload; + } + + if (toDownload == 0) { + Application *app = qobject_cast(qApp); + MainWindow *mainWindow = app->mainWindow(); + if (mainWindow->isCloseWindowAnimation() == true) { - Application *app = qobject_cast(qApp); - MainWindow *mainWindow = app->mainWindow(); - if (mainWindow->isCloseWindowAnimation() == true) - { - qDebug() << "Download: 后台安装结束,退出程序"; - qApp->quit(); - } + qDebug() << "Download: 后台安装结束,退出程序"; + qApp->quit(); } } } diff --git a/translations/spark-store_en.ts b/translations/spark-store_en.ts index e13a3b6..d031691 100644 --- a/translations/spark-store_en.ts +++ b/translations/spark-store_en.ts @@ -268,16 +268,24 @@ DAboutDialog - + Version: %1 - + %1 is released under %2 + + DownloadController + + + Download Failed, please retry :( + + + DownloadItem @@ -506,19 +514,19 @@ QObject - - + + Spark Store - + <span style=' font-size:10pt;font-weight:60;'>An appstore powered by community</span><br/><a href='https://www.spark-app.store/'>https://www.spark-app.store</a><br/><span style=' font-size:12pt;'>Spark developers</span> - + Spark Project diff --git a/translations/spark-store_fr.ts b/translations/spark-store_fr.ts index 50f58ff..5e574ff 100644 --- a/translations/spark-store_fr.ts +++ b/translations/spark-store_fr.ts @@ -268,16 +268,24 @@ DAboutDialog - + Version: %1 Version: %1 - + %1 is released under %2 %1 publié sous %2 + + DownloadController + + + Download Failed, please retry :( + + + DownloadItem @@ -506,19 +514,19 @@ QObject - - + + Spark Store Le Spark store - + <span style=' font-size:10pt;font-weight:60;'>An appstore powered by community</span><br/><a href='https://www.spark-app.store/'>https://www.spark-app.store</a><br/><span style=' font-size:12pt;'>Spark developers</span> <span style=' font-size:10pt;font-weight:60;'>An appstore powered by community</span><br/><a href='https://www.spark-app.store/'>https://www.spark-app.store</a><br/><span style=' font-size:12pt;'>Spark developers</span> - + Spark Project Le projet Spark diff --git a/translations/spark-store_zh_CN.ts b/translations/spark-store_zh_CN.ts index 48c412f..78c024e 100644 --- a/translations/spark-store_zh_CN.ts +++ b/translations/spark-store_zh_CN.ts @@ -268,16 +268,24 @@ DAboutDialog - + Version: %1 版本:%1 - + %1 is released under %2 %1遵循%2协议发布 + + DownloadController + + + Download Failed, please retry :( + + + DownloadItem @@ -506,19 +514,19 @@ QObject - - + + Spark Store 星火应用商店 - + <span style=' font-size:10pt;font-weight:60;'>An appstore powered by community</span><br/><a href='https://www.spark-app.store/'>https://www.spark-app.store</a><br/><span style=' font-size:12pt;'>Spark developers</span> <span style=' font-size:10pt;font-weight:60;'>一款由社区提供的应用商店</span><br/><a href='https://www.spark-app.store/'>https://www.spark-app.store</a><br/><span style=' font-size:12pt;'>星火计划开发者</span> - + Spark Project 星火计划 diff --git a/translations/spark-store_zh_TW.ts b/translations/spark-store_zh_TW.ts index 417b8e8..d4f2af1 100644 --- a/translations/spark-store_zh_TW.ts +++ b/translations/spark-store_zh_TW.ts @@ -268,16 +268,24 @@ DAboutDialog - + Version: %1 版本:%1 - + %1 is released under %2 %1遵循%2协议发布 + + DownloadController + + + Download Failed, please retry :( + + + DownloadItem @@ -506,19 +514,19 @@ QObject - - + + Spark Store 星火应用商店 - + <span style=' font-size:10pt;font-weight:60;'>An appstore powered by community</span><br/><a href='https://www.spark-app.store/'>https://www.spark-app.store</a><br/><span style=' font-size:12pt;'>Spark developers</span> <span style=' font-size:10pt;font-weight:60;'>一款由社区提供的应用商店</span><br/><a href='https://www.spark-app.store/'>https://www.spark-app.store</a><br/><span style=' font-size:12pt;'>星火计划开发者</span> - + Spark Project 星火计划