From dd4dd0e66b8528a65a20abd1d60fedaa7c3e80a7 Mon Sep 17 00:00:00 2001 From: uniartisan Date: Thu, 22 Dec 2022 21:50:27 +0800 Subject: [PATCH 01/17] feat: support wayland --- README.en.md | 2 +- README.md | 2 +- src/main.cpp | 29 +++++++++++++++++++++++++---- 3 files changed, 27 insertions(+), 6 deletions(-) diff --git a/README.en.md b/README.en.md index f08b8c1d..60facca8 100644 --- a/README.en.md +++ b/README.en.md @@ -36,7 +36,7 @@ If you are using Debian11/Ubuntu 20.04, you will need extra dependency package. For Deepin V20/UOS 21/ Debian 11 ```shell -sudo apt install git qt5-default debhelper pkg-config qtchooser libqt5core5a libqt5gui5 libqt5widgets5 libqt5network5 libqt5concurrent5 libdtkcore-dev libdtkgui-dev libdtkwidget-dev qttools5-private-dev libnotify-dev qtwebengine5-dev fakeroot qtwayland5 qtwayland5-dev-tools +sudo apt install git qt5-default debhelper pkg-config qtchooser libqt5core5a libqt5gui5 libqt5widgets5 libqt5network5 libqt5concurrent5 libdtkcore-dev libdtkgui-dev libdtkwidget-dev qttools5-private-dev libnotify-dev qtwebengine5-dev fakeroot qtwayland5 qtwayland5-dev-tools dde-qt5wayland-plugin ``` diff --git a/README.md b/README.md index c7ef95eb..b9022b3b 100644 --- a/README.md +++ b/README.md @@ -34,7 +34,7 @@ Deepin V20/UOS 21 系统下, 安装依赖 ```shell -sudo apt install git qt5-default debhelper pkg-config qtchooser libqt5core5a libqt5gui5 libqt5widgets5 libqt5network5 libqt5concurrent5 libdtkcore-dev libdtkgui-dev libdtkwidget-dev qttools5-private-dev libnotify-dev qtwebengine5-dev fakeroot qtwayland5 qtwayland5-dev-tools +sudo apt install git qt5-default debhelper pkg-config qtchooser libqt5core5a libqt5gui5 libqt5widgets5 libqt5network5 libqt5concurrent5 libdtkcore-dev libdtkgui-dev libdtkwidget-dev qttools5-private-dev libnotify-dev qtwebengine5-dev fakeroot qtwayland5 qtwayland5-dev-tools dde-qt5wayland-plugin ``` diff --git a/src/main.cpp b/src/main.cpp index 465d0447..123f451f 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -7,6 +7,8 @@ #include #include #include +#include + DCORE_USE_NAMESPACE DWIDGET_USE_NAMESPACE @@ -21,10 +23,28 @@ int main(int argc, char *argv[]) if (!QString(qgetenv("XDG_CURRENT_DESKTOP")).toLower().startsWith("deepin")) { setenv("XDG_CURRENT_DESKTOP", "Deepin", 1); } + bool isWayland = false; + auto e = QProcessEnvironment::systemEnvironment(); + QString XDG_SESSION_TYPE = e.value(QStringLiteral("XDG_SESSION_TYPE")); + QString WAYLAND_DISPLAY = e.value(QStringLiteral("WAYLAND_DISPLAY")); + if (XDG_SESSION_TYPE == QLatin1String("wayland") || WAYLAND_DISPLAY.contains(QLatin1String("wayland"), Qt::CaseInsensitive)){ + isWayland = true; + } + qDebug() << "Wayland enabled:" << isWayland; + + if(isWayland && !Dtk::Core::DSysInfo::isDDE()){ + qputenv("QT_QPA_PLATFORM", "wayland"); + + } + else if (isWayland && Dtk::Core::DSysInfo::isDDE()){ + qputenv("QT_QPA_PLATFORM", "dwayland"); + } + else { + qputenv("QT_QPA_PLATFORM", "dxcb"); + } DApplication::setAttribute(Qt::AA_EnableHighDpiScaling); // 开启 Hidpi 支持 -#ifndef DSTORE_NO_DXCBs - DApplication::loadDXcbPlugin(); // 加载 DXCB 插件 -#endif + + // 浏览器开启 GPU 支持 qputenv("QTWEBENGINE_CHROMIUM_FLAGS", "--ignore-gpu-blocklist --enable-gpu-rasterization --enable-native-gpu-memory-buffers --enable-accelerated-video-decode"); @@ -48,7 +68,7 @@ int main(int argc, char *argv[]) a.setAttribute(Qt::AA_DontCreateNativeWidgetSiblings, true); } a.setAttribute(Qt::AA_UseHighDpiPixmaps); - a.loadDXcbPlugin(); + a.setApplicationDisplayName("Spark Store"); a.loadTranslator(); // 载入翻译 @@ -125,6 +145,7 @@ int main(int argc, char *argv[]) w.openUrl(QUrl(argv[1])); } w.show(); + w.setWindowTitle("Spark Store"); return a.exec(); } -- Gitee From 0a13a3cf141be27ca385c52c975b7ca693c7b3bb Mon Sep 17 00:00:00 2001 From: uniartisan Date: Fri, 23 Dec 2022 12:13:48 +0800 Subject: [PATCH 02/17] =?UTF-8?q?format:=20=E4=BB=A3=E7=A0=81=E6=A0=BC?= =?UTF-8?q?=E5=BC=8F=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/backend/downloadworker.cpp | 1 - src/backend/image_show.cpp | 13 +- src/backend/sparkapi.cpp | 30 ++-- src/dbus/dbussparkstoreservice.cpp | 3 +- src/main.cpp | 107 +++++++------- src/mainwindow-dtk.cpp | 185 ++++++++++++------------ src/pages/appintopage.cpp | 124 ++++++++-------- src/pages/applistpage.cpp | 86 ++++++----- src/pages/settingspage.cpp | 79 +++++----- src/utils/httprequest.cpp | 19 +-- src/utils/utils.cpp | 7 +- src/utils/widgetanimation.cpp | 30 ++-- src/widgets/base/basewidgetopacity.cpp | 23 +-- src/widgets/big_image.cpp | 7 +- src/widgets/common/downloaditem.cpp | 26 ++-- src/widgets/common/progressbutton.cpp | 75 +++++----- src/widgets/common/smoothlistwidget.cpp | 8 +- src/widgets/common/smoothscrollbar.cpp | 38 ++--- src/widgets/common/webenginepage.cpp | 6 +- src/widgets/downloadlistwidget.cpp | 79 +++++----- 20 files changed, 475 insertions(+), 471 deletions(-) diff --git a/src/backend/downloadworker.cpp b/src/backend/downloadworker.cpp index 1d14f27f..0895d430 100644 --- a/src/backend/downloadworker.cpp +++ b/src/backend/downloadworker.cpp @@ -30,7 +30,6 @@ void DownloadController::setFilename(QString filename) this->filename = filename; } - bool checkMeatlink(QString metaUrl) { QFile metaStatus("/tmp/spark-store/metaStatus.txt"); diff --git a/src/backend/image_show.cpp b/src/backend/image_show.cpp index f67b3403..f817a49d 100644 --- a/src/backend/image_show.cpp +++ b/src/backend/image_show.cpp @@ -1,13 +1,12 @@ #include "image_show.h" #include -#include // Qt5 不再建议使用 QDesktopWidget +#include // Qt5 不再建议使用 QDesktopWidget #include -image_show::image_show(QWidget *parent) : - QWidget(parent), - m_dialog(new big_image), - m_label(new QLabel) +image_show::image_show(QWidget *parent) : QWidget(parent), + m_dialog(new big_image), + m_label(new QLabel) { QHBoxLayout *layout = new QHBoxLayout; layout->addWidget(m_label); @@ -27,7 +26,7 @@ void image_show::setImage(QPixmap image) desktop_w = QGuiApplication::primaryScreen()->geometry().width(); desktop_h = QGuiApplication::primaryScreen()->geometry().height(); - if(screen0.width() > (desktop_w - 20) || screen0.height() > (desktop_h - 20)) + if (screen0.width() > (desktop_w - 20) || screen0.height() > (desktop_h - 20)) { re_screen1 = screen0.scaled(QSize(desktop_w - 20, desktop_h - 20), Qt::KeepAspectRatio, Qt::SmoothTransformation); m_image = QPixmap::fromImage(re_screen1); @@ -48,7 +47,7 @@ void image_show::mousePressEvent(QMouseEvent *) // 识别主屏幕尺寸并设置 widget 大小 m_dialog->setFixedSize(desktop_w, desktop_h); - m_dialog->move(0,0); + m_dialog->move(0, 0); } image_show::~image_show() { diff --git a/src/backend/sparkapi.cpp b/src/backend/sparkapi.cpp index 70c1983c..8a2a4f5f 100644 --- a/src/backend/sparkapi.cpp +++ b/src/backend/sparkapi.cpp @@ -7,7 +7,7 @@ QString SparkAPI::serverUrl = ""; SparkAPI::SparkAPI(QObject *parent) : QObject(parent) { QSettings readConfig(QDir::homePath() + "/.config/spark-store/config.ini", QSettings::IniFormat); - if(!readConfig.value("server/choose").toString().isEmpty() && readConfig.value("server/updated").toString() == "TRUE") + if (!readConfig.value("server/choose").toString().isEmpty() && readConfig.value("server/updated").toString() == "TRUE") { SparkAPI::setServerUrl(readConfig.value("server/choose").toString()); } @@ -15,9 +15,10 @@ SparkAPI::SparkAPI(QObject *parent) : QObject(parent) void SparkAPI::get(QUrl url) { QNetworkRequest request; - HttpRequest *httprequest=new HttpRequest; - request.setUrl(QUrl(url.toString().replace("+","%2B"))); - connect(httprequest,&HttpRequest::finished,[=](QString data){ + HttpRequest *httprequest = new HttpRequest; + request.setUrl(QUrl(url.toString().replace("+", "%2B"))); + connect(httprequest, &HttpRequest::finished, [=](QString data) + { QByteArray arr = data.toUtf8(); //解析Json QJsonParseError error; @@ -30,36 +31,35 @@ void SparkAPI::get(QUrl url) emit finishedObject(doc); } - httprequest->deleteLater(); - }); + httprequest->deleteLater(); }); httprequest->getRequest(request); } void SparkAPI::getRAW(QUrl url) { QNetworkRequest request; - HttpRequest *httprequest=new HttpRequest; - request.setUrl(QUrl(url.toString().replace("+","%2B"))); - connect(httprequest,&HttpRequest::finished,[=](QString data){ + HttpRequest *httprequest = new HttpRequest; + request.setUrl(QUrl(url.toString().replace("+", "%2B"))); + connect(httprequest, &HttpRequest::finished, [=](QString data) + { emit finishedRAW(data); - httprequest->deleteLater(); - }); + httprequest->deleteLater(); }); httprequest->getRequest(request); } void SparkAPI::getAppList(QString type) { - get(QUrl(getServerUrl()+"store/"+type+"/applist.json")); + get(QUrl(getServerUrl() + "store/" + type + "/applist.json")); } void SparkAPI::getSearchList(QString keyword) { - get(QUrl("https://search.deepinos.org.cn/appinfo/search?keyword="+keyword)); + get(QUrl("https://search.deepinos.org.cn/appinfo/search?keyword=" + keyword)); } void SparkAPI::getAppInfo(QUrl spk) { - get(QUrl(getServerUrl()+"store"+spk.path().replace("+","%2B") + "/app.json")); + get(QUrl(getServerUrl() + "store" + spk.path().replace("+", "%2B") + "/app.json")); } void SparkAPI::getAppDownloadTimes(QUrl spk) { - getRAW(QUrl(getServerUrl()+"store"+spk.path().replace("+","%2B") + "/download-times.txt")); + getRAW(QUrl(getServerUrl() + "store" + spk.path().replace("+", "%2B") + "/download-times.txt")); } QString SparkAPI::getServerUrl() { diff --git a/src/dbus/dbussparkstoreservice.cpp b/src/dbus/dbussparkstoreservice.cpp index 9fcd6736..aaa4bb39 100644 --- a/src/dbus/dbussparkstoreservice.cpp +++ b/src/dbus/dbussparkstoreservice.cpp @@ -3,10 +3,9 @@ DBusSparkStoreService::DBusSparkStoreService(QObject *parent) : QDBusAbstractAdaptor(parent) { - } -void DBusSparkStoreService::activeWindow(const QString & arg) +void DBusSparkStoreService::activeWindow(const QString &arg) { emit sigOpenUrl(arg); } diff --git a/src/main.cpp b/src/main.cpp index 123f451f..8e053a97 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -16,55 +16,57 @@ int main(int argc, char *argv[]) { // Get build time static const QString version = "Version 4.1.1"; - static const QDate buildDate = QLocale( QLocale::English ).toDate( QString(__DATE__).replace(" ", " 0"), "MMM dd yyyy"); + 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"); - //设置桌面环境环境变量 - if (!QString(qgetenv("XDG_CURRENT_DESKTOP")).toLower().startsWith("deepin")) { + // 设置桌面环境环境变量 + if (!QString(qgetenv("XDG_CURRENT_DESKTOP")).toLower().startsWith("deepin")) + { setenv("XDG_CURRENT_DESKTOP", "Deepin", 1); } bool isWayland = false; auto e = QProcessEnvironment::systemEnvironment(); QString XDG_SESSION_TYPE = e.value(QStringLiteral("XDG_SESSION_TYPE")); QString WAYLAND_DISPLAY = e.value(QStringLiteral("WAYLAND_DISPLAY")); - if (XDG_SESSION_TYPE == QLatin1String("wayland") || WAYLAND_DISPLAY.contains(QLatin1String("wayland"), Qt::CaseInsensitive)){ + if (XDG_SESSION_TYPE == QLatin1String("wayland") || WAYLAND_DISPLAY.contains(QLatin1String("wayland"), Qt::CaseInsensitive)) + { isWayland = true; } qDebug() << "Wayland enabled:" << isWayland; - if(isWayland && !Dtk::Core::DSysInfo::isDDE()){ + if (isWayland && !Dtk::Core::DSysInfo::isDDE()) + { qputenv("QT_QPA_PLATFORM", "wayland"); - } - else if (isWayland && Dtk::Core::DSysInfo::isDDE()){ + else if (isWayland && Dtk::Core::DSysInfo::isDDE()) + { qputenv("QT_QPA_PLATFORM", "dwayland"); } - else { + else + { qputenv("QT_QPA_PLATFORM", "dxcb"); } DApplication::setAttribute(Qt::AA_EnableHighDpiScaling); // 开启 Hidpi 支持 - - // 浏览器开启 GPU 支持 qputenv("QTWEBENGINE_CHROMIUM_FLAGS", "--ignore-gpu-blocklist --enable-gpu-rasterization --enable-native-gpu-memory-buffers --enable-accelerated-video-decode"); - QVector fakeArgs(argc + 2); + QVector fakeArgs(argc + 2); fakeArgs[0] = argv[0]; fakeArgs[1] = "-platformtheme"; fakeArgs[2] = "deepin"; - for(int i = 1; i < argc; i++) fakeArgs[i + 2] = argv[i]; - int fakeArgc = argc + 2; // 为啥DApplication的argc要用引用啊? + for (int i = 1; i < argc; i++) + fakeArgs[i + 2] = argv[i]; + int fakeArgc = argc + 2; // DApplication的argc要用引用,避免c++编译器优化 DApplication a(fakeArgc, fakeArgs.data()); - - //初始化日志模块 (默认日志位置 ~/.cache/deepin/spark-store) + // 初始化日志模块 (默认日志位置 ~/.cache/deepin/spark-store) DLogManager::registerConsoleAppender(); DLogManager::registerFileAppender(); - - //Wayland 环境下使用,防止子控件 Native 化 - if (!DPlatformWindowHandle::pluginVersion().isEmpty()) { + // Wayland 环境下使用,防止子控件 Native 化 + if (!DPlatformWindowHandle::pluginVersion().isEmpty()) + { a.setAttribute(Qt::AA_DontCreateNativeWidgetSiblings, true); } a.setAttribute(Qt::AA_UseHighDpiPixmaps); @@ -74,50 +76,47 @@ int main(int argc, char *argv[]) QSettings readConfig(QDir::homePath() + "/.config/spark-store/config.ini", QSettings::IniFormat); - if (readConfig.value("build/version").toString() != version){ + if (readConfig.value("build/version").toString() != version) + { qDebug() << "Spark Store has been updated!"; QSettings *setConfig = new QSettings(QDir::homePath() + "/.config/spark-store/config.ini", QSettings::IniFormat); setConfig->setValue("build/version", version); - setConfig->setValue("build/time", buildDate.toString("yyyy.MM.dd")+"-"+buildTime.toString()); + setConfig->setValue("build/time", buildDate.toString("yyyy.MM.dd") + "-" + buildTime.toString()); setConfig->deleteLater(); } - //Customized DAboutDialog - - DAboutDialog dialog; - a.setAboutDialog(&dialog); - dialog.setLicense(QObject::tr("We publish this program under GPL V3")); - dialog.setVersion(DApplication::buildVersion(readConfig.value("build/version").toString()+"-"+"Flamescion"+"-"+readConfig.value("build/time").toString())); - dialog.setProductIcon(QIcon::fromTheme("spark-store")); // 设置Logo - dialog.setProductName(QLabel::tr("Spark Store")); - dialog.setDescription( - QObject::tr( - "An appstore powered by community
" - "https://www.spark-app.store
" - "Spark developers" - ) - ); - - dialog.setProductName(QLabel::tr("Spark Store")); - dialog.setCompanyLogo(QPixmap(":/spark-store.png")); - dialog.setWebsiteName(QObject::tr("The Spark Project")); - dialog.setWebsiteLink("https://gitee.com/deepin-community-store"); + // Customized DAboutDialog + + DAboutDialog dialog; + a.setAboutDialog(&dialog); + dialog.setLicense(QObject::tr("We publish this program under GPL V3")); + dialog.setVersion(DApplication::buildVersion(readConfig.value("build/version").toString() + "-" + "Flamescion" + "-" + readConfig.value("build/time").toString())); + dialog.setProductIcon(QIcon::fromTheme("spark-store")); // 设置Logo + dialog.setProductName(QLabel::tr("Spark Store")); + dialog.setDescription( + QObject::tr( + "An appstore powered by community
" + "https://www.spark-app.store
" + "Spark developers")); + + dialog.setProductName(QLabel::tr("Spark Store")); + dialog.setCompanyLogo(QPixmap(":/spark-store.png")); + dialog.setWebsiteName(QObject::tr("The Spark Project")); + dialog.setWebsiteLink("https://gitee.com/deepin-community-store"); a.setOrganizationName("spark-union"); a.setProductName(QObject::tr("Spark Store")); - a.setApplicationName("Spark Store"); // 不用翻译,影响 ~/.local/share/spark-union 下文件夹名称 + a.setApplicationName("Spark Store"); // 不用翻译,影响 ~/.local/share/spark-union 下文件夹名称 a.setApplicationDisplayName(QObject::tr("Spark Store")); // 设置窗口显示标题 (Wayland 下会显示 Qt 原生标题栏) a.setWindowIcon(QIcon::fromTheme("spark-store")); a.setApplicationDescription( - QObject::tr( - "An appstore powered by deepin community
" - "https://www.spark-app.store
" - "Spark developers

" - "Published under GPL V3" - ) - ); + QObject::tr( + "An appstore powered by deepin community
" + "https://www.spark-app.store
" + "Spark developers

" + "Published under GPL V3")); // 限制单实例运行 - if(!a.setSingleInstance("spark-store")) + if (!a.setSingleInstance("spark-store")) { qDebug() << "The application is already running!"; QDBusInterface iface("com.gitee.spark.store", @@ -127,21 +126,21 @@ int main(int argc, char *argv[]) QString arg1 = argv[1]; - iface.asyncCall("activeWindow",arg1); - + iface.asyncCall("activeWindow", arg1); return -1; } - DGuiApplicationHelper::instance()->setPaletteType(DGuiApplicationHelper::LightType); //固定主题为浅色主题 - DApplicationSettings settings; // 定义 DApplicationSettings,自动保存主题设置 + DGuiApplicationHelper::instance()->setPaletteType(DGuiApplicationHelper::LightType); // 固定主题为浅色主题 + DApplicationSettings settings; // 定义 DApplicationSettings,自动保存主题设置 MainWindow w; // 让打开时界面显示在正中 Dtk::Widget::moveToCenter(&w); QString arg1 = argv[1]; - if (arg1.startsWith("spk://")) { + if (arg1.startsWith("spk://")) + { w.openUrl(QUrl(argv[1])); } w.show(); diff --git a/src/mainwindow-dtk.cpp b/src/mainwindow-dtk.cpp index 3e516395..6c47115a 100644 --- a/src/mainwindow-dtk.cpp +++ b/src/mainwindow-dtk.cpp @@ -11,14 +11,13 @@ #define AppPageSettings 3 MainWindow::MainWindow(QWidget *parent) - : BaseWidgetOpacity(parent) - , ui(new Ui::MainWindow) + : BaseWidgetOpacity(parent), ui(new Ui::MainWindow) { ui->setupUi(this); initConfig(); - moveToCenter(this); //让窗口居中显示 + moveToCenter(this); // 让窗口居中显示 - WidgetAnimation::widgetOpacity(this,true); + WidgetAnimation::widgetOpacity(this, true); downloadlistwidget = new DownloadListWidget; downloadButton = new ProgressButton(ui->titlebar); @@ -26,7 +25,7 @@ MainWindow::MainWindow(QWidget *parent) ui->appintopage->setDownloadWidget(downloadlistwidget); ui->stackedWidget->setCurrentIndex(0); ui->titlebar->setBackgroundTransparent(true); - //ui->titlebar->setSwitchThemeMenuVisible(false); // 去除 dtk 标题栏主题切换菜单 + // ui->titlebar->setSwitchThemeMenuVisible(false); // 去除 dtk 标题栏主题切换菜单 setMaskAlpha(250); updateUi(0); @@ -42,32 +41,34 @@ MainWindow::MainWindow(QWidget *parent) menu->addAction(actionSubmissionWithClient); ui->titlebar->setMenu(menu); - connect(actionSubmission, &QAction::triggered, this, [=]{QDesktopServices::openUrl(QUrl("https://upload.deepinos.org/"));}); - connect(setting, &QAction::triggered, this, [=]{ + connect(actionSubmission, &QAction::triggered, this, [=] + { QDesktopServices::openUrl(QUrl("https://upload.deepinos.org/")); }); + connect(setting, &QAction::triggered, this, [=] + { switchPage(AppPageSettings); - ui->settingspage->updateUI(); - }); - connect(upgrade, &QAction::triggered, this, [=]{QProcess::startDetached("/opt/durapps/spark-store/bin/update-upgrade/ss-update-controler.sh");}); + ui->settingspage->updateUI(); }); + connect(upgrade, &QAction::triggered, this, [=] + { QProcess::startDetached("/opt/durapps/spark-store/bin/update-upgrade/ss-update-controler.sh"); }); // 投稿器 connect(actionSubmissionWithClient, &QAction::triggered, this, [=] - { - QString submitterSpk = "spk://store/tools/spark-store-submitter"; - QFile actionSubmissionClientStatus("/opt/spark-store-submitter/bin/spark-store-submitter"); - if (actionSubmissionClientStatus.exists()) { - qDebug() << "投稿器存在"; - QProcess::startDetached("/opt/spark-store-submitter/bin/spark-store-submitter"); - } - else{ - qDebug() << "投稿器不存在,跳转页面"; - openUrl(submitterSpk); - } - - }); - + QString submitterSpk = "spk://store/tools/spark-store-submitter"; + QFile actionSubmissionClientStatus("/opt/spark-store-submitter/bin/spark-store-submitter"); + if (actionSubmissionClientStatus.exists()) + { + qDebug() << "投稿器存在"; + QProcess::startDetached("/opt/spark-store-submitter/bin/spark-store-submitter"); + } + else + { + qDebug() << "投稿器不存在,跳转页面"; + openUrl(submitterSpk); + } + }); - //主题切换 - connect(DGuiApplicationHelper::instance(), &DGuiApplicationHelper::themeTypeChanged, this, [=](DGuiApplicationHelper::ColorType themeType) { + // 主题切换 + connect(DGuiApplicationHelper::instance(), &DGuiApplicationHelper::themeTypeChanged, this, [=](DGuiApplicationHelper::ColorType themeType) + { if (themeType == DGuiApplicationHelper::DarkType) { //深色模式 setMaskColor(QColor("#2a2b2b")); @@ -123,32 +124,32 @@ MainWindow::MainWindow(QWidget *parent) ui->applistpage->setTheme(themeType == DGuiApplicationHelper::DarkType); ui->applistpage_1->setTheme(themeType == DGuiApplicationHelper::DarkType); ui->appintopage->setTheme(themeType == DGuiApplicationHelper::DarkType); - ui->settingspage->setTheme(themeType == DGuiApplicationHelper::DarkType); - }); + ui->settingspage->setTheme(themeType == DGuiApplicationHelper::DarkType); }); - //初始化标题栏控件 - connect(downloadButton, &ProgressButton::clicked, [=]() { + // 初始化标题栏控件 + connect(downloadButton, &ProgressButton::clicked, [=]() + { QPoint pos; pos.setX(downloadButton->mapToGlobal(QPoint(0, 0)).x() + downloadButton->width() / 2 - downloadlistwidget->width() / 2); pos.setY(downloadButton->mapToGlobal(QPoint(0, 0)).y() + downloadButton->height() + 5); downloadlistwidget->m_move(pos.x(), pos.y()); - downloadlistwidget->show(); - }); + downloadlistwidget->show(); }); - //appintopage按下下载按钮时标题栏下载列表按钮抖动 - connect(ui->appintopage, &AppIntoPage::clickedDownloadBtn, [=]() { - WidgetAnimation::widgetShake(downloadButton,6);//第一个参数是抖动的控件,第二个参数是抖动范围(像素) - }); + // appintopage按下下载按钮时标题栏下载列表按钮抖动 + connect(ui->appintopage, &AppIntoPage::clickedDownloadBtn, [=]() + { + WidgetAnimation::widgetShake(downloadButton, 6); // 第一个参数是抖动的控件,第二个参数是抖动范围(像素) + }); - connect(backButtom, &QPushButton::clicked, [=]() { + connect(backButtom, &QPushButton::clicked, [=]() + { ui->stackedWidget->setCurrentIndex(pageHistory.at(pageHistory.count() - 2)); pageHistory.removeLast(); if (pageHistory.count() > 1) { backButtom->show(); } else { backButtom->hide(); - } - }); + } }); downloadlistwidget->hide(); backButtom->hide(); ui->titlebar->setIcon(QIcon::fromTheme(":/icon/logo.svg")); @@ -164,21 +165,23 @@ MainWindow::MainWindow(QWidget *parent) ly_titlebar->addWidget(downloadButton); ly_titlebar->addStretch(1); ui->titlebar->setCustomWidget(w_titlebar); - //侧边栏按钮 + // 侧边栏按钮 int i = 0; - while (i < ui->buttonGroup->buttons().size()) { + while (i < ui->buttonGroup->buttons().size()) + { ui->buttonGroup->buttons()[i]->setStyleSheet("QPushButton{qproperty-icon: url(data/images/userMangaer/teacher.png);}"); - connect(ui->buttonGroup->buttons()[i], &QPushButton::toggled, [=](bool checked) { + connect(ui->buttonGroup->buttons()[i], &QPushButton::toggled, [=](bool checked) + { if (checked == true) { searchEdit->clearEdit(); updateUi(i); - } - }); + } }); i++; } // 搜索事件 - connect(searchEdit, &DSearchEdit::returnPressed, this, [=]() { + connect(searchEdit, &DSearchEdit::returnPressed, this, [=]() + { QString searchtext = searchEdit->text(); if (!searchtext.isEmpty()) { if (searchtext.startsWith("spk://")) { @@ -189,22 +192,17 @@ MainWindow::MainWindow(QWidget *parent) switchPage(AppPageSearchlist); } } - this->setFocus(); - }); + this->setFocus(); }); - connect(downloadlistwidget, &DownloadListWidget::downloadProgress, this, [=](int i) { - downloadButton->setProgress(i); - }); + connect(downloadlistwidget, &DownloadListWidget::downloadProgress, this, [=](int i) + { downloadButton->setProgress(i); }); // 列表点击事件 - connect(ui->applistpage, &AppListPage::clicked, this, [=](QUrl spk) { - openUrl(spk); - }); - connect(ui->applistpage_1, &AppListPage::clicked, this, [=](QUrl spk) { - openUrl(spk); - }); - connect(ui->settingspage, &SettingsPage::openUrl, this, [=](QUrl spk) { - openUrl(spk); - }); + connect(ui->applistpage, &AppListPage::clicked, this, [=](QUrl spk) + { openUrl(spk); }); + connect(ui->applistpage_1, &AppListPage::clicked, this, [=](QUrl spk) + { openUrl(spk); }); + connect(ui->settingspage, &SettingsPage::openUrl, this, [=](QUrl spk) + { openUrl(spk); }); emit DGuiApplicationHelper::instance()->themeTypeChanged(DGuiApplicationHelper::instance()->themeType()); initDbus(); @@ -223,12 +221,12 @@ void MainWindow::initDbus() QDBusConnection::sessionBus().registerService("com.gitee.spark.store"); QDBusConnection::sessionBus().registerObject("/com/gitee/spark/store", "com.gitee.spark.store", this); - connect(dbusInter,&DBusSparkStoreService::sigOpenUrl,this,&MainWindow::onGetUrl); + connect(dbusInter, &DBusSparkStoreService::sigOpenUrl, this, &MainWindow::onGetUrl); } void MainWindow::onGetUrl(const QString &url) { - if(url.left(6)=="spk://") + if (url.left(6) == "spk://") { openUrl(QUrl(url)); } @@ -237,11 +235,14 @@ void MainWindow::onGetUrl(const QString &url) void MainWindow::openUrl(QUrl url) { - if (url.toString().startsWith("spk://")) { - ui->appintopage->openUrl(QUrl(url.toString().replace("+","%2B"))); + if (url.toString().startsWith("spk://")) + { + ui->appintopage->openUrl(QUrl(url.toString().replace("+", "%2B"))); switchPage(AppPageAppdetail); - } else { - QDesktopServices::openUrl(QUrl(url.toString().replace("+","%2B"))); + } + else + { + QDesktopServices::openUrl(QUrl(url.toString().replace("+", "%2B"))); } } @@ -252,50 +253,54 @@ void MainWindow::initConfig() dir.mkpath("/tmp/spark-store"); } -void MainWindow::switchPage(int now) //临时方案,回家后修改 +void MainWindow::switchPage(int now) // 临时方案,回家后修改 { qDebug() << pageHistory.count(); - if (pageHistory.count() >= 1) { + if (pageHistory.count() >= 1) + { backButtom->show(); - } else { + } + else + { backButtom->hide(); } ui->stackedWidget->setCurrentIndex(now); pageHistory << now; } -//刷新界面 +// 刷新界面 void MainWindow::updateUi(int now) { pageHistory.clear(); - QStringList itemlist; - itemlist << "" - << "network" - << "chat" - << "music" - << "video" - << "image_graphics" - << "games" - << "office" - << "reading" - << "development" - << "tools" - << "themes" - << "others"; - ui->applistpage->getAppList(itemlist[now]); - qDebug() << itemlist[now]; - switchPage(AppPageApplist); + QStringList itemlist; + itemlist << "" + << "network" + << "chat" + << "music" + << "video" + << "image_graphics" + << "games" + << "office" + << "reading" + << "development" + << "tools" + << "themes" + << "others"; + ui->applistpage->getAppList(itemlist[now]); + qDebug() << itemlist[now]; + switchPage(AppPageApplist); } void MainWindow::on_pushButton_14_clicked() { QFile upgradeStatus("/tmp/spark-store/upgradeStatus.txt"); - if (!upgradeStatus.exists()){ - QtConcurrent::run([=]{ + if (!upgradeStatus.exists()) + { + QtConcurrent::run([=] + { auto upgradeP = new QProcess(); upgradeP->startDetached("/opt/durapps/spark-store/bin/update-upgrade/ss-do-upgrade.sh"); upgradeP->waitForStarted(); - upgradeP->waitForFinished(-1); - }); + upgradeP->waitForFinished(-1); }); } } diff --git a/src/pages/appintopage.cpp b/src/pages/appintopage.cpp index eebf9532..6d4e0752 100644 --- a/src/pages/appintopage.cpp +++ b/src/pages/appintopage.cpp @@ -1,20 +1,19 @@ #include "appintopage.h" #include "ui_appintopage.h" -AppIntoPage::AppIntoPage(QWidget *parent) : - QWidget(parent), - ui(new Ui::AppIntoPage) +AppIntoPage::AppIntoPage(QWidget *parent) : QWidget(parent), + ui(new Ui::AppIntoPage) { ui->setupUi(this); ui->listWidget->setViewMode(QListView::IconMode); ui->listWidget->setMovement(QListView::Static); ui->listWidget->setMaximumHeight(200); ui->listWidget->setFlow(QListView::TopToBottom); - api1=new SparkAPI(this); - connect(api1,&SparkAPI::finishedRAW,[=](QString download_times){ + api1 = new SparkAPI(this); + connect(api1, &SparkAPI::finishedRAW, [=](QString download_times) + { download_times.remove(QRegExp("\\n")); ui->download_times->setText(download_times); - qDebug()<<"Download Times:"+download_times; - }); + qDebug()<<"Download Times:"+download_times; }); clear(); } @@ -35,31 +34,31 @@ void AppIntoPage::clear() ui->downloadButton->hide(); ui->downloadButton->setEnabled(true); ui->pushButton_3->hide(); - int n=ui->listWidget->count(); - for(int i=0;ilistWidget->count(); + for (int i = 0; i < n; i++) { QListWidgetItem *item = ui->listWidget->takeItem(0); QWidget *card = ui->listWidget->itemWidget(item); delete card; - card = NULL; + card = NULL; delete item; - item = NULL; + item = NULL; } ui->listWidget->clear(); } void AppIntoPage::setDownloadWidget(DownloadListWidget *w) { - dw=w; - connect(w, &DownloadListWidget::downloadFinished, [=]() { - isDownloading(SparkAPI::getServerUrl()+"store"+spk.path()+"/"+info["Filename"].toString()); - }); + dw = w; + connect(w, &DownloadListWidget::downloadFinished, [=]() + { isDownloading(SparkAPI::getServerUrl() + "store" + spk.path() + "/" + info["Filename"].toString()); }); } void AppIntoPage::openUrl(QUrl url) { - spk=url; - SparkAPI *api=new SparkAPI(this); + spk = url; + SparkAPI *api = new SparkAPI(this); clear(); - connect(api,&SparkAPI::finishedObject,[=](QJsonObject appinfo){ + connect(api, &SparkAPI::finishedObject, [=](QJsonObject appinfo) + { info = appinfo; // qDebug()<sltAppinfoTags(&taglist); disconnect(api,&SparkAPI::finished,nullptr,nullptr); - api->deleteLater(); - }); + api->deleteLater(); }); api->getAppInfo(url); api1->getAppDownloadTimes(url); } void AppIntoPage::isDownloading(QUrl url) { - if (dw->getUrlList().lastIndexOf(url) == -1) { + if (dw->getUrlList().lastIndexOf(url) == -1) + { ui->downloadButton->setEnabled(true); return; - } else { + } + else + { ui->downloadButton->setEnabled(false); } ui->pushButton_3->hide(); - if (dw->getDIList()[dw->getUrlList().lastIndexOf(url)]->download == 2) { + if (dw->getDIList()[dw->getUrlList().lastIndexOf(url)]->download == 2) + { ui->downloadButton->setEnabled(true); ui->downloadButton->setText(tr("Download")); } - if (dw->getDIList()[dw->getUrlList().lastIndexOf(url)]->download == 1) { + if (dw->getDIList()[dw->getUrlList().lastIndexOf(url)]->download == 1) + { ui->downloadButton->setEnabled(true); ui->downloadButton->setText(tr("Install")); } - if (dw->getDIList()[dw->getUrlList().lastIndexOf(url)]->isInstall) { + if (dw->getDIList()[dw->getUrlList().lastIndexOf(url)]->isInstall) + { ui->downloadButton->setEnabled(false); ui->downloadButton->setText(tr("Installing")); return; } - if (dw->getDIList()[dw->getUrlList().lastIndexOf(url)]->download == 3) { + if (dw->getDIList()[dw->getUrlList().lastIndexOf(url)]->download == 3) + { ui->downloadButton->setEnabled(true); ui->downloadButton->setText(tr("Reinstall")); ui->downloadButton->show(); @@ -227,37 +232,37 @@ void AppIntoPage::isDownloading(QUrl url) void AppIntoPage::sltAppinfoTags(QStringList *tagList) { - foreach(const QString &tag, *tagList) + foreach (const QString &tag, *tagList) { - if(tag=="community") + if (tag == "community") { ui->tag_community->show(); } - else if(tag=="ubuntu") + else if (tag == "ubuntu") { ui->tag_ubuntu->show(); } - else if(tag=="deepin") + else if (tag == "deepin") { ui->tag_deepin->show(); } - else if(tag=="uos") + else if (tag == "uos") { ui->tag_uos->show(); } - else if(tag=="dtk5") + else if (tag == "dtk5") { ui->tag_dtk5->show(); } - else if(tag=="dwine2") + else if (tag == "dwine2") { ui->tag_dwine2->show(); } - else if(tag=="dwine5") + else if (tag == "dwine5") { ui->tag_dwine5->show(); } - else if(tag=="a2d") + else if (tag == "a2d") { ui->tag_a2d->show(); } @@ -265,9 +270,9 @@ void AppIntoPage::sltAppinfoTags(QStringList *tagList) } void AppIntoPage::setTheme(bool dark) { - if(dark) + if (dark) { - QString frameStyleSheet ="#frame,#frame_2,#frame_3,#frame_4{background-color: #252525;border-radius:14px;border:1px solid rgb(64, 64, 64);}"; + QString frameStyleSheet = "#frame,#frame_2,#frame_3,#frame_4{background-color: #252525;border-radius:14px;border:1px solid rgb(64, 64, 64);}"; ui->frame->setStyleSheet(frameStyleSheet); ui->frame_2->setStyleSheet(frameStyleSheet); ui->frame_3->setStyleSheet(frameStyleSheet); @@ -279,9 +284,11 @@ void AppIntoPage::setTheme(bool dark) ui->icon_4->setPixmap(QPixmap(":/icon/dark/text.svg")); ui->icon_5->setPixmap(QPixmap(":/icon/dark/folder.svg")); ui->icon_6->setPixmap(QPixmap(":/icon/dark/globe.svg")); - }else { - //亮色模式 - QString frameStyleSheet ="#frame,#frame_2,#frame_3,#frame_4{background-color: #fbfbfb;border-radius:14px;border:1px solid rgb(229,229,229);}"; + } + else + { + // 亮色模式 + QString frameStyleSheet = "#frame,#frame_2,#frame_3,#frame_4{background-color: #fbfbfb;border-radius:14px;border:1px solid rgb(229,229,229);}"; ui->frame->setStyleSheet(frameStyleSheet); ui->frame_2->setStyleSheet(frameStyleSheet); ui->frame_3->setStyleSheet(frameStyleSheet); @@ -293,7 +300,6 @@ void AppIntoPage::setTheme(bool dark) ui->icon_4->setPixmap(QPixmap(":/icon/light/text.svg")); ui->icon_5->setPixmap(QPixmap(":/icon/light/folder.svg")); ui->icon_6->setPixmap(QPixmap(":/icon/light/globe.svg")); - } } AppIntoPage::~AppIntoPage() @@ -303,34 +309,34 @@ AppIntoPage::~AppIntoPage() void AppIntoPage::on_downloadButton_clicked() { - if(ui->downloadButton->text() == tr("Install")) + if (ui->downloadButton->text() == tr("Install")) { - dw->getDIList()[dw->getUrlList().lastIndexOf(SparkAPI::getServerUrl()+"store"+spk.path()+"/"+info["Filename"].toString())]->install(0); - isDownloading(SparkAPI::getServerUrl()+"store"+spk.path()+"/"+info["Filename"].toString()); - QObject::connect(dw->getDIList()[dw->getUrlList().lastIndexOf(SparkAPI::getServerUrl()+"store"+spk.path()+"/"+info["Filename"].toString())],&DownloadItem::finished,[=](){ + dw->getDIList()[dw->getUrlList().lastIndexOf(SparkAPI::getServerUrl() + "store" + spk.path() + "/" + info["Filename"].toString())]->install(0); + isDownloading(SparkAPI::getServerUrl() + "store" + spk.path() + "/" + info["Filename"].toString()); + QObject::connect(dw->getDIList()[dw->getUrlList().lastIndexOf(SparkAPI::getServerUrl() + "store" + spk.path() + "/" + info["Filename"].toString())], &DownloadItem::finished, [=]() + { isDownloading(SparkAPI::getServerUrl()+"store"+spk.path()+"/"+info["Filename"].toString()); - disconnect(dw->getDIList()[dw->getUrlList().lastIndexOf(SparkAPI::getServerUrl()+"store"+spk.path()+"/"+info["Filename"].toString())],&DownloadItem::finished,nullptr,nullptr); - }); + disconnect(dw->getDIList()[dw->getUrlList().lastIndexOf(SparkAPI::getServerUrl()+"store"+spk.path()+"/"+info["Filename"].toString())],&DownloadItem::finished,nullptr,nullptr); }); return; } emit clickedDownloadBtn(); - dw->addItem(info["Name"].toString(),info["Filename"].toString(),info["Pkgname"].toString(),iconpixmap,SparkAPI::getServerUrl()+"store"+spk.path()+"/"+info["Filename"].toString()); - if(ui->downloadButton->text() == tr("Reinstall")) + dw->addItem(info["Name"].toString(), info["Filename"].toString(), info["Pkgname"].toString(), iconpixmap, SparkAPI::getServerUrl() + "store" + spk.path() + "/" + info["Filename"].toString()); + if (ui->downloadButton->text() == tr("Reinstall")) { dw->getDIList()[dw->allDownload - 1]->reinstall = true; } ui->downloadButton->setEnabled(false); - QObject::connect(dw->getDIList()[dw->getUrlList().lastIndexOf(SparkAPI::getServerUrl()+"store"+spk.path()+"/"+info["Filename"].toString())],&DownloadItem::finished,[=](){ + QObject::connect(dw->getDIList()[dw->getUrlList().lastIndexOf(SparkAPI::getServerUrl() + "store" + spk.path() + "/" + info["Filename"].toString())], &DownloadItem::finished, [=]() + { isDownloading(SparkAPI::getServerUrl()+"store"+spk.path()+"/"+info["Filename"].toString()); - disconnect(dw->getDIList()[dw->getUrlList().lastIndexOf(SparkAPI::getServerUrl()+"store"+spk.path()+"/"+info["Filename"].toString())],&DownloadItem::finished,nullptr,nullptr); - }); - isDownloading(SparkAPI::getServerUrl()+"store"+spk.path()+"/"+info["Filename"].toString()); + disconnect(dw->getDIList()[dw->getUrlList().lastIndexOf(SparkAPI::getServerUrl()+"store"+spk.path()+"/"+info["Filename"].toString())],&DownloadItem::finished,nullptr,nullptr); }); + isDownloading(SparkAPI::getServerUrl() + "store" + spk.path() + "/" + info["Filename"].toString()); } void AppIntoPage::on_pushButton_3_clicked() { QtConcurrent::run([=]() - { + { ui->downloadButton->setEnabled(false); ui->pushButton_3->setEnabled(false); @@ -352,19 +358,17 @@ void AppIntoPage::on_pushButton_3_clicked() } ui->downloadButton->setEnabled(true); - ui->pushButton_3->setEnabled(true); - }); + ui->pushButton_3->setEnabled(true); }); } void AppIntoPage::on_shareButton_clicked() { qDebug() << "Share" << spk; - Utils::sendNotification("spark-store",tr("Spark Store"),tr("The URL has been copied to the clipboard")); + Utils::sendNotification("spark-store", tr("Spark Store"), tr("The URL has been copied to the clipboard")); QClipboard *clipboard = QApplication::clipboard(); clipboard->setText(spk.toString()); } - void AppIntoPage::on_updateButton_clicked() { QString feedbackSpk = "spk://store/chat/store.spark-app.feedback"; @@ -374,9 +378,9 @@ void AppIntoPage::on_updateButton_clicked() qDebug() << "反馈器存在"; QProcess::startDetached("sh /opt/durapps/store.spark-app.feedback/launch.sh"); } - else{ + else + { qDebug() << "反馈器不存在,跳转页面"; openUrl(feedbackSpk); } } - diff --git a/src/pages/applistpage.cpp b/src/pages/applistpage.cpp index 7ea357b1..913db5b4 100644 --- a/src/pages/applistpage.cpp +++ b/src/pages/applistpage.cpp @@ -1,48 +1,55 @@ #include "applistpage.h" #include "ui_applistpage.h" -AppListPage::AppListPage(QWidget *parent) : - QWidget(parent), - ui(new Ui::AppListPage) +AppListPage::AppListPage(QWidget *parent) : QWidget(parent), + ui(new Ui::AppListPage) { ui->setupUi(this); ui->webEngineView->page()->setBackgroundColor(Qt::transparent); } void AppListPage::setTheme(bool dark) { - isDark=dark; - if(dark) + isDark = dark; + if (dark) { this->setStyleSheet("#frame{background-color: #252525;border-radius:14px;border:1px solid rgb(64, 64, 64);}"); - }else { - //亮色模式 + } + else + { + // 亮色模式 this->setStyleSheet("#frame{background-color: #ffffff;border-radius:14px;border:1px solid rgb(229,229,229);}"); } - if(isSearch) + if (isSearch) { getSearchList(nowType); - }else{ + } + else + { getAppList(nowType); } } void AppListPage::getAppList(QString type) { - isSearch=false; - nowType=type; - SparkAPI *api=new SparkAPI(this); + isSearch = false; + nowType = type; + SparkAPI *api = new SparkAPI(this); QString url; QString theme; - if(isDark) + if (isDark) { - theme="theme=dark"; - }else{ - theme="theme=light"; + theme = "theme=dark"; } - if(type=="") + else { - url=api->getServerUrl()+"store/#/flamescion/?"+theme; - }else{ - url=api->getServerUrl()+"store/#/flamescion/applist?type="+type+"&"+theme; + theme = "theme=light"; + } + if (type == "") + { + url = api->getServerUrl() + "store/#/flamescion/?" + theme; + } + else + { + url = api->getServerUrl() + "store/#/flamescion/applist?type=" + type + "&" + theme; } ui->webEngineView->setUrl(url); @@ -50,18 +57,20 @@ void AppListPage::getAppList(QString type) void AppListPage::getSearchList(QString keyword) { - isSearch=true; - nowType=keyword; - SparkAPI *api=new SparkAPI(this); + isSearch = true; + nowType = keyword; + SparkAPI *api = new SparkAPI(this); QString url; QString theme; - if(isDark) + if (isDark) + { + theme = "theme=dark"; + } + else { - theme="theme=dark"; - }else{ - theme="theme=light"; + theme = "theme=light"; } - url=api->getServerUrl()+"store/#/flamescion/search?keywords="+keyword+"&"+theme; + url = api->getServerUrl() + "store/#/flamescion/search?keywords=" + keyword + "&" + theme; ui->webEngineView->setUrl(url); } @@ -72,15 +81,14 @@ AppListPage::~AppListPage() void AppListPage::on_webEngineView_urlChanged(const QUrl &arg1) { - if(arg1.path().right(8) == "app.json") - { - QString url = arg1.toString(); - url = url.mid(url.indexOf("/store/")); - url = "spk:/"+url; - url = url.mid(0,url.indexOf("/app.json")); - qDebug() << "程序跳转链接地址:" << url; - ui->webEngineView->back(); - emit clicked(url); - } + if (arg1.path().right(8) == "app.json") + { + QString url = arg1.toString(); + url = url.mid(url.indexOf("/store/")); + url = "spk:/" + url; + url = url.mid(0, url.indexOf("/app.json")); + qDebug() << "程序跳转链接地址:" << url; + ui->webEngineView->back(); + emit clicked(url); + } } - diff --git a/src/pages/settingspage.cpp b/src/pages/settingspage.cpp index 6c0d431a..1a17213c 100644 --- a/src/pages/settingspage.cpp +++ b/src/pages/settingspage.cpp @@ -1,9 +1,8 @@ #include "settingspage.h" #include "ui_settingspage.h" bool SettingsPage::isdownload = false; -SettingsPage::SettingsPage(QWidget *parent) : - QWidget(parent), - ui(new Ui::SettingsPage) +SettingsPage::SettingsPage(QWidget *parent) : QWidget(parent), + ui(new Ui::SettingsPage) { ui->setupUi(this); configCanSave = false; @@ -12,11 +11,13 @@ SettingsPage::SettingsPage(QWidget *parent) : void SettingsPage::setTheme(bool dark) { - if(dark) + if (dark) { this->setStyleSheet("#frame{background-color: #252525;border-radius:14px;border:1px solid rgb(64, 64, 64);}"); - }else { - //亮色模式 + } + else + { + // 亮色模式 this->setStyleSheet("#frame{background-color: #ffffff;border-radius:14px;border:1px solid rgb(229,229,229);}"); } } @@ -26,7 +27,7 @@ void SettingsPage::readServerList() // 读取服务器列表并初始化 QFile file(QDir::homePath().toUtf8() + "/.config/spark-store/server.list"); - //判断文件是否存在 + // 判断文件是否存在 if (!file.exists()) { ui->comboBox_server->addItem("https://d.store.deepinos.org.cn/"); @@ -34,28 +35,28 @@ void SettingsPage::readServerList() if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) { - qDebug()<<"无法读取server.list"; + qDebug() << "无法读取server.list"; } - //创建QTextStream对象 + // 创建QTextStream对象 QTextStream textStream(&file); - QString lineData = textStream.readLine();//读取文件的第一行 + QString lineData = textStream.readLine(); // 读取文件的第一行 ui->comboBox_server->addItem(lineData); - while(!lineData.isNull()) + while (!lineData.isNull()) { lineData = textStream.readLine(); ui->comboBox_server->addItem(lineData); } - for(int i = 0; i < ui->comboBox_server->count(); i++) + for (int i = 0; i < ui->comboBox_server->count(); i++) { - if(ui->comboBox_server->itemText(i) == "开发者模式 Dev only") + if (ui->comboBox_server->itemText(i) == "开发者模式 Dev only") { ui->comboBox_server->model()->setData(ui->comboBox_server->model()->index(i, 0), QVariant(0), Qt::UserRole - 1); } - if(ui->comboBox_server->itemText(i) == "镜像源 Download only") + if (ui->comboBox_server->itemText(i) == "镜像源 Download only") { - for(int j = i; j < ui->comboBox_server->count(); j++) + for (int j = i; j < ui->comboBox_server->count(); j++) { ui->comboBox_server->model()->setData(ui->comboBox_server->model()->index(j, 0), QVariant(0), Qt::UserRole - 1); } @@ -71,13 +72,13 @@ void SettingsPage::initConfig() // 读取服务器URL并初始化菜单项的链接 QSettings readConfig(QDir::homePath() + "/.config/spark-store/config.ini", QSettings::IniFormat); - if(!readConfig.value("server/choose").toString().isEmpty() && readConfig.value("server/updated").toString() == "TRUE") + if (!readConfig.value("server/choose").toString().isEmpty() && readConfig.value("server/updated").toString() == "TRUE") { - qDebug()<comboBox_server->setCurrentText(readConfig.value("server/choose").toString()); SparkAPI::setServerUrl(readConfig.value("server/choose").toString()); } - configCanSave = true; // 防止触发保存配置信号 + configCanSave = true; //  防止触发保存配置信号 } SettingsPage::~SettingsPage() @@ -88,7 +89,7 @@ SettingsPage::~SettingsPage() void SettingsPage::on_pushButton_updateServer_clicked() { QtConcurrent::run([=]() - { + { ui->pushButton_updateServer->setEnabled(false); ui->comboBox_server->clear(); @@ -97,17 +98,15 @@ void SettingsPage::on_pushButton_updateServer_clicked() ui->pushButton_updateServer->setEnabled(true); readServerList(); - ui->comboBox_server->setCurrentIndex(0); - }); + ui->comboBox_server->setCurrentIndex(0); }); } - void SettingsPage::on_comboBox_server_currentIndexChanged(const QString &arg1) { - SparkAPI::setServerUrl(arg1); // 服务器信息更新 -qDebug()<label_setting1->show(); QSettings *setConfig = new QSettings(QDir::homePath() + "/.config/spark-store/config.ini", QSettings::IniFormat); @@ -124,7 +123,7 @@ void SettingsPage::setIsDownload(bool isdownload) void SettingsPage::updateUI() { - if(isdownload) + if (isdownload) { ui->pushButton_clear->setEnabled(false); } @@ -135,15 +134,15 @@ void SettingsPage::updateUI() // 显示缓存占用空间 quint64 tmp_size = dirFileSize(QString::fromUtf8(TMP_PATH)); QString tmp_size_str; - if(tmp_size < 1024) + if (tmp_size < 1024) { tmp_size_str = QString::number(tmp_size) + "B"; } - else if(tmp_size < (1024 * 1024)) + else if (tmp_size < (1024 * 1024)) { tmp_size_str = QString::number(0.01 * int(100 * (tmp_size / 1024))) + "KB"; } - else if(tmp_size<(1024*1024*1024)) + else if (tmp_size < (1024 * 1024 * 1024)) { tmp_size_str = QString::number(0.01 * int(100 * (tmp_size / (1024 * 1024)))) + "MB"; } @@ -160,13 +159,13 @@ quint64 SettingsPage::dirFileSize(const QString &path) QDir dir(path); quint64 size = 0; // dir.entryInfoList(QDir::Files); // 返回文件信息 - foreach(QFileInfo fileInfo, dir.entryInfoList(QDir::Files)) + foreach (QFileInfo fileInfo, dir.entryInfoList(QDir::Files)) { // 计算文件大小 size += quint64(fileInfo.size()); } // dir.entryList(QDir::Dirs|QDir::NoDotAndDotDot); // 返回所有子目录,并进行过滤 - foreach(QString subDir, dir.entryList(QDir::Dirs | QDir::NoDotAndDotDot)) + foreach (QString subDir, dir.entryList(QDir::Dirs | QDir::NoDotAndDotDot)) { // 若存在子目录,则递归调用 dirFileSize() 函数 size += dirFileSize(path + QDir::separator() + subDir); @@ -177,22 +176,20 @@ quint64 SettingsPage::dirFileSize(const QString &path) void SettingsPage::on_pushButton_updateApt_clicked() { QtConcurrent::run([=]() - { + { ui->pushButton_updateApt->setEnabled(false); ui->label_aptserver->setText(tr("Updating, please wait...")); emit openUrl(QUrl("spk://store/tools/spark-store")); ui->label_aptserver->setText(tr("")); - ui->pushButton_updateApt->setEnabled(true); - }); + ui->pushButton_updateApt->setEnabled(true); }); } - void SettingsPage::on_pushButton_clear_clicked() { QtConcurrent::run([=]() - { + { ui->pushButton_clear->setEnabled(false); QDir tmpdir("/tmp/spark-store"); @@ -204,15 +201,13 @@ void SettingsPage::on_pushButton_clear_clicked() } Utils::sendNotification("spark-store",tr("Spark Store"),tr("Temporary cache was cleaned")); ui->pushButton_clear->setEnabled(true); - updateUI(); - }); + updateUI(); }); } - void SettingsPage::on_pushButton_clearWebCache_clicked() { QtConcurrent::run([=]() - { + { QString dataLocal = QStandardPaths::writableLocation(QStandardPaths::AppLocalDataLocation); qDebug() << dataLocal; QDir dataDir(dataLocal); @@ -220,7 +215,5 @@ void SettingsPage::on_pushButton_clearWebCache_clicked() dataLocal = QStandardPaths::writableLocation(QStandardPaths::TempLocation); qDebug() << dataLocal; QDir cacheDir(dataLocal); - cacheDir.removeRecursively(); - }); + cacheDir.removeRecursively(); }); } - diff --git a/src/utils/httprequest.cpp b/src/utils/httprequest.cpp index a9a73dd2..c4cf95a1 100644 --- a/src/utils/httprequest.cpp +++ b/src/utils/httprequest.cpp @@ -1,22 +1,19 @@ #include "httprequest.h" - - HttpRequest::HttpRequest() { - } void HttpRequest::getRequest(QNetworkRequest request) { - QNetworkAccessManager *naManager=new QNetworkAccessManager(this); + QNetworkAccessManager *naManager = new QNetworkAccessManager(this); request.setRawHeader("User-Agent", "Mozilla/5.0"); request.setRawHeader("Content-Type", "charset='utf-8'"); request.setRawHeader("Content-Type", "application/json"); naManager->get(request); - QObject::connect(naManager,&QNetworkAccessManager::finished,this,&HttpRequest::readdata_slot); + QObject::connect(naManager, &QNetworkAccessManager::finished, this, &HttpRequest::readdata_slot); } void HttpRequest::readdata_slot(QNetworkReply *reply) { @@ -24,19 +21,19 @@ void HttpRequest::readdata_slot(QNetworkReply *reply) } QString HttpRequest::postRequest(QString url, QString jsondata) { - QByteArray array= jsondata.toLatin1(); + QByteArray array = jsondata.toLatin1(); QNetworkRequest request; - QNetworkAccessManager *naManager=new QNetworkAccessManager(this); - QUrl strUrl = url.replace("+","%2B"); + QNetworkAccessManager *naManager = new QNetworkAccessManager(this); + QUrl strUrl = url.replace("+", "%2B"); request.setUrl(strUrl); request.setRawHeader("Content-Type", "charset='utf-8'"); request.setRawHeader("Content-Type", "application/json"); - QNetworkReply* reply = naManager->post(request, array); + QNetworkReply *reply = naManager->post(request, array); QEventLoop eventLoop; - connect(naManager, SIGNAL(finished(QNetworkReply*)), &eventLoop, SLOT(quit())); + connect(naManager, SIGNAL(finished(QNetworkReply *)), &eventLoop, SLOT(quit())); eventLoop.exec(); - QTextCodec* codec = QTextCodec::codecForName("utf8"); + QTextCodec *codec = QTextCodec::codecForName("utf8"); QString strReply = codec->toUnicode(reply->readAll()); reply->deleteLater(); return strReply; diff --git a/src/utils/utils.cpp b/src/utils/utils.cpp index f475c1f3..d57b4037 100644 --- a/src/utils/utils.cpp +++ b/src/utils/utils.cpp @@ -2,18 +2,17 @@ Utils::Utils() { - } -//这个函数是chatGPT写的 -void Utils::sendNotification(QString icon,QString title,QString body) +// Author: chatGPT +void Utils::sendNotification(QString icon, QString title, QString body) { QDBusInterface iface("org.freedesktop.Notifications", "/org/freedesktop/Notifications", "org.freedesktop.Notifications"); QVariantList args; - args << QCoreApplication::applicationName() // the name of the application + args << QCoreApplication::applicationName() // the name of the application << (uint)0 // replaces the previous notification with the same ID << icon // the application icon of the notification << title // the title of the notification diff --git a/src/utils/widgetanimation.cpp b/src/utils/widgetanimation.cpp index f74b1300..ee6fe64c 100644 --- a/src/utils/widgetanimation.cpp +++ b/src/utils/widgetanimation.cpp @@ -2,43 +2,45 @@ WidgetAnimation::WidgetAnimation() { - } void WidgetAnimation::widgetShake(QWidget *pWidget, int nRange) { int nX = pWidget->x(); int nY = pWidget->y(); - QPropertyAnimation *pAnimation = new QPropertyAnimation(pWidget,"geometry"); + QPropertyAnimation *pAnimation = new QPropertyAnimation(pWidget, "geometry"); pAnimation->setEasingCurve(QEasingCurve::InOutSine); pAnimation->setDuration(400); - pAnimation->setStartValue(QRect(QPoint(nX,nY),pWidget->size())); + pAnimation->setStartValue(QRect(QPoint(nX, nY), pWidget->size())); int nShakeCount = 8; - double nStep = 1.0/nShakeCount; - for(int i = 1; i < nShakeCount; i++){ - nRange = i&1 ? -nRange : nRange; - pAnimation->setKeyValueAt(nStep*i,QRect(QPoint(nX + nRange,nY),pWidget->size())); + double nStep = 1.0 / nShakeCount; + for (int i = 1; i < nShakeCount; i++) + { + nRange = i & 1 ? -nRange : nRange; + pAnimation->setKeyValueAt(nStep * i, QRect(QPoint(nX + nRange, nY), pWidget->size())); } - pAnimation->setEndValue(QRect(QPoint(nX,nY),pWidget->size())); + pAnimation->setEndValue(QRect(QPoint(nX, nY), pWidget->size())); pAnimation->start(QAbstractAnimation::DeleteWhenStopped); } -QPropertyAnimation* WidgetAnimation::createWidgetOpacity(QWidget *pWidget, bool isAppear) +QPropertyAnimation *WidgetAnimation::createWidgetOpacity(QWidget *pWidget, bool isAppear) { QPropertyAnimation *animation = new QPropertyAnimation(pWidget, "windowOpacity", pWidget); - //设置动画效果 + // 设置动画效果 animation->setEasingCurve(QEasingCurve::Linear); - //设置动画时间(单位:毫秒) + // 设置动画时间(单位:毫秒) animation->setDuration(500); // 设置动画步长值,以及在该位置时显示的透明度 - if(isAppear) + if (isAppear) { animation->setKeyValueAt(0, 0); // m_animation->setKeyValueAt(0.5, 0); animation->setKeyValueAt(1, 1); - }else{ + } + else + { animation->setKeyValueAt(0, 1); animation->setKeyValueAt(1, 0); } @@ -46,7 +48,7 @@ QPropertyAnimation* WidgetAnimation::createWidgetOpacity(QWidget *pWidget, bool } void WidgetAnimation::widgetOpacity(QWidget *pWidget, bool isAppear) -{ +{ // 开始动画 createWidgetOpacity(pWidget, isAppear)->start(); } diff --git a/src/widgets/base/basewidgetopacity.cpp b/src/widgets/base/basewidgetopacity.cpp index 224e74a6..fcff23fb 100644 --- a/src/widgets/base/basewidgetopacity.cpp +++ b/src/widgets/base/basewidgetopacity.cpp @@ -5,14 +5,15 @@ BaseWidgetOpacity::BaseWidgetOpacity(QWidget *parent) : DBlurEffectWidget(parent) { -// WidgetAnimation::widgetOpacity(this,true); + // WidgetAnimation::widgetOpacity(this,true); } /// @brief 窗口关闭事件 /// @param event void BaseWidgetOpacity::closeEvent(QCloseEvent *event) { - if (!closeWindowAnimation) { + if (!closeWindowAnimation) + { closeWindowAnimation = true; QPropertyAnimation *animation = new QPropertyAnimation(this, "windowOpacity"); @@ -21,18 +22,20 @@ void BaseWidgetOpacity::closeEvent(QCloseEvent *event) animation->setStartValue(1.0); animation->setEndValue(0.0); - QObject::connect(animation, &QPropertyAnimation::valueChanged, this, [=](const QVariant &value){ - this->update(); - // setWindowTitle(QString("ヾ(⌒∇⌒*)See You♪ - %1%").arg(int(value.toFloat() * 100))); - }); + QObject::connect(animation, &QPropertyAnimation::valueChanged, this, [=](const QVariant &value) + { + this->update(); + // setWindowTitle(QString("ヾ(⌒∇⌒*)See You♪ - %1%").arg(int(value.toFloat() * 100))); + }); - QObject::connect(animation, &QPropertyAnimation::finished, this, [=](){ - this->close(); - }); + QObject::connect(animation, &QPropertyAnimation::finished, this, [=]() + { this->close(); }); animation->start(); event->ignore(); - } else { + } + else + { event->accept(); } } diff --git a/src/widgets/big_image.cpp b/src/widgets/big_image.cpp index b8d7afaa..2549b599 100644 --- a/src/widgets/big_image.cpp +++ b/src/widgets/big_image.cpp @@ -3,11 +3,10 @@ #include #include -big_image::big_image(DBlurEffectWidget *parent) : - DBlurEffectWidget(parent), - m_image(new QLabel) +big_image::big_image(DBlurEffectWidget *parent) : DBlurEffectWidget(parent), + m_image(new QLabel) { -// setWindowFlags(this->windowFlags() | Qt::WindowStaysOnTopHint); // 设置图片对话框总在最前 + // setWindowFlags(this->windowFlags() | Qt::WindowStaysOnTopHint); // 设置图片对话框总在最前 setWindowModality(Qt::ApplicationModal); // 以上无效不如直接使用 模态化对话框 setRadius(0); setMaskAlpha(60); diff --git a/src/widgets/common/downloaditem.cpp b/src/widgets/common/downloaditem.cpp index bff00951..538942f8 100644 --- a/src/widgets/common/downloaditem.cpp +++ b/src/widgets/common/downloaditem.cpp @@ -6,13 +6,12 @@ bool DownloadItem::isInstall = false; -DownloadItem::DownloadItem(QWidget *parent) : - QWidget(parent), - reinstall(false), - close(false), - ui(new Ui::DownloadItem), - output_w(new DDialog), - textbrowser(new QTextBrowser) +DownloadItem::DownloadItem(QWidget *parent) : QWidget(parent), + reinstall(false), + close(false), + ui(new Ui::DownloadItem), + output_w(new DDialog), + textbrowser(new QTextBrowser) { ui->setupUi(this); @@ -34,7 +33,7 @@ void DownloadItem::setValue(qint64 value) { ui->progressBar->setValue(qint32(value)); ui->label_2->setText(QString::number(double(value) / 100) + "% (" + speed + ")"); - if(ui->label_2->text().left(4) == "100%") + if (ui->label_2->text().left(4) == "100%") { download = 1; ui->label_2->setText(tr("Download Complete.")); @@ -58,7 +57,7 @@ QString DownloadItem::getName() void DownloadItem::readyInstall() { - if(!close) + if (!close) { ui->progressBar->hide(); ui->pushButton_install->setEnabled(true); @@ -90,7 +89,7 @@ void DownloadItem::setSpeed(QString s) void DownloadItem::install(int t) { - if(!isInstall) + if (!isInstall) { isInstall = true; ui->pushButton_install->hide(); @@ -99,7 +98,7 @@ void DownloadItem::install(int t) ui->label_2->setText(tr("Installing")); QtConcurrent::run([=]() - { + { QProcess installer; switch(t) { @@ -164,10 +163,9 @@ void DownloadItem::install(int t) ui->widget_spinner->hide(); DownloadItem::isInstall = false; - emit finished(); - }); + emit finished(); }); // emit finished(); - qDebug()<label_filename->text().toUtf8(); + qDebug() << ui->label_filename->text().toUtf8(); } } diff --git a/src/widgets/common/progressbutton.cpp b/src/widgets/common/progressbutton.cpp index a58532b3..59eaf532 100644 --- a/src/widgets/common/progressbutton.cpp +++ b/src/widgets/common/progressbutton.cpp @@ -8,15 +8,15 @@ ProgressButton::ProgressButton(QWidget *parent) : QWidget{parent} { - //this->setWindowFlags(Qt::FramelessWindowHint); + // this->setWindowFlags(Qt::FramelessWindowHint); this->setAttribute(Qt::WA_TranslucentBackground, true); setMinimumWidth(36); setMinimumHeight(36); - svgPath=""; - backColor=Qt::transparent; + svgPath = ""; + backColor = Qt::transparent; setMouseTracking(true); - connect(this,&ProgressButton::startProcessing,this,&ProgressButton::operationProcessing,Qt::QueuedConnection); + connect(this, &ProgressButton::startProcessing, this, &ProgressButton::operationProcessing, Qt::QueuedConnection); } ProgressButton::~ProgressButton() @@ -26,63 +26,63 @@ ProgressButton::~ProgressButton() void ProgressButton::paintEvent(QPaintEvent *event) { QPainter painter(this); - painter.setRenderHint(QPainter::Antialiasing,true); + painter.setRenderHint(QPainter::Antialiasing, true); auto rect = event->rect(); - if(buttonState == state::normal || buttonState == state::hover) + if (buttonState == state::normal || buttonState == state::hover) { auto radiu = (rect.height() - 6) / 2; painter.translate(rect.center()); painter.setPen(Qt::transparent); painter.setBrush(QColor(buttonState == state::normal ? color : color.darker())); - //painter.drawEllipse(QPoint(0,0),radiu,radiu); + // painter.drawEllipse(QPoint(0,0),radiu,radiu); - //radiu -= 3; + // radiu -= 3; painter.setBrush(backColor); - painter.drawEllipse(QPoint(0,0),radiu,radiu); + painter.drawEllipse(QPoint(0, 0), radiu, radiu); QSvgRenderer m_svgRender; m_svgRender.load(svgPath); - m_svgRender.render(&painter ,QRectF(-radiu / 2,-radiu / 2,radiu,radiu)); + m_svgRender.render(&painter, QRectF(-radiu / 2, -radiu / 2, radiu, radiu)); } - else if(buttonState == state::openProgress) + else if (buttonState == state::openProgress) { painter.translate(rect.center()); - auto radiu = (rect.height() - 6) / 2 -3; + auto radiu = (rect.height() - 6) / 2 - 3; painter.setBrush(backColor); - painter.setPen(QPen(backColor,3)); - painter.drawEllipse(QPoint(0,0),radiu,radiu); + painter.setPen(QPen(backColor, 3)); + painter.drawEllipse(QPoint(0, 0), radiu, radiu); - painter.setPen(QPen(backColor,3)); + painter.setPen(QPen(backColor, 3)); QSvgRenderer m_svgRender; m_svgRender.load(svgPath); - m_svgRender.render(&painter ,QRectF(-radiu / 2,-radiu / 2,radiu,radiu)); + m_svgRender.render(&painter, QRectF(-radiu / 2, -radiu / 2, radiu, radiu)); QRect rect = QRect(-radiu, -radiu, - radiu*2, radiu*2); + radiu * 2, radiu * 2); - painter.setPen(QPen(color.darker(100),3)); + painter.setPen(QPen(color.darker(100), 3)); auto angle = progress * 360 / 100; - painter.drawArc(rect.adjusted(-3,-3,3,3),90 * 16,-static_cast(angle * 16)); + painter.drawArc(rect.adjusted(-3, -3, 3, 3), 90 * 16, -static_cast(angle * 16)); } - else if(buttonState == state::closeProgress) + else if (buttonState == state::closeProgress) { auto radiu = (rect.height() - 6) / 2; painter.translate(rect.center()); painter.setPen(Qt::transparent); painter.setBrush(QColor(0, 0, 0, 63)); - painter.drawEllipse(QPoint(0,0),radiu,radiu); + painter.drawEllipse(QPoint(0, 0), radiu, radiu); radiu -= 3; painter.setBrush(backColor); - painter.drawEllipse(QPoint(0,0),radiu,radiu); + painter.drawEllipse(QPoint(0, 0), radiu, radiu); - painter.setPen(QPen(color,3,Qt::SolidLine,Qt::RoundCap,Qt::RoundJoin)); - painter.drawLine(QPoint(-radiu / 3,0), - QPoint(-radiu / 5,radiu / 3)); - painter.drawLine(QPoint(-radiu / 5,radiu / 3), - QPoint(radiu / 4,-radiu / 4)); + painter.setPen(QPen(color, 3, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin)); + painter.drawLine(QPoint(-radiu / 3, 0), + QPoint(-radiu / 5, radiu / 3)); + painter.drawLine(QPoint(-radiu / 5, radiu / 3), + QPoint(radiu / 4, -radiu / 4)); } } @@ -90,12 +90,12 @@ void ProgressButton::setProgress(int progress) { buttonState = state::openProgress; ProgressButton::progress = progress; - if(progress == 0) + if (progress == 0) { buttonState = state::normal; update(); } - if(progress == 100) + if (progress == 100) { buttonState = state::closeProgress; update(); @@ -127,7 +127,7 @@ void ProgressButton::setColor(QColor color) void ProgressButton::leaveEvent(QEvent *event) { - if(buttonState == state::hover) + if (buttonState == state::hover) { buttonState = state::normal; update(); @@ -137,12 +137,12 @@ void ProgressButton::leaveEvent(QEvent *event) void ProgressButton::mousePressEvent(QMouseEvent *event) { - if(buttonState == state::hover || buttonState == state::normal) + if (buttonState == state::hover || buttonState == state::normal) { widthChangeValue = (this->width() - 6) / 2; update(); } - else if(buttonState == state::closeProgress) + else if (buttonState == state::closeProgress) { update(); } @@ -152,24 +152,21 @@ void ProgressButton::mousePressEvent(QMouseEvent *event) void ProgressButton::operationProcessing() { - } const int RADIUS = 60; WaterDrop::WaterDrop(QWidget *parent) - : QWidget(parent) - , m_waterDropAnimation(nullptr) - , m_animationRadius(0) + : QWidget(parent), m_waterDropAnimation(nullptr), m_animationRadius(0) { this->setFixedSize(QSize(RADIUS * 2, RADIUS * 2)); this->setWindowFlags(Qt::FramelessWindowHint | Qt::Tool); this->setAttribute(Qt::WA_TranslucentBackground); this->setAttribute(Qt::WA_DeleteOnClose); m_waterDropAnimation = new QVariantAnimation(this); -// m_waterDropAnimation->setEasingCurve(QEasingCurve(static_cast(QRandomGenerator::global()->bounded(40)))); + // m_waterDropAnimation->setEasingCurve(QEasingCurve(static_cast(QRandomGenerator::global()->bounded(40)))); } -//把鼠标点击的点转换为圆心点坐标 +// 把鼠标点击的点转换为圆心点坐标 void WaterDrop::move(const QPoint &point) { QPoint translatePoint = point - QPoint(RADIUS, RADIUS); @@ -196,7 +193,7 @@ void WaterDrop::paintEvent(QPaintEvent *event) pen.setColor(QColor(0xffffff80)); pen.setWidth(5); painter.setPen(pen); - painter.drawEllipse(event->rect().center(),m_animationRadius, m_animationRadius); + painter.drawEllipse(event->rect().center(), m_animationRadius, m_animationRadius); } void WaterDrop::onRaduisChanged(QVariant value) diff --git a/src/widgets/common/smoothlistwidget.cpp b/src/widgets/common/smoothlistwidget.cpp index aa84496f..3cba1b48 100644 --- a/src/widgets/common/smoothlistwidget.cpp +++ b/src/widgets/common/smoothlistwidget.cpp @@ -5,13 +5,13 @@ #include SmoothListWidget::SmoothListWidget(QWidget *parent) : QListWidget(parent) { - vScrollBar->setOrientation(Qt::Orientation::Vertical); //将滚动条设置为纵向 - setVerticalScrollBar(vScrollBar); //设置纵向滚动条 + vScrollBar->setOrientation(Qt::Orientation::Vertical); // 将滚动条设置为纵向 + setVerticalScrollBar(vScrollBar); // 设置纵向滚动条 connect(vScrollBar, SIGNAL(valueChanged(int)), this, SLOT(onSliderChanged(int))); } void SmoothListWidget::wheelEvent(QWheelEvent *e) { - //当捕获到事件后,调用相对滚动的槽函数 + // 当捕获到事件后,调用相对滚动的槽函数 vScrollBar->scroll(e->angleDelta().y()); } void SmoothListWidget::onSliderChanged(int p) @@ -21,5 +21,5 @@ void SmoothListWidget::onSliderChanged(int p) { emit reachedBottom(); // 1 } - emit msliderChanged(p); // 2 + emit msliderChanged(p); // 2 } diff --git a/src/widgets/common/smoothscrollbar.cpp b/src/widgets/common/smoothscrollbar.cpp index 87591244..5fd190b5 100644 --- a/src/widgets/common/smoothscrollbar.cpp +++ b/src/widgets/common/smoothscrollbar.cpp @@ -1,56 +1,56 @@ #include "smoothscrollbar.h" #include #include -SmoothScrollBar::SmoothScrollBar(QWidget* parent):QScrollBar(parent) +SmoothScrollBar::SmoothScrollBar(QWidget *parent) : QScrollBar(parent) { - m_scrollAni=new QPropertyAnimation(this); + m_scrollAni = new QPropertyAnimation(this); m_scrollAni->setTargetObject(this); m_scrollAni->setPropertyName("value"); - m_scrollAni->setEasingCurve(QEasingCurve::OutQuint); //设置动画曲线,在Qt文档中有详细的介绍 - m_scrollAni->setDuration(500); //设置动画时间,数值越小播放越快 - m_targetValue_v=value(); //将m_targetValue_v初始化 + m_scrollAni->setEasingCurve(QEasingCurve::OutQuint); // 设置动画曲线,在Qt文档中有详细的介绍 + m_scrollAni->setDuration(500); // 设置动画时间,数值越小播放越快 + m_targetValue_v = value(); // 将m_targetValue_v初始化 } void SmoothScrollBar::setValue(int value) { - m_scrollAni->stop();//停止现在的动画,防止出现冲突 - m_scrollAni->setStartValue(this->value()); //设置动画滚动的初始值为当前位置 - m_scrollAni->setEndValue(value); //设置动画的结束位置为目标值 - m_scrollAni->start(); //开始动画 + m_scrollAni->stop(); // 停止现在的动画,防止出现冲突 + m_scrollAni->setStartValue(this->value()); // 设置动画滚动的初始值为当前位置 + m_scrollAni->setEndValue(value); // 设置动画的结束位置为目标值 + m_scrollAni->start(); // 开始动画 } void SmoothScrollBar::scrollTop() { - setValue(-m_targetValue_v); //开始动画 - m_targetValue_v=0; + setValue(-m_targetValue_v); // 开始动画 + m_targetValue_v = 0; } void SmoothScrollBar::scroll(int value) { - //这里推荐评论区中大佬优化的写法 - if(m_targetValue_v-value>=0) + // 这里推荐评论区中大佬优化的写法 + if (m_targetValue_v - value >= 0) { - m_targetValue_v-=value; //将目标值和相对位置进行运算 - setValue(m_targetValue_v); //开始动画 + m_targetValue_v -= value; // 将目标值和相对位置进行运算 + setValue(m_targetValue_v); // 开始动画 } } void SmoothScrollBar::mousePressEvent(QMouseEvent *e) { - //当使用鼠标操作滚动条时,不会刷新m_targetValue_v的值,因而需要重写事件,对其进行刷新。 + // 当使用鼠标操作滚动条时,不会刷新m_targetValue_v的值,因而需要重写事件,对其进行刷新。 m_scrollAni->stop(); QScrollBar::mousePressEvent(e); - m_targetValue_v=value(); + m_targetValue_v = value(); } void SmoothScrollBar::mouseReleaseEvent(QMouseEvent *e) { m_scrollAni->stop(); QScrollBar::mouseReleaseEvent(e); - m_targetValue_v=value(); + m_targetValue_v = value(); } void SmoothScrollBar::mouseMoveEvent(QMouseEvent *e) { m_scrollAni->stop(); QScrollBar::mouseMoveEvent(e); - m_targetValue_v=value(); + m_targetValue_v = value(); } diff --git a/src/widgets/common/webenginepage.cpp b/src/widgets/common/webenginepage.cpp index 5f9d0259..af7a050b 100644 --- a/src/widgets/common/webenginepage.cpp +++ b/src/widgets/common/webenginepage.cpp @@ -13,7 +13,8 @@ WebEnginePage::~WebEnginePage() void WebEnginePage::setUrl(const QUrl &url) { - if (m_currentUrl == url) { + if (m_currentUrl == url) + { return; } @@ -32,7 +33,8 @@ QWebEnginePage *WebEnginePage::createWindow(QWebEnginePage::WebWindowType type) void WebEnginePage::slotUrlChanged(const QUrl &url) { - if (m_currentUrl == url) { + if (m_currentUrl == url) + { sender()->deleteLater(); return; } diff --git a/src/widgets/downloadlistwidget.cpp b/src/widgets/downloadlistwidget.cpp index d99e2f7b..e778175f 100644 --- a/src/widgets/downloadlistwidget.cpp +++ b/src/widgets/downloadlistwidget.cpp @@ -3,23 +3,22 @@ #include #include #include -DownloadListWidget::DownloadListWidget(QWidget *parent) : - DBlurEffectWidget(parent), - ui(new Ui::DownloadListWidget) +DownloadListWidget::DownloadListWidget(QWidget *parent) : DBlurEffectWidget(parent), + ui(new Ui::DownloadListWidget) { ui->setupUi(this); installEventFilter(this); - this->setAttribute(Qt::WA_Hover,true); + this->setAttribute(Qt::WA_Hover, true); setFocus(); - setFixedSize(500,400); + setFixedSize(500, 400); setMaskAlpha(250); ui->listWidget->hide(); ui->widget->show(); // 计算显示下载速度 download_speed.setInterval(1000); download_speed.start(); - connect(&download_speed,&QTimer::timeout,[=]() - { + connect(&download_speed, &QTimer::timeout, [=]() + { if(isdownload && theSpeed == "") { size1 = download_size; @@ -47,13 +46,13 @@ DownloadListWidget::DownloadListWidget(QWidget *parent) : downloaditemlist[nowDownload - 1]->setSpeed(theSpeed); }else{ emit downloadProgress(0); - } - }); + } }); } DownloadListWidget::~DownloadListWidget() { - if (downloadController) { + if (downloadController) + { downloadController->stopDownload(); downloadController->deleteLater(); } @@ -64,41 +63,41 @@ DownloadListWidget::~DownloadListWidget() void DownloadListWidget::clearItem() { ui->listWidget->vScrollBar->scrollTop(); - int n=ui->listWidget->count(); - for(int i=0;ilistWidget->count(); + for (int i = 0; i < n; i++) { QListWidgetItem *item = ui->listWidget->takeItem(0); QWidget *card = ui->listWidget->itemWidget(item); delete card; - card = NULL; + card = NULL; delete item; - item = NULL; + item = NULL; } ui->listWidget->clear(); } -void DownloadListWidget::addItem(QString name,QString fileName,QString pkgName,const QPixmap icon,QString downloadurl) +void DownloadListWidget::addItem(QString name, QString fileName, QString pkgName, const QPixmap icon, QString downloadurl) { - if(fileName.isEmpty()) + if (fileName.isEmpty()) { return; } urList.append(downloadurl); allDownload += 1; - DownloadItem *di=new DownloadItem(this); - dlist<setName(name); di->setFileName(fileName); - di->pkgName=pkgName; + di->pkgName = pkgName; di->seticon(icon); - QListWidgetItem* pItem = new QListWidgetItem(); + QListWidgetItem *pItem = new QListWidgetItem(); pItem->setSizeHint(QSize(240, 50)); ui->listWidget->addItem(pItem); ui->listWidget->setItemWidget(pItem, di); - if(!isBusy) + if (!isBusy) { nowDownload += 1; - startRequest(urList.at(nowDownload - 1), fileName); // 进行链接请求 + startRequest(urList.at(nowDownload - 1), fileName); // 进行链接请求 } } @@ -120,10 +119,10 @@ void DownloadListWidget::startRequest(QUrl url, QString fileName) isdownload = true; downloaditemlist[allDownload - 1]->free = false; - downloadController = new DownloadController(this); // 并发下载,在点击下载按钮的时候才会初始化 + downloadController = new DownloadController(this); // 并发下载,在点击下载按钮的时候才会初始化 connect(downloadController, &DownloadController::downloadProcess, this, &DownloadListWidget::updateDataReadProgress); connect(downloadController, &DownloadController::downloadFinished, this, &DownloadListWidget::httpFinished); - //connect(downloadController, &DownloadController::errorOccur, this, [=](QString msg){this->sendNotification(msg);}); + // connect(downloadController, &DownloadController::errorOccur, this, [=](QString msg){this->sendNotification(msg);}); downloadController->setFilename(fileName); downloadController->startDownload(url.toString()); } @@ -135,37 +134,37 @@ void DownloadListWidget::httpFinished() // 完成下载 downloaditemlist[nowDownload - 1]->readyInstall(); downloaditemlist[nowDownload - 1]->free = true; emit downloadFinished(); - if(nowDownload < allDownload) + if (nowDownload < allDownload) { // 如果有排队则下载下一个 qDebug() << "切换下一个下载..."; nowDownload += 1; - while(downloaditemlist[nowDownload - 1]->close) + while (downloaditemlist[nowDownload - 1]->close) { nowDownload += 1; - if(nowDownload >= allDownload) + if (nowDownload >= allDownload) { nowDownload = allDownload; return; } } QString fileName = downloaditemlist[nowDownload - 1]->getName(); - startRequest(urList.at(nowDownload-1), fileName); + startRequest(urList.at(nowDownload - 1), fileName); } } void DownloadListWidget::updateDataReadProgress(QString speedInfo, qint64 bytesRead, qint64 totalBytes) { - if(totalBytes <= 0) + if (totalBytes <= 0) { return; } theSpeed = speedInfo; - downloaditemlist[nowDownload - 1]->setMax(10000); // 最大值 - downloaditemlist[nowDownload - 1]->setValue(int(bytesRead * 100 / totalBytes) * 100); // 当前值 + downloaditemlist[nowDownload - 1]->setMax(10000); // 最大值 + downloaditemlist[nowDownload - 1]->setValue(int(bytesRead * 100 / totalBytes) * 100); // 当前值 emit downloadProgress(int(bytesRead * 100 / totalBytes)); download_size = bytesRead; - if(downloaditemlist[nowDownload - 1]->close) + if (downloaditemlist[nowDownload - 1]->close) { // 随时检测下载是否被取消 downloadController->disconnect(); @@ -175,21 +174,23 @@ void DownloadListWidget::updateDataReadProgress(QString speedInfo, qint64 bytesR } } - -void DownloadListWidget::m_move(int x,int y) +void DownloadListWidget::m_move(int x, int y) { m_rect.setX(x); m_rect.setY(y); - move(x,y); + move(x, y); return; } bool DownloadListWidget::eventFilter(QObject *watched, QEvent *event) { - if (Q_NULLPTR == watched) { + if (Q_NULLPTR == watched) + { return false; } - if (QEvent::ActivationChange == event->type()) { - if(QApplication::activeWindow() != this){ + if (QEvent::ActivationChange == event->type()) + { + if (QApplication::activeWindow() != this) + { this->close(); } } -- Gitee From f351794fb7558f36a47384b43bedd66422edb211 Mon Sep 17 00:00:00 2001 From: uniartisan Date: Fri, 23 Dec 2022 13:59:17 +0800 Subject: [PATCH 03/17] =?UTF-8?q?fix:=20Wayland=20=E5=9C=A8=E6=9F=90?= =?UTF-8?q?=E4=BA=9B=E7=8E=AF=E5=A2=83=E4=B8=8B=E9=94=99=E8=AF=AF=E8=AF=86?= =?UTF-8?q?=E5=88=AB=E4=B8=BA=20dde?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index 8e053a97..640b49f1 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -20,9 +20,11 @@ int main(int argc, char *argv[]) static const QTime buildTime = QTime::fromString(__TIME__, "hh:mm:ss"); // 设置桌面环境环境变量 + bool isDeepinOS = true; if (!QString(qgetenv("XDG_CURRENT_DESKTOP")).toLower().startsWith("deepin")) { setenv("XDG_CURRENT_DESKTOP", "Deepin", 1); + isDeepinOS = false; } bool isWayland = false; auto e = QProcessEnvironment::systemEnvironment(); @@ -34,11 +36,12 @@ int main(int argc, char *argv[]) } qDebug() << "Wayland enabled:" << isWayland; - if (isWayland && !Dtk::Core::DSysInfo::isDDE()) + // Set display backend + if (isWayland && useWayland && !(Dtk::Core::DSysInfo::isDDE() || isDeepinOS)) { qputenv("QT_QPA_PLATFORM", "wayland"); } - else if (isWayland && Dtk::Core::DSysInfo::isDDE()) + else if (isWayland && useWayland && (Dtk::Core::DSysInfo::isDDE() && isDeepinOS)) { qputenv("QT_QPA_PLATFORM", "dwayland"); } -- Gitee From ac8589210fc182bcacde97a1b9fd46a545e82e50 Mon Sep 17 00:00:00 2001 From: uniartisan Date: Fri, 23 Dec 2022 16:30:14 +0800 Subject: [PATCH 04/17] =?UTF-8?q?fix:=20=E4=BF=AE=E5=A4=8D=E9=9D=9Edeepin?= =?UTF-8?q?=E7=9A=84wayland=E7=8E=AF=E5=A2=83=E4=B8=8Bui=E6=98=BE=E7=A4=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main.cpp | 20 +++++++++++++++----- src/mainwindow-dtk.cpp | 19 ++++++++++++++++--- 2 files changed, 31 insertions(+), 8 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index 640b49f1..c4301e42 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -18,6 +18,8 @@ int main(int argc, char *argv[]) static const QString version = "Version 4.1.1"; 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"); + QSettings readConfig(QDir::homePath() + "/.config/spark-store/config.ini", QSettings::IniFormat); + QSettings *setConfig = new QSettings(QDir::homePath() + "/.config/spark-store/config.ini", QSettings::IniFormat); // 设置桌面环境环境变量 bool isDeepinOS = true; @@ -30,11 +32,22 @@ int main(int argc, char *argv[]) auto e = QProcessEnvironment::systemEnvironment(); QString XDG_SESSION_TYPE = e.value(QStringLiteral("XDG_SESSION_TYPE")); QString WAYLAND_DISPLAY = e.value(QStringLiteral("WAYLAND_DISPLAY")); + if (XDG_SESSION_TYPE == QLatin1String("wayland") || WAYLAND_DISPLAY.contains(QLatin1String("wayland"), Qt::CaseInsensitive)) { isWayland = true; } - qDebug() << "Wayland enabled:" << isWayland; + setConfig->setValue("build/isWayland", isWayland); + setConfig->setValue("build/isDeepinOS", isDeepinOS); + + // Check config file, if there is no wayland config, then set it to default, which means use wayland if possible. + if (!readConfig.contains("build/useWayland")) + { + setConfig->setValue("build/useWayland", true); + } + + bool useWayland = readConfig.value("build/useWayland").toBool(); + qDebug() << "System Wayland enabled:" << isWayland << ". Spark Wayland enabled:" << useWayland; // Set display backend if (isWayland && useWayland && !(Dtk::Core::DSysInfo::isDDE() || isDeepinOS)) @@ -77,16 +90,13 @@ int main(int argc, char *argv[]) a.loadTranslator(); // 载入翻译 - QSettings readConfig(QDir::homePath() + "/.config/spark-store/config.ini", QSettings::IniFormat); - if (readConfig.value("build/version").toString() != version) { qDebug() << "Spark Store has been updated!"; - QSettings *setConfig = new QSettings(QDir::homePath() + "/.config/spark-store/config.ini", QSettings::IniFormat); setConfig->setValue("build/version", version); setConfig->setValue("build/time", buildDate.toString("yyyy.MM.dd") + "-" + buildTime.toString()); - setConfig->deleteLater(); } + setConfig->deleteLater(); // Customized DAboutDialog diff --git a/src/mainwindow-dtk.cpp b/src/mainwindow-dtk.cpp index 6c47115a..c9b6c729 100644 --- a/src/mainwindow-dtk.cpp +++ b/src/mainwindow-dtk.cpp @@ -3,6 +3,7 @@ #include #include +#include #include #define AppPageApplist 0 @@ -63,8 +64,7 @@ MainWindow::MainWindow(QWidget *parent) { qDebug() << "投稿器不存在,跳转页面"; openUrl(submitterSpk); - } - }); + } }); // 主题切换 connect(DGuiApplicationHelper::instance(), &DGuiApplicationHelper::themeTypeChanged, this, [=](DGuiApplicationHelper::ColorType themeType) @@ -153,6 +153,10 @@ MainWindow::MainWindow(QWidget *parent) downloadlistwidget->hide(); backButtom->hide(); ui->titlebar->setIcon(QIcon::fromTheme(":/icon/logo.svg")); + + // Check wayland configs + QSettings readConfig(QDir::homePath() + "/.config/spark-store/config.ini", QSettings::IniFormat); + QWidget *w_titlebar = new QWidget(ui->titlebar); QHBoxLayout *ly_titlebar = new QHBoxLayout(w_titlebar); QLabel *title = new QLabel(this); @@ -160,7 +164,16 @@ MainWindow::MainWindow(QWidget *parent) searchEdit->setPlaceholderText(tr("Search or enter spk://")); ly_titlebar->addWidget(title); ly_titlebar->addWidget(backButtom); - ly_titlebar->addStretch(2.5); + + if (!readConfig.value("build/isDeepinOS").toBool() && readConfig.value("build/useWayland").toBool()) + { + ly_titlebar->addStretch(1); + } + else + { + ly_titlebar->addStretch(2); + } + ly_titlebar->addWidget(searchEdit); ly_titlebar->addWidget(downloadButton); ly_titlebar->addStretch(1); -- Gitee From b275cef0e18b1fbd4209309e4d9907d8a0d6cbe3 Mon Sep 17 00:00:00 2001 From: uniartisan Date: Fri, 23 Dec 2022 16:46:32 +0800 Subject: [PATCH 05/17] =?UTF-8?q?enhance:=20=E6=B6=88=E9=99=A4=20c11=20?= =?UTF-8?q?=E6=A0=87=E5=87=86=E8=AD=A6=E5=91=8A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main.cpp | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index c4301e42..36ffcf35 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -69,8 +69,13 @@ int main(int argc, char *argv[]) QVector fakeArgs(argc + 2); fakeArgs[0] = argv[0]; - fakeArgs[1] = "-platformtheme"; - fakeArgs[2] = "deepin"; + QString fakeArgs1 = "-platformtheme"; + QByteArray fakeArgsTemp = fakeArgs1.toLatin1(); // must + fakeArgs[1] = fakeArgsTemp.data(); + fakeArgs1 = "deepin"; + fakeArgsTemp = fakeArgs1.toLatin1(); // must + fakeArgs[2] = fakeArgsTemp.data(); + for (int i = 1; i < argc; i++) fakeArgs[i + 2] = argv[i]; int fakeArgc = argc + 2; // DApplication的argc要用引用,避免c++编译器优化 -- Gitee From 2ad80f55a35b6ad8f0a459de237145c6b24229eb Mon Sep 17 00:00:00 2001 From: uniartisan Date: Fri, 23 Dec 2022 18:11:44 +0800 Subject: [PATCH 06/17] =?UTF-8?q?fix:=20=E4=BF=AE=E5=A4=8D=E7=BC=96?= =?UTF-8?q?=E8=AF=91=E4=BE=9D=E8=B5=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- debian/control | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/debian/control b/debian/control index e85011b3..0af650ef 100644 --- a/debian/control +++ b/debian/control @@ -17,7 +17,9 @@ Build-Depends: qttools5-private-dev, qtwebengine5-dev, qtwayland5, - qtwayland5-dev-tools + qtwayland5-dev-tools, + gcc, + g++, Standards-Version: 3.0 Homepage: https://www.spark-app.store/ @@ -30,17 +32,15 @@ Depends:${shlibs:Depends}, ${misc:Depends}, libqt5widgets5, libqt5network5, libqt5concurrent5, + qtwayland5, libdtkcore5, libdtkgui5, libdtkwidget5, curl, openssl, - libssl-dev, dde-qt5integration, bubblewrap, aria2, - gcc, - g++, zenity Description: Spark Store A community powered app store, based on DTK. -- Gitee From ef7c4f8afb3523a3b3eb5778e25a13b325596300 Mon Sep 17 00:00:00 2001 From: momen <954551908@qq.com> Date: Fri, 23 Dec 2022 10:12:18 +0000 Subject: [PATCH 07/17] =?UTF-8?q?!176=20=E8=AE=A9=E6=B5=8F=E8=A7=88?= =?UTF-8?q?=E5=99=A8=E8=8E=B7=E5=8F=96=E4=B8=AD=E6=96=87=E9=A1=B5=E9=9D=A2?= =?UTF-8?q?=20*=20!1=20enhanced:=20=E5=88=A4=E6=96=AD=E7=B3=BB=E7=BB=9F?= =?UTF-8?q?=E8=AF=AD=E8=A8=80=EF=BC=8C=E4=B8=AD=E6=96=87=E5=88=99=E4=BF=AE?= =?UTF-8?q?=E6=94=B9=E8=AF=B7=E6=B1=82=E5=A4=B4=EF=BC=8C=E8=AF=B7=E6=B1=82?= =?UTF-8?q?=E4=B8=AD=E6=96=87=E7=BD=91=E9=A1=B5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/widgets/common/webenginepage.cpp | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/src/widgets/common/webenginepage.cpp b/src/widgets/common/webenginepage.cpp index af7a050b..f52b336d 100644 --- a/src/widgets/common/webenginepage.cpp +++ b/src/widgets/common/webenginepage.cpp @@ -1,10 +1,26 @@ #include "webenginepage.h" #include +#include +#include WebEnginePage::WebEnginePage(QObject *parent) : QWebEnginePage(parent) { + QLocale ql; + switch (ql.language()) + { + case QLocale::Chinese: + { + // 系统语言是中文,获取网页为中文 @momen @uniartisan + QWebEngineProfile *profile = QWebEngineProfile::defaultProfile(); + qDebug() << profile->httpAcceptLanguage(); + profile->setHttpAcceptLanguage("zh-CN,zh;q=0.8,en;q=0.6"); + } + break; + default: + break; + } } WebEnginePage::~WebEnginePage() -- Gitee From 9cde4319d088afae6ff316720bf4dc7c646b68c2 Mon Sep 17 00:00:00 2001 From: uniartisan Date: Fri, 23 Dec 2022 18:28:38 +0800 Subject: [PATCH 08/17] =?UTF-8?q?fix:=20=E5=AE=89=E8=A3=85=E4=BE=9D?= =?UTF-8?q?=E8=B5=96=E7=BC=BA=E5=A4=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- debian/control | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/debian/control b/debian/control index 0af650ef..64f2f145 100644 --- a/debian/control +++ b/debian/control @@ -19,7 +19,7 @@ Build-Depends: qtwayland5, qtwayland5-dev-tools, gcc, - g++, + g++ Standards-Version: 3.0 Homepage: https://www.spark-app.store/ @@ -41,6 +41,8 @@ Depends:${shlibs:Depends}, ${misc:Depends}, dde-qt5integration, bubblewrap, aria2, + gcc, + g++, zenity Description: Spark Store A community powered app store, based on DTK. -- Gitee From 6a7445dbbaecb7bbd7a0848ac28d08615d92362f Mon Sep 17 00:00:00 2001 From: uniartisan Date: Fri, 23 Dec 2022 18:42:19 +0800 Subject: [PATCH 09/17] =?UTF-8?q?enhance:=20=E4=B8=8B=E8=BD=BD=E5=88=97?= =?UTF-8?q?=E8=A1=A8=E6=96=B0=E5=A2=9E=20wayland=20=E7=AA=97=E5=8F=A3?= =?UTF-8?q?=E6=A0=87=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/widgets/downloadlistwidget.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/widgets/downloadlistwidget.cpp b/src/widgets/downloadlistwidget.cpp index e778175f..6c611150 100644 --- a/src/widgets/downloadlistwidget.cpp +++ b/src/widgets/downloadlistwidget.cpp @@ -7,6 +7,7 @@ DownloadListWidget::DownloadListWidget(QWidget *parent) : DBlurEffectWidget(pare ui(new Ui::DownloadListWidget) { ui->setupUi(this); + setWindowTitle("Download list"); installEventFilter(this); this->setAttribute(Qt::WA_Hover, true); setFocus(); -- Gitee From 63e436c0cc576c26d44c3fdc2c21c7635e1957df Mon Sep 17 00:00:00 2001 From: shenmo Date: Fri, 23 Dec 2022 13:55:40 +0000 Subject: [PATCH 10/17] update debian/changelog. Signed-off-by: shenmo --- debian/changelog | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/debian/changelog b/debian/changelog index 6a5a7054..e06224f6 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,12 @@ +spark-store (4.1.2) stable; urgency=medium + + * feat: 初步的wayland支持 + * fix: 首页的捐赠页面在中文环境下显示中文 + * chore: 新增编译依赖 + +-- shenmo Fri, 30 Jan 2022 00:00:00 +0800 + + spark-store (4.1.1) stable; urgency=medium * fix:更新失效 -- Gitee From ea4f28cd429db49b311d71604c72554ccb652d31 Mon Sep 17 00:00:00 2001 From: shenmo Date: Fri, 23 Dec 2022 13:55:58 +0000 Subject: [PATCH 11/17] update src/main.cpp. Signed-off-by: shenmo --- src/main.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main.cpp b/src/main.cpp index 36ffcf35..e8f93934 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -15,7 +15,7 @@ DWIDGET_USE_NAMESPACE int main(int argc, char *argv[]) { // Get build time - static const QString version = "Version 4.1.1"; + static const QString version = "Version 4.1.2"; 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"); QSettings readConfig(QDir::homePath() + "/.config/spark-store/config.ini", QSettings::IniFormat); -- Gitee From c9bec86bed2b4bc0d246df960383513a09d1b021 Mon Sep 17 00:00:00 2001 From: shenmo Date: Sat, 24 Dec 2022 01:14:25 +0000 Subject: [PATCH 12/17] =?UTF-8?q?fix:=20aptss=20ssupdate=E5=87=BA=E9=94=99?= =?UTF-8?q?=E6=97=B6=E4=B8=8D=E5=86=8D=E9=94=81=E6=AD=BB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: shenmo --- tool/update-upgrade/ss-do-upgrade.sh | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tool/update-upgrade/ss-do-upgrade.sh b/tool/update-upgrade/ss-do-upgrade.sh index 1aebc948..5b5cf952 100755 --- a/tool/update-upgrade/ss-do-upgrade.sh +++ b/tool/update-upgrade/ss-do-upgrade.sh @@ -12,6 +12,7 @@ else zenity --error --text "检查更新进程出现错误!按确定查看报错,可用于反馈" --title "星火商店更新检测模块" --height 200 --width 350 --window-icon=/usr/share/icons/hicolor/scalable/apps/spark-store.svg zenity --text-info --filename=/tmp/spark-store-app-ssupdate-log.txt --checkbox="我已复制了此文本框中的日志,且将会在反馈时附上。反馈渠道可以在右上角菜单的设置中找到" --title="反馈渠道在商店右上角的设置里" --window-icon=/usr/share/icons/hicolor/scalable/apps/spark-store.svg pkexec /opt/durapps/spark-store/bin/update-upgrade/ss-do-upgrade-worker.sh clean-log + rm -f /tmp/spark-store/upgradeStatus.txt exit fi @@ -77,5 +78,5 @@ done` fi fi -rm -f touch /tmp/spark-store/upgradeStatus.txt +rm -f /tmp/spark-store/upgradeStatus.txt # 从最开头 -- Gitee From 8cc869872c5b345916be023abd651c804a5dbf09 Mon Sep 17 00:00:00 2001 From: uniartisan Date: Sat, 24 Dec 2022 10:01:27 +0800 Subject: [PATCH 13/17] =?UTF-8?q?enhance:=20=E9=99=90=E5=88=B6=E5=BE=AA?= =?UTF-8?q?=E7=8E=AF=E5=8F=98=E9=87=8F=E7=9A=84=E4=BD=9C=E7=94=A8=E8=8C=83?= =?UTF-8?q?=E5=9B=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/mainwindow-dtk.cpp | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/src/mainwindow-dtk.cpp b/src/mainwindow-dtk.cpp index c9b6c729..6686c082 100644 --- a/src/mainwindow-dtk.cpp +++ b/src/mainwindow-dtk.cpp @@ -80,8 +80,7 @@ MainWindow::MainWindow(QWidget *parent) downloadButton->setBackgroundColor(QColor("#444444")); downloadButton->setColor(QColor("#66CCFF")); ui->pushButton_14->setIcon(QIcon(":/icon/dark/update.svg")); - int i = 0; - while (i < ui->buttonGroup->buttons().size()) { + for (int i = 0; i < ui->buttonGroup->buttons().size(); i++) { ui->buttonGroup->buttons()[i]->setIcon(QIcon(":/icon/dark/leftbutton_" + QString::number(i) + ".svg")); if (QLocale::system().name() == "zh_CN") { ui->buttonGroup->buttons()[i]->setStyleSheet("QPushButton{background-color:transparent;}\ @@ -92,7 +91,6 @@ MainWindow::MainWindow(QWidget *parent) QPushButton:hover{background-color:#7a7a7a;border:0px;border-radius:8px;text-align: left; padding-left: 15px;}\ QPushButton:checked{background-color:#6e6e6e;border:0px;border-radius:8px;text-align: left; padding-left: 15px;}"); } - i++; } } else { //亮色模式 @@ -105,8 +103,7 @@ MainWindow::MainWindow(QWidget *parent) downloadButton->setColor(QColor("#66CCFF")); downloadButton->setIcon(":/icon/light/download.svg"); ui->pushButton_14->setIcon(QIcon(":/icon/light/update.svg")); - int i = 0; - while (i < ui->buttonGroup->buttons().size()) { + for (int i = 0; i < ui->buttonGroup->buttons().size(); i++) { ui->buttonGroup->buttons()[i]->setIcon(QIcon(":/icon/light/leftbutton_" + QString::number(i) + ".svg")); if (QLocale::system().name() == "zh_CN") { ui->buttonGroup->buttons()[i]->setStyleSheet("QPushButton{background-color:transparent;}\ @@ -117,7 +114,6 @@ MainWindow::MainWindow(QWidget *parent) QPushButton:hover{background-color:#eAeAeA;border:0px;border-radius:8px;text-align: left; padding-left: 15px;}\ QPushButton:checked{background-color:#dddddd;border:0px;border-radius:8px;text-align: left; padding-left: 15px;}"); } - i++; } } ui->pushButton_14->setStyleSheet(ui->pushButton_4->styleSheet()); -- Gitee From 1c1dbd3e7d4ba40132b969854d4585d884263ad2 Mon Sep 17 00:00:00 2001 From: uniartisan Date: Sat, 24 Dec 2022 10:29:55 +0800 Subject: [PATCH 14/17] =?UTF-8?q?enhance:=20=E8=A7=84=E8=8C=83=E4=BB=A3?= =?UTF-8?q?=E7=A0=81=E8=A1=8C=E4=B8=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/mainwindow-dtk.cpp | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/src/mainwindow-dtk.cpp b/src/mainwindow-dtk.cpp index 6686c082..8df18ec1 100644 --- a/src/mainwindow-dtk.cpp +++ b/src/mainwindow-dtk.cpp @@ -10,6 +10,9 @@ #define AppPageSearchlist 1 #define AppPageAppdetail 2 #define AppPageSettings 3 +#define WaylandSearchCenter 1 +#define OtherSearchCenter 2 +#define RightSearchSpace 1 MainWindow::MainWindow(QWidget *parent) : BaseWidgetOpacity(parent), ui(new Ui::MainWindow) @@ -163,16 +166,18 @@ MainWindow::MainWindow(QWidget *parent) if (!readConfig.value("build/isDeepinOS").toBool() && readConfig.value("build/useWayland").toBool()) { - ly_titlebar->addStretch(1); + // Wayland 搜索栏居中 + ly_titlebar->addStretch(WaylandSearchCenter); } else { - ly_titlebar->addStretch(2); + // dwayland dxcb 搜索栏顶部右侧居中 + ly_titlebar->addStretch(OtherSearchCenter); } ly_titlebar->addWidget(searchEdit); ly_titlebar->addWidget(downloadButton); - ly_titlebar->addStretch(1); + ly_titlebar->addStretch(RightSearchSpace); ui->titlebar->setCustomWidget(w_titlebar); // 侧边栏按钮 int i = 0; @@ -310,6 +315,7 @@ void MainWindow::on_pushButton_14_clicked() auto upgradeP = new QProcess(); upgradeP->startDetached("/opt/durapps/spark-store/bin/update-upgrade/ss-do-upgrade.sh"); upgradeP->waitForStarted(); - upgradeP->waitForFinished(-1); }); + upgradeP->waitForFinished(-1); + upgradeP->deleteLater(); }); } } -- Gitee From 30e800c3a4cfb5bd6dc418a236aa71edc508008a Mon Sep 17 00:00:00 2001 From: shenmo Date: Sun, 25 Dec 2022 03:21:04 +0000 Subject: [PATCH 15/17] update debian/changelog. Signed-off-by: shenmo --- debian/changelog | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/debian/changelog b/debian/changelog index e06224f6..92bb217b 100644 --- a/debian/changelog +++ b/debian/changelog @@ -2,7 +2,8 @@ spark-store (4.1.2) stable; urgency=medium * feat: 初步的wayland支持 * fix: 首页的捐赠页面在中文环境下显示中文 - * chore: 新增编译依赖 + * chore: 新增编译依赖,测试安装时不会出现报错 + * fix: 更新检测模块在aptss ssupdate操作失败后现在会正确地移除锁而不是错误的残留锁。 -- shenmo Fri, 30 Jan 2022 00:00:00 +0800 -- Gitee From 809f68fbd7c5f9bccc2bddb7349d0180fd8b8302 Mon Sep 17 00:00:00 2001 From: shenmo Date: Sun, 25 Dec 2022 12:43:51 +0800 Subject: [PATCH 16/17] =?UTF-8?q?=E6=8A=8A=E9=BB=98=E8=AE=A4=E7=9A=84READM?= =?UTF-8?q?E=E6=94=B9=E6=88=90=E8=8B=B1=E6=96=87?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 53 ++++++++++++++++++++---------------- README.en.md => README.zh.md | 53 ++++++++++++++++-------------------- 2 files changed, 53 insertions(+), 53 deletions(-) rename README.en.md => README.zh.md (35%) diff --git a/README.md b/README.md index b9022b3b..60facca8 100644 --- a/README.md +++ b/README.md @@ -1,50 +1,53 @@ -# 星火应用商店 +# Spark App Store [![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) -众所周知,国内的Linux应用比较少,wine应用难以获取,优质工具分散在民间各大论坛,无法形成合力,难以改善生态 +Spark Store aims to collect Linux apps for the convieniece of Linux new comers -生态构建需要的不是某一方的单打独斗,而是人人行动起来,汇聚星火,产生燎原之势 +The collecting process needs everyone's help -我们创建了这个应用商店,广泛收录大家需要的软件包,搜集优质小工具,主动适配wine应用,存放到储存库供大家获取 -我们支持:Deepin 20 ; Ubuntu 22.04 LTS / Ubuntu 20.04 LTS(将会逐渐停止支持) ; UOS Home 21 +We set up this APP Store and collect APPs/tools that everyone need widely. Also we pack Windows apps with wine. -## 关于协作:分支相关的文档见 [这里](https://deepin-community-store.gitee.io/spark-wiki/#/Dev/Spark-Store-Git-Repo) +All packages will be shared in our repository for users to get freely. -*关于OpenKylin和deepin 23* +Distrobution supported:Deepin 20 ; Ubuntu 22.04 LTS / Ubuntu 20.04 LTS(May stop support in the future) ; UniontechOS Home 21 -支持计划将会在对应系统发布正式版之后开始评估和执行 +*About OpenKylin and deepin 23* -希望看到这里的人也可以加入我们的队伍,开发或者投递应用都很欢迎,共同构建Linux应用生态 +The adaptation work is scheduled after their official release. -在这里追踪我们的Issue处理情况 https://gitee.com/deepin-community-store/spark-store/board +You can track our Issue resoving progress here https://gitee.com/deepin-community-store/spark-store/board -如果有想要提交的软件包,请 [在这里投稿](https://upload.deepinos.org/index) +We hope people who see here can also join our team,development help or submit applications are welcomed -## 🙌 简单的开始 +If you want to submit an APP to share with others,Please [Click here](https://upload.deepinos.org/index) -如果想安装 `星火应用商店` ,请打开右侧的 [Release] 页面,找到最新版本,并选择适用于当前系统的安装包下载。 -如果你在使用 `Debian 11/Ubuntu 20.04`,你需要额外下载[依赖补充包](https://code.gitlink.org.cn/shenmo7192/spark-store-dependencies/raw/branch/master/spark-store-dependencies-kylin.zip) +## 🙌 A simple start + +If you simply want to install the Spark Store,just enter the [Release] page, find the version you want and install. + +If you are using Debian11/Ubuntu 20.04, you will need extra dependency package. Available [here](https://code.gitlink.org.cn/shenmo7192/spark-store-dependencies/raw/branch/master/spark-store-dependencies-kylin.zip) --- -#### 编译安装 +#### Compile and developement -Deepin V20/UOS 21 系统下, 安装依赖 +For Deepin V20/UOS 21/ Debian 11 ```shell sudo apt install git qt5-default debhelper pkg-config qtchooser libqt5core5a libqt5gui5 libqt5widgets5 libqt5network5 libqt5concurrent5 libdtkcore-dev libdtkgui-dev libdtkwidget-dev qttools5-private-dev libnotify-dev qtwebengine5-dev fakeroot qtwayland5 qtwayland5-dev-tools dde-qt5wayland-plugin ``` -Ubuntu 22.04 系统下, 安装依赖 +Ubuntu 22.04 ```shell -sudo apt install git qtbase5-dev debhelper pkg-config qtchooser libqt5core5a libqt5gui5 libqt5widgets5 libqt5network5 libqt5concurrent5 libdtkcore-dev libdtkgui-dev libdtkwidget-dev qttools5-private-dev libnotify-dev qtwebengine5-dev qtwayland5 qtwayland5-dev-tools +sudo apt install git qtbase5-dev debhelper pkg-config qtchooser libqt5core5a libqt5gui5 libqt5widgets5 libqt5network5 libqt5concurrent5 libdtkcore-dev libdtkgui-dev libdtkwidget-dev qttools5-private-dev libnotify-dev qtwebengine5-dev qtwayland5 qtwayland5-dev-tools ``` -然后 +Then + ```shell git clone https://gitee.com/deepin-community-store/spark-store.git cd spark-store @@ -53,16 +56,18 @@ dpkg-buildpackage -## 🚀 协作 +## 🚀 Coorperation + +We use Gitee as our code hosting platform. Please click here to contact us. -非常感谢有兴趣的开发者或爱好者参与 `星火应用商店` 项目,分享你的见解与思路。 +https://gitee.com/deepin-community-store/spark-store -### 交流平台 +### Rocket Chat https://chat.shenmo.tech/ -客户端PWA: +PWA Client: spk://store/chat/store.spark-app.feedback -(安装星火商店后在浏览器打开或复制到搜索栏打开) \ No newline at end of file +(Copy and paste to search bar or in browser address bar after installing Spark Store) \ No newline at end of file diff --git a/README.en.md b/README.zh.md similarity index 35% rename from README.en.md rename to README.zh.md index 60facca8..b9022b3b 100644 --- a/README.en.md +++ b/README.zh.md @@ -1,53 +1,50 @@ -# Spark App Store +# 星火应用商店 [![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) -Spark Store aims to collect Linux apps for the convieniece of Linux new comers +众所周知,国内的Linux应用比较少,wine应用难以获取,优质工具分散在民间各大论坛,无法形成合力,难以改善生态 -The collecting process needs everyone's help +生态构建需要的不是某一方的单打独斗,而是人人行动起来,汇聚星火,产生燎原之势 -We set up this APP Store and collect APPs/tools that everyone need widely. Also we pack Windows apps with wine. +我们创建了这个应用商店,广泛收录大家需要的软件包,搜集优质小工具,主动适配wine应用,存放到储存库供大家获取 +我们支持:Deepin 20 ; Ubuntu 22.04 LTS / Ubuntu 20.04 LTS(将会逐渐停止支持) ; UOS Home 21 -All packages will be shared in our repository for users to get freely. +## 关于协作:分支相关的文档见 [这里](https://deepin-community-store.gitee.io/spark-wiki/#/Dev/Spark-Store-Git-Repo) -Distrobution supported:Deepin 20 ; Ubuntu 22.04 LTS / Ubuntu 20.04 LTS(May stop support in the future) ; UniontechOS Home 21 +*关于OpenKylin和deepin 23* -*About OpenKylin and deepin 23* +支持计划将会在对应系统发布正式版之后开始评估和执行 -The adaptation work is scheduled after their official release. +希望看到这里的人也可以加入我们的队伍,开发或者投递应用都很欢迎,共同构建Linux应用生态 -You can track our Issue resoving progress here https://gitee.com/deepin-community-store/spark-store/board +在这里追踪我们的Issue处理情况 https://gitee.com/deepin-community-store/spark-store/board +如果有想要提交的软件包,请 [在这里投稿](https://upload.deepinos.org/index) -We hope people who see here can also join our team,development help or submit applications are welcomed -If you want to submit an APP to share with others,Please [Click here](https://upload.deepinos.org/index) +## 🙌 简单的开始 +如果想安装 `星火应用商店` ,请打开右侧的 [Release] 页面,找到最新版本,并选择适用于当前系统的安装包下载。 -## 🙌 A simple start - -If you simply want to install the Spark Store,just enter the [Release] page, find the version you want and install. - -If you are using Debian11/Ubuntu 20.04, you will need extra dependency package. Available [here](https://code.gitlink.org.cn/shenmo7192/spark-store-dependencies/raw/branch/master/spark-store-dependencies-kylin.zip) +如果你在使用 `Debian 11/Ubuntu 20.04`,你需要额外下载[依赖补充包](https://code.gitlink.org.cn/shenmo7192/spark-store-dependencies/raw/branch/master/spark-store-dependencies-kylin.zip) --- -#### Compile and developement +#### 编译安装 -For Deepin V20/UOS 21/ Debian 11 +Deepin V20/UOS 21 系统下, 安装依赖 ```shell sudo apt install git qt5-default debhelper pkg-config qtchooser libqt5core5a libqt5gui5 libqt5widgets5 libqt5network5 libqt5concurrent5 libdtkcore-dev libdtkgui-dev libdtkwidget-dev qttools5-private-dev libnotify-dev qtwebengine5-dev fakeroot qtwayland5 qtwayland5-dev-tools dde-qt5wayland-plugin ``` -Ubuntu 22.04 +Ubuntu 22.04 系统下, 安装依赖 ```shell -sudo apt install git qtbase5-dev debhelper pkg-config qtchooser libqt5core5a libqt5gui5 libqt5widgets5 libqt5network5 libqt5concurrent5 libdtkcore-dev libdtkgui-dev libdtkwidget-dev qttools5-private-dev libnotify-dev qtwebengine5-dev qtwayland5 qtwayland5-dev-tools +sudo apt install git qtbase5-dev debhelper pkg-config qtchooser libqt5core5a libqt5gui5 libqt5widgets5 libqt5network5 libqt5concurrent5 libdtkcore-dev libdtkgui-dev libdtkwidget-dev qttools5-private-dev libnotify-dev qtwebengine5-dev qtwayland5 qtwayland5-dev-tools ``` -Then - +然后 ```shell git clone https://gitee.com/deepin-community-store/spark-store.git cd spark-store @@ -56,18 +53,16 @@ dpkg-buildpackage -## 🚀 Coorperation - -We use Gitee as our code hosting platform. Please click here to contact us. +## 🚀 协作 -https://gitee.com/deepin-community-store/spark-store +非常感谢有兴趣的开发者或爱好者参与 `星火应用商店` 项目,分享你的见解与思路。 -### Rocket Chat +### 交流平台 https://chat.shenmo.tech/ -PWA Client: +客户端PWA: spk://store/chat/store.spark-app.feedback -(Copy and paste to search bar or in browser address bar after installing Spark Store) \ No newline at end of file +(安装星火商店后在浏览器打开或复制到搜索栏打开) \ No newline at end of file -- Gitee From 5f533ed619a047263e591c4049fcb15c7caccebf Mon Sep 17 00:00:00 2001 From: zty199 <46324746+zty199@users.noreply.github.com> Date: Sun, 25 Dec 2022 15:03:47 +0800 Subject: [PATCH 17/17] =?UTF-8?q?fix:=20=E4=BF=AE=E5=A4=8D=E4=B8=BB?= =?UTF-8?q?=E7=AA=97=E5=8F=A3=E5=85=B3=E9=97=AD=E5=90=8E=EF=BC=8C=E5=85=B3?= =?UTF-8?q?=E4=BA=8E=E7=AA=97=E5=8F=A3=E6=B2=A1=E6=9C=89=E8=87=AA=E5=8A=A8?= =?UTF-8?q?=E5=85=B3=E9=97=AD=E7=9A=84=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 关于窗口未指定父对象,未按照重载 DApplication::handleAboutAction 方式实现 Log: 1. 添加 Application 类,继承 DApplication,将 main 函数中设置属性、关于信息等操作移至 Application 构造函数中进行 1.1. 添加 setOrganizationName 操作,设置组织名称为 spark-union,与 SWRT 保持一致 1.2. 设置组织名称后,QStandardPaths::AppConfigLocation 等路径相应改变,修改所有配置文件和缓存文件路径(server.list/config.ini 等) 1.3. 关于对话框设置父对象后,对话框背景色受主窗口样式表影响,移动部分控件样式表设置方式与位置 2. 修复关于窗口不显示组织 Logo 的问题,补充丢失的资源文件,整理资源文件 3. 去除 .pro 文件中无效的更新翻译文件脚本调用,整理 .pro 文件,添加编译时更新 ts 文件脚本调用 4. 继续修复偶现关闭客户端时崩溃问题(疑似 aria2c 进程未启动,pid 未初始化为随机值,执行 kill 操作时未判断导致) 5. 修复进入详情页时焦点默认在分享链接按钮上的问题 6. 暂时去除没有意义的 DBus 接口,使用 DGuiApplicationHelper::newProcessInstance 获取新进程的启动参数 7. 更新翻译文件,去除已经不存在的翻译 --- debian/changelog | 125 ++--- spark-store-project.pro | 12 +- src/application.cpp | 101 ++++ src/application.h | 27 + src/assets/assets.qrc | 129 ++--- src/assets/icon/Logo-Spark.png | Bin 46967 -> 10917 bytes src/backend/downloadworker.cpp | 34 +- src/backend/downloadworker.h | 2 +- src/backend/sparkapi.cpp | 43 +- src/backend/sparkapi.h | 16 +- src/main.cpp | 131 ++--- src/mainwindow-dtk.cpp | 39 +- src/mainwindow-dtk.h | 16 +- src/mainwindow-dtk.ui | 8 +- src/pages/appintopage.cpp | 49 +- src/pages/settingspage.cpp | 83 ++-- src/pages/settingspage.h | 9 +- src/spark-store.pro | 81 ++- src/widgets/common/downloaditem.cpp | 2 +- src/widgets/downloadlistwidget.cpp | 1 - translate_generation.sh | 8 +- translate_update.sh | 6 + translations/spark-store_en.ts | 160 +++--- translations/spark-store_fr.ts | 353 +++---------- translations/spark-store_zh_CN.ts | 735 +++------------------------- 25 files changed, 748 insertions(+), 1422 deletions(-) create mode 100644 src/application.cpp create mode 100644 src/application.h create mode 100755 translate_update.sh diff --git a/debian/changelog b/debian/changelog index 92bb217b..fe510625 100644 --- a/debian/changelog +++ b/debian/changelog @@ -12,66 +12,75 @@ spark-store (4.1.1) stable; urgency=medium * fix:更新失效 --- shenmo Fri, 30 Jan 2022 00:00:00 +0800 + -- shenmo Fri, 30 Jan 2022 00:00:00 +0800 + spark-store (4.1.0) stable; urgency=medium * feat: 现在可以支持UOS签名包问题了 --- shenmo Fri, 30 Jan 2022 00:00:00 +0800 + -- shenmo Fri, 30 Jan 2022 00:00:00 +0800 + spark-store (4.0.1) stable; urgency=medium * feat: 提升Ubuntu下的显示效果 --- shenmo Fri, 30 Jan 2022 00:00:00 +0800 + -- shenmo Fri, 30 Jan 2022 00:00:00 +0800 + spark-store (4.0.0) stable; urgency=medium * feat: 修复了成吨的bug后开始正式版 --- shenmo Fri, 30 Jan 2022 00:00:00 +0800 + -- shenmo Fri, 30 Jan 2022 00:00:00 +0800 + spark-store (4.0.0~test2) stable; urgency=medium * feat: 修复了成吨的bug后开始公测 --- shenmo Fri, 30 Jan 2022 00:00:00 +0800 + -- shenmo Fri, 30 Jan 2022 00:00:00 +0800 + spark-store (4.0.0~test1) stable; urgency=medium * feat: 柚子过来补充一下啦 --- shenmo Fri, 30 Jan 2022 00:00:00 +0800 + -- shenmo Fri, 30 Jan 2022 00:00:00 +0800 + spark-store (3.4~test1) stable; urgency=medium * feat: aptss不再尝试安装apt-fast,转而自带 * chore: 删除password-check模块 --- shenmo Fri, 30 Jan 2022 00:00:00 +0800 + -- shenmo Fri, 30 Jan 2022 00:00:00 +0800 + spark-store (3.3.3) stable; urgency=medium * feat: 首页链接调用浏览器打开 --- shenmo Fri, 30 Jan 2022 00:00:00 +0800 + -- shenmo Fri, 30 Jan 2022 00:00:00 +0800 + -0spark-store (3.3.3~test5) stable; urgency=medium +spark-store (3.3.3~test5) stable; urgency=medium * 修复可能的内存泄漏问题 * 修复应用搜索为空但仍显示上一次搜索结果的问题 * 修复动画加载延后的问题 * 修复统计下载量卡主渲染线程的问题 --- shenmo Fri, 30 Jan 2022 00:00:00 +0800 + -- shenmo Fri, 30 Jan 2022 00:00:00 +0800 spark-store (3.3.3~test4) stable; urgency=medium * Enable i386 arch support by default --- shenmo Fri, 30 Jan 2022 00:00:00 +0800 + -- shenmo Fri, 30 Jan 2022 00:00:00 +0800 + spark-store (3.3.3~test3) stable; urgency=medium @@ -84,7 +93,8 @@ spark-store (3.3.3~test2) stable; urgency=medium * bug fix: 更新和检查更新出错时不报错.此更新需要一个推送 --- shenmo Fri, 30 Jan 2022 00:00:00 +0800 + -- shenmo Fri, 30 Jan 2022 00:00:00 +0800 + spark-store (3.3.3~test1) stable; urgency=medium @@ -92,84 +102,89 @@ spark-store (3.3.3~test1) stable; urgency=medium * 图形环境中所有root权限的组件剥离到cli(可用于deepin 23 daily,只保证商店本体正常运作,不处理安装依赖不满足) * 文案更改:更新检查-->检查更新 --- shenmo Fri, 30 Jan 2022 00:00:00 +0800 + -- shenmo Fri, 30 Jan 2022 00:00:00 +0800 + spark-store (3.3.1~test1) stable; urgency=medium * 安装时不再需要联网 --- shenmo Fri, 30 Jan 2022 00:00:00 +0800 + -- shenmo Fri, 30 Jan 2022 00:00:00 +0800 + spark-store (3.3.0.4) stable; urgency=medium * 为减轻服务器压力,不再单独更新某一个应用,而是作为整体更新 + -- shenmo Fri, 30 Jan 2022 00:00:00 +0800 --- shenmo Fri, 30 Jan 2022 00:00:00 +0800 spark-store (3.3.0.3) stable; urgency=medium * 回滚 更新中行为到进度条而不是实时输出 * 更新应用时显示正在更新哪个应用 + -- shenmo Fri, 30 Jan 2022 00:00:00 +0800 --- shenmo Fri, 30 Jan 2022 00:00:00 +0800 spark-store (3.3.0.2) stable; urgency=medium * 修复 pkexec未执行 + -- shenmo Fri, 30 Jan 2022 00:00:00 +0800 --- shenmo Fri, 30 Jan 2022 00:00:00 +0800 spark-store (3.3.0.1) stable; urgency=medium * 修复 检查更新的更新进程未实际运行 + -- shenmo Fri, 30 Jan 2022 00:00:00 +0800 --- shenmo Fri, 30 Jan 2022 00:00:00 +0800 spark-store (3.3) stable; urgency=medium * 修复 检查更新 未刷新软件源 * 把检查更新单独拿出作为左列 --- shenmo Fri, 30 Jan 2022 00:00:00 +0800 + -- shenmo Fri, 30 Jan 2022 00:00:00 +0800 + spark-store (3.3~test3) stable; urgency=medium * 把检查更新加入免密码 --- shenmo Fri, 30 Jan 2022 00:00:00 +0800 + -- shenmo Fri, 30 Jan 2022 00:00:00 +0800 + spark-store (3.3~test2) stable; urgency=medium * 更新检测功能全部更改到zenity --- shenmo Fri, 30 Jan 2022 00:00:00 +0800 + -- shenmo Fri, 30 Jan 2022 00:00:00 +0800 + spark-store (3.3~test1) stable; urgency=medium * zenity,选择可更新应用 * 自动更新检测现在会跳过hold --- shenmo Fri, 30 Jan 2022 00:00:00 +0800 + -- shenmo Fri, 30 Jan 2022 00:00:00 +0800 + spark-store (3.2.4) stable; urgency=medium * 修改tag相关的文案内容:wine相关环境已可自动配置了 * 准备发版 --- shenmo Fri, 30 Jan 2022 00:00:00 +0800 + -- shenmo Fri, 30 Jan 2022 00:00:00 +0800 + spark-store (3.2.4~test4) stable; urgency=medium * 现在在商店启动后点击spk链接仍会正常启动 https://gitee.com/deepin-community-store/spark-store/commit/dd6780d636042bf12d77414e6f1552cc7d1ed24c - - + -- shenmo Fri, 30 Jan 2022 00:00:00 +0800 --- shenmo Fri, 30 Jan 2022 00:00:00 +0800 spark-store (3.2.4~test3) stable; urgency=medium @@ -177,47 +192,47 @@ spark-store (3.2.4~test3) stable; urgency=medium * 翻译完毕 * 合入先前的各项改动,为:客户端集成投稿器入口和支持,修复:安装依赖时间较长时错误地返回“安装完毕”结果,现在客户端版本更新时不关闭免密码登录,UOS安装进程合并正常aptss中 + -- shenmo Fri, 30 Jan 2022 00:00:00 +0800 --- shenmo Fri, 30 Jan 2022 00:00:00 +0800 - spark-store (3.2.4~test2) stable; urgency=medium * 客户端集成投稿器入口和支持 * 修复:安装依赖时间较长时错误地返回“安装完毕”结果 + -- shenmo Fri, 30 Jan 2022 00:00:00 +0800 --- shenmo Fri, 30 Jan 2022 00:00:00 +0800 - spark-store (3.2.4~test1) stable; urgency=medium * 客户端更新时不关闭免密码登录 * UOS合并正常aptss中 + -- shenmo Fri, 30 Jan 2022 00:00:00 +0800 --- shenmo Fri, 30 Jan 2022 00:00:00 +0800 spark-store (3.2.3) stable; urgency=medium * 客户端异常退出时仍然占用资源问题修复 * 降低dtk依赖版本,Debian 11 stable可直接安装 --- shenmo Fri, 30 Jan 2022 00:00:00 +0800 + -- shenmo Fri, 30 Jan 2022 00:00:00 +0800 + spark-store (3.2.2) stable; urgency=medium * aptss will now refresh the system source before doing install, policy....etc * 启动客户端GPU加速支持 --- shenmo Fri, 30 Jan 2022 00:00:00 +0800 + -- shenmo Fri, 30 Jan 2022 00:00:00 +0800 + spark-store (3.2.1) stable; urgency=medium * 更改刷新系统源的功能 + -- shenmo Fri, 30 Jan 2022 00:00:00 +0800 --- shenmo Fri, 30 Jan 2022 00:00:00 +0800 spark-store (3.2) stable; urgency=medium @@ -230,20 +245,22 @@ spark-store (3.2) stable; urgency=medium * 修复 在更新检测设置中的是否开启自动更新检测设置项的显示不随开启或关闭状态改变 * 修复 在检测更新时临时降低优先级到100,防止系统中有且版本一致的包被反复来回更新 --- shenmo Fri, 30 Jan 2022 00:00:00 +0800 + -- shenmo Fri, 30 Jan 2022 00:00:00 +0800 + spark-store (3.1.6) stable; urgency=medium * 修复部分情况下无法选中正确的镜像源的问题 * 合入3.1.5以来的各项修改 --- shenmo Fri, 30 Jan 2022 00:00:00 +0800 + -- shenmo Fri, 30 Jan 2022 00:00:00 +0800 + spark-store (3.1.5-5) stable; urgency=medium * 从所有镜像源中选取最快镜像源高速下载 --- shenmo Fri, 30 Jan 2022 00:00:00 +0800 + -- shenmo Fri, 30 Jan 2022 00:00:00 +0800 spark-store (3.1.5-4) stable; urgency=medium @@ -253,53 +270,54 @@ spark-store (3.1.5-4) stable; urgency=medium * 更新检测服务优化:从分体改为一体 * aptss 支持自动补全 --- shenmo Fri, 30 Jan 2022 00:00:00 +0800 + -- shenmo Fri, 30 Jan 2022 00:00:00 +0800 + spark-store (3.1.5-3) stable; urgency=medium * 包内自带密钥 + -- shenmo Fri, 30 Jan 2022 00:00:00 +0800 --- shenmo Fri, 30 Jan 2022 00:00:00 +0800 spark-store (3.1.5-2) stable; urgency=medium * 下载软件时跳过获取大小,修复部分软件无法下载的问题 * 修复 获取key时出错,指定使用http1.1 + -- shenmo Fri, 30 Jan 2022 00:00:00 +0800 --- shenmo Fri, 30 Jan 2022 00:00:00 +0800 spark-store (3.1.5-1) stable; urgency=medium * 改变更新策略,UOS也下载加速,但是安装不加速 + -- shenmo Fri, 30 Jan 2022 00:00:00 +0800 --- shenmo Fri, 30 Jan 2022 00:00:00 +0800 - spark-store (3.1.5) stable; urgency=medium * 改变更新策略,现在支持应用在更新时引入新依赖 * ss-apt-fast现在默认允许降级,以与apt使用体验一致 + -- shenmo Fri, 30 Jan 2022 00:00:00 +0800 --- shenmo Fri, 30 Jan 2022 00:00:00 +0800 spark-store (3.1.4-2) stable; urgency=medium * 客户端下载使用metalink来支持bt下载加速 * 修复使用更新和安装设置更新商店本体时出错 + -- shenmo Fri, 30 Jan 2022 00:00:00 +0800 --- shenmo Fri, 30 Jan 2022 00:00:00 +0800 spark-store (3.1.4-1) stable; urgency=medium * 安装脚本和检测更新脚本检查网络时间超时时间延长至5s * 修复:ssinstall在没有安装apt-fast的情况下首次安装需要依赖的软件时安装失败 --- shenmo Fri, 30 Jan 2022 00:00:00 +0800 + -- shenmo Fri, 30 Jan 2022 00:00:00 +0800 + spark-store (3.1.4) stable; urgency=medium @@ -312,6 +330,7 @@ spark-store (3.1.4) stable; urgency=medium -- shenmo Fri, 30 Jan 2022 00:00:00 +0800 + spark-store (3.1.3-2) stable; urgency=medium * 调整 现在与系统更新分开,不再导致更新失败 @@ -320,17 +339,17 @@ spark-store (3.1.3-2) stable; urgency=medium * 修改ss-apt-fast的策略,现在除了安装,下载和更新都改用apt * ssinstall 现在也会在不适用ss-apt-fast的时候模拟源了(针对UOS) - -- shenmo Fri, 30 Jan 2022 00:00:00 +0800 + spark-store (3.1.3-1) stable; urgency=medium * 修复 下载提前退出 * 移除 下载量显示 - -- shenmo Fri, 30 Jan 2022 00:00:00 +0800 + spark-store (3.1.3) stable; urgency=medium * Now uses aria2 to download softwares form all mirrors @@ -342,6 +361,7 @@ spark-store (3.1.3) stable; urgency=medium -- shenmo Fri, 30 Jan 2022 00:00:00 +0800 + spark-store (3.1.2) stable; urgency=medium * Now let apt-fast method support all mirrors @@ -350,8 +370,6 @@ spark-store (3.1.2) stable; urgency=medium -- shenmo Mon, 17 Jan 2022 00:00:00 +0800 - - spark-store (3.1.1) stable; urgency=medium * Now will delete the link of policy file after uninstall or upgrade @@ -360,8 +378,6 @@ spark-store (3.1.1) stable; urgency=medium -- shenmo Mon, 17 Jan 2022 00:00:00 +0800 - - spark-store (3.1.0) stable; urgency=medium * Add pkexec policy: ssinstall. Only will be enabled after permitted. @@ -370,7 +386,6 @@ spark-store (3.1.0) stable; urgency=medium -- shenmo Mon, 17 Jan 2022 00:00:00 +0800 - spark-store (3.0.3-13) stable; urgency=medium * Update the ssinstall script. Now support apt-fast and will temporarily increase the spark store source priority to 500 to make depends install correctly @@ -380,7 +395,6 @@ spark-store (3.0.3-13) stable; urgency=medium -- shenmo Mon, 17 Jan 2022 00:00:00 +0800 - spark-store (3.0.3-12) stable; urgency=medium * Rollback to use DApplication::loadDXcbPlugin() to make titlebar behave normally in ubuntu @@ -390,8 +404,6 @@ spark-store (3.0.3-12) stable; urgency=medium -- shenmo Mon, 17 Jan 2022 00:00:00 +0800 - - spark-store (3.0.3-11) stable; urgency=medium * Now support autoupdate @@ -399,8 +411,6 @@ spark-store (3.0.3-11) stable; urgency=medium -- shenmo Mon, 17 Jan 2022 00:00:00 +0800 - - spark-store (3.0.3-10) stable; urgency=medium * Now also compile dstore patch @@ -413,3 +423,4 @@ spark-store (3.0.3-9) stable; urgency=medium * Support dpkg-buildpackage -- shenmo Mon, 17 Jan 2022 00:00:00 +0800 + diff --git a/spark-store-project.pro b/spark-store-project.pro index 1975041d..f0e92ddd 100644 --- a/spark-store-project.pro +++ b/spark-store-project.pro @@ -14,13 +14,11 @@ SUBDIRS += \ src/spark-dstore-patch \ src/spark-store.pro -#TRANSLATIONS += \ -# translations/spark-store_fr.ts \ -# translations/spark-store_en.ts \ -# translations/spark-store_zh_CN.ts - # Update translation files -CONFIG(release, debug|release): system(bash $${PWD}/translate_generation.sh) +CONFIG(release, debug|release) { + system(bash $${PWD}/translate_update.sh) + system(bash $${PWD}/translate_generation.sh) +} # Rules for deployment tool.files += tool/* @@ -64,4 +62,4 @@ INSTALLS += \ service \ bash_completion \ polkit-1 -# 暂时不添加 \ No newline at end of file +# 暂时不添加 diff --git a/src/application.cpp b/src/application.cpp new file mode 100644 index 00000000..73af9701 --- /dev/null +++ b/src/application.cpp @@ -0,0 +1,101 @@ +#include "application.h" + +#include +#include +#include +#include + +#include +#include + +DCORE_USE_NAMESPACE + +Application::Application(int &argc, char **argv) + : DApplication(argc, argv) +{ + // Wayland 环境下使用,防止子控件 Native 化 + if (!DPlatformWindowHandle::pluginVersion().isEmpty()) { + setAttribute(Qt::AA_DontCreateNativeWidgetSiblings, true); + } + setAttribute(Qt::AA_UseHighDpiPixmaps); + + loadTranslator(); // 载入翻译 + + setOrganizationName("spark-union"); + setApplicationName("spark-store"); // 影响 ~/.local/share/spark-union 下文件夹名称 + setApplicationDisplayName(QObject::tr("Spark Store")); // 设置窗口显示标题 (Wayland 下会显示 Qt 原生标题栏) + setProductName(QObject::tr("Spark Store")); + setProductIcon(QIcon::fromTheme("spark-store")); + setApplicationHomePage("https://gitee.com/deepin-community-store"); + setApplicationDescription( + QObject::tr( + "An appstore powered by community
" + "https://www.spark-app.store
" + "Spark developers")); + setApplicationLicense(" GPLv3 "); + + // 检查 ~/.config/spark-union/spark-store 文件夹是否存在 + checkAppConfigLocation(); + + // 初始化日志模块 (默认日志位置 ~/.cache/spark-union/spark-store) + DLogManager::registerConsoleAppender(); + DLogManager::registerFileAppender(); +} + +void Application::handleAboutAction() +{ + if (aboutDialog()) { + DApplication::handleAboutAction(); + return; + } + + initAboutDialog(); + DApplication::handleAboutAction(); +} + +void Application::setVersionAndBuildDateTime(const QString &version, const QString &buildDateTime) +{ + m_version = version; + m_buildDateTime = buildDateTime; + + QSettings config(QStandardPaths::writableLocation(QStandardPaths::AppConfigLocation) + "/config.ini", QSettings::IniFormat); + if (config.value("build/version").toString() != m_version) { + qDebug() << "Spark Store has been updated!"; + + config.setValue("build/version", m_version); + config.setValue("build/time", m_buildDateTime); + config.sync(); + } + + setApplicationVersion(DApplication::buildVersion(config.value("build/version").toString() + "-" + "Flamescion" + "-" + config.value("build/time").toString())); +} + +void Application::checkAppConfigLocation() +{ + QDir dir(QStandardPaths::writableLocation(QStandardPaths::AppConfigLocation)); + if (!dir.exists()) { + qWarning() << "AppConfigLocation not existed, creating..."; + dir.mkpath(dir.absolutePath()); + } +} + +void Application::initAboutDialog() +{ + // Customized DAboutDialog + DAboutDialog *dialog = new DAboutDialog(activeWindow()); + dialog->setProductName(productName()); + dialog->setProductIcon(productIcon()); + dialog->setVersion(translate("DAboutDialog", "Version: %1").arg(applicationVersion())); + // dialog->setCompanyLogo(QPixmap(":/icon/Logo-Spark.png")); // 根据 shenmo 要求,不显示组织 Logo + dialog->setWebsiteName(QObject::tr("Spark Project")); + dialog->setWebsiteLink(applicationHomePage()); + dialog->setDescription(applicationDescription()); + dialog->setLicense(translate("DAboutDialog", "%1 is released under %2").arg(productName()).arg(applicationLicense())); + + setAboutDialog(dialog); + connect(aboutDialog(), &DAboutDialog::destroyed, this, [=] { + setAboutDialog(nullptr); + }); + + dialog->hide(); +} diff --git a/src/application.h b/src/application.h new file mode 100644 index 00000000..993da3f7 --- /dev/null +++ b/src/application.h @@ -0,0 +1,27 @@ +#ifndef APPLICATION_H +#define APPLICATION_H + +#include + +DWIDGET_USE_NAMESPACE + +class Application : public DApplication +{ + Q_OBJECT + +public: + Application(int &argc, char **argv); + void handleAboutAction() override; + + void setVersionAndBuildDateTime(const QString &version, const QString &buildDateTime); + +private: + void checkAppConfigLocation(); + void initAboutDialog(); + +private: + QString m_version; + QString m_buildDateTime; +}; + +#endif // APPLICATION_H diff --git a/src/assets/assets.qrc b/src/assets/assets.qrc index c8d1f97f..ef4b2485 100644 --- a/src/assets/assets.qrc +++ b/src/assets/assets.qrc @@ -1,64 +1,65 @@ - - - icon/logo.svg - tags/a2d-small.png - tags/a2d.png - tags/community-small.png - tags/community.png - tags/community.svg - tags/deepin-small.png - tags/deepin.svg - tags/dtk-small.png - tags/dwine2-small.png - tags/dwine5-small.png - tags/dwine5.svg - tags/logo_icon.svg - tags/ubuntu-small.png - tags/ubuntu.png - tags/uos-authorize.svg - tags/uos-small.png - tags/uos.svg - icon/light/back.svg - icon/light/download.svg - icon/light/leftbutton_0.svg - icon/light/leftbutton_1.svg - icon/light/leftbutton_2.svg - icon/light/leftbutton_3.svg - icon/light/leftbutton_4.svg - icon/light/leftbutton_5.svg - icon/light/leftbutton_6.svg - icon/light/leftbutton_7.svg - icon/light/leftbutton_8.svg - icon/light/leftbutton_9.svg - icon/light/leftbutton_10.svg - icon/light/leftbutton_11.svg - icon/light/leftbutton_12.svg - icon/light/box.svg - icon/light/calendar.svg - icon/light/globe.svg - icon/light/folder.svg - icon/light/text.svg - icon/dark/back.svg - icon/dark/box.svg - icon/dark/calendar.svg - icon/dark/download.svg - icon/dark/folder.svg - icon/dark/globe.svg - icon/dark/leftbutton_0.svg - icon/dark/leftbutton_1.svg - icon/dark/leftbutton_2.svg - icon/dark/leftbutton_3.svg - icon/dark/leftbutton_4.svg - icon/dark/leftbutton_5.svg - icon/dark/leftbutton_6.svg - icon/dark/leftbutton_7.svg - icon/dark/leftbutton_8.svg - icon/dark/leftbutton_9.svg - icon/dark/leftbutton_10.svg - icon/dark/leftbutton_11.svg - icon/dark/leftbutton_12.svg - icon/dark/text.svg - icon/light/update.svg - icon/dark/update.svg - - + + + icon/Logo-Spark.png + icon/dark/back.svg + icon/dark/box.svg + icon/dark/calendar.svg + icon/dark/download.svg + icon/dark/folder.svg + icon/dark/globe.svg + icon/dark/leftbutton_0.svg + icon/dark/leftbutton_1.svg + icon/dark/leftbutton_2.svg + icon/dark/leftbutton_3.svg + icon/dark/leftbutton_4.svg + icon/dark/leftbutton_5.svg + icon/dark/leftbutton_6.svg + icon/dark/leftbutton_7.svg + icon/dark/leftbutton_8.svg + icon/dark/leftbutton_9.svg + icon/dark/leftbutton_10.svg + icon/dark/leftbutton_11.svg + icon/dark/leftbutton_12.svg + icon/dark/text.svg + icon/dark/update.svg + icon/light/back.svg + icon/light/download.svg + icon/light/leftbutton_0.svg + icon/light/leftbutton_1.svg + icon/light/leftbutton_2.svg + icon/light/leftbutton_3.svg + icon/light/leftbutton_4.svg + icon/light/leftbutton_5.svg + icon/light/leftbutton_6.svg + icon/light/leftbutton_7.svg + icon/light/leftbutton_8.svg + icon/light/leftbutton_9.svg + icon/light/leftbutton_10.svg + icon/light/leftbutton_11.svg + icon/light/leftbutton_12.svg + icon/light/box.svg + icon/light/calendar.svg + icon/light/globe.svg + icon/light/folder.svg + icon/light/text.svg + icon/light/update.svg + icon/logo.svg + tags/a2d-small.png + tags/a2d.png + tags/community-small.png + tags/community.png + tags/community.svg + tags/deepin-small.png + tags/deepin.svg + tags/dtk-small.png + tags/dwine2-small.png + tags/dwine5-small.png + tags/dwine5.svg + tags/logo_icon.svg + tags/ubuntu-small.png + tags/ubuntu.png + tags/uos-authorize.svg + tags/uos-small.png + tags/uos.svg + + diff --git a/src/assets/icon/Logo-Spark.png b/src/assets/icon/Logo-Spark.png index 941a4a652676252711fb54a357d72abc56dddfcb..905224c8fe7ee658a431e74f9d31c5f210915895 100644 GIT binary patch literal 10917 zcma)ibyOVRvhF|<2%Z2zgS*4v?k>Syf()*M5AN=+LvSa!Ga)zx2<`+YxVt@m=e~E= zyK9|y*W0`IuI{Su>#EvoclRG%5z0!^XvhS}0000@Rz^bgRmQ#!_74cJ^GDvpwO2uE zDx<0h06?e#0RLbB;Qm$R{}%voWd#8CzXAY!=>Pz(V|JU0z^ehlL|$3~@bXX3>nurn z)gU>_=r{uaC|LgtI6!7L-m4PPMOIM~aR(I#6Z><9l)UGw%F9Jk+eOvbozxNRU~Xj# zB6aa}1d&=fx|jlx|Cy0V|J68v$m~2EKn`9GGggk*{_n8DUsGKsk_-6S9f?S%NvoU3gYB-HryLn9=0uC$hY8=evce=2{kPM7_sR4| ztahX5WY-<)*R{~u&R=igK0cPsTMvhb{+Y*d?MJ|y|M{eYWkXGC&9iX%lZGdmKQPg? zxcaM}#E=Wz4}uKA8Q_Pj-p7_<(jc~#JFMt#a?@UM<+<-V)tLFyolIWBS30jQ)~xy40th&bbD$%c~`Aops}kT-}gS&s+k1NUp?^~N0GIM(U6IXaW(w+2;*8_du7 zQ3~6cp+E6%hc88{#Uihkana7G3aH*84RfDs9-5C(srfCit+&;UyJ63p$hjA36cGY| zi6HwB(ZUa2*81-}Khz+r!BO}zk-R^9kf=R6Tf6N1MdN_1a=bBH4PAVE4d3Bx;&bfw zMOG19v~)gw249d}r5BvMUYvd~n~ub%)jr3aHKPsYy>LuP;4>{S-q8LEwJ*y9NISRn zPF+Rohz@xzl#}dTg@luiFc>;d*2CkdloBFI_K^T0eU;|J<0qt>@yTzvB!9bfl4g<4 zf`w0PQnjbiq?^>Dw($vbO)vIw9X(;`&R!AEW6StsP%ten%yqn^3-zDSPP#zPe?eJ~Ef`Tq!bas+yeuD%?iT+jz(z@Lq<& zGdju=+K=k=V#xAC7S69j{*Rr7Z;>$&!yhkOo_yIcAXSPX2Mw}33enaOTSE0YB zW`ux<{><%hf}^CGmbC(izN$(=OA)EY22KB tWm{5Ze&fz1Ofu&sjMPul8m=Is=+ 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 literal 46967 zcmeFYWmsIzwl3O@ySp|H!Ce9bcXxs|?(XjH5FjDAC%9{n;E>?%65L%va+`c>ul? z`i}E5-mHtNrd=!CWkuo9q`Y!v4H^@q4R+Zx`t7^=`@A%r$e?LSjjC-?~O!;p^m{x$@_9mnvJ9k3X9es(I1KnsXiRofFvt16LZWElr-{xn?I-uwKpi66XJ)VpIFPDc4TP#kSJ9MgdheB}yj zLh345d&xO~JMCLhOysLC>pb#^#5*@LO>4-`Oqr$T!4Qy0)A4lc*@a8wxfYx;(A^K^ z_|R;0`lfRu*Kf65&=w~IZ+cgcaRB#SBZ_$Pw5OqzNbhq@RwwMQi<{@cXRHMYm=k7K z(~z&@<1{7VxvlREp{NZlfBw{vDAQAoWtHc+nIHRH8AKkZ>0 z$aF4wU;2&X$gY08RwnmdMrGZh&FAXcZ6)HU1@rk;kM->^@mH;>iPT#Ej*~xcG#SG@;6V z#k@m;%ilkCC!?ujmQ=EEyb*~Uj@h5O?@@tuAQw2{w4~g>k?`zaXn7Bd?Qp% z1+i`y*(g|KF@v-YHeX*1Kcp>8CBM|!=U$>!{1$`TZme=gI=>8~2J5Awv%j3Qd z8+TX2o!z;iUGq10(OtKfIhRbPHX6t=H36g5DYb8ZcvW>6R5zb}vRihw#G_`*7_jQ|B-I@Ws-jy-MMv78hN=|V~9+L<;hMa|!M7TaVe}_>q?ysNI z&#Tyh_p)%gx`Q;^2+K8Jbp{B{BF2%bXJk5G^%6~0G2Droq-;E$c3L*{5TBYEJVOa; zleo?jkF@fCw8jai`=N9&tVn-)Tkx46Q86WpBJDoSIHYGAWJPtF1%AXpicNYJlRw#_ zGmU9nL>xwyt+0X_L)#wdjPSyzCI*t#Yy=^Eju0-P*_zV5^%xXZ0m?cn!7$0J9C?i5 zUy>?TvudoDfoq#OX-g7A1nkwlqk|M2v>Z{==ZU^ysVWBbk{10B&a!kz$&p_)^&vR!6xQCyLv4L${$=0~!sQfBM9OSD8M~cx^^y z=_m4B_ewYF<%+2?%P(Uptz8tjq?ioC(&e}M;dL;ELjdjkxTbI^wO%ik> z8N0duEHo-5l6wrWdm_x0-XWm8-;oCDJJz&<;NZGOPB8By_icwUmtd%rJT@?D z70y}5fZwHX;HaeN0YUY+6>wunQM&_nz9siEwMrhqxl|&_h-AT4<_(OAPa%!%+xo;8 zJuo)%Of1E1-t{BzhJrf7-y6Y9QM+!7F*$$MbDm1j%q)U>FG%QSEJ}A_3|vMK+9OWp z?DL{TPs+Y2!NRkuljB`M3Zbg45s5@54GE`QOVP>mKvpZ+wj~( zN84Hiq}~K)1ul*QPjSv9wru3vc=6fOB_!MytO+!wwh;`dM-&1IZsIVhSN*VKQ9ADhN8Mo1 z-)Y0>k+ByX$KkMVlE|wrd4r^=Tzqkr@ep3s)CY9SQ%}+|cQ;ZJeFumDnepUBKb;KI z@4Yjr-BR5e1y%syCjcHr0KEKY+p+~+!S|S=2k~UJ4zMC)BHKFi-K%hxcsraVb6_QH zWOQ(krRH$bV&qv8thh;QCOE;2qot|$0{)=<4s1Lhc<+zh2s z5`);Gx68y`{kPPyH0p;0J@Iuh=?zz&dvgurV(On5pFNZ4zBnL_W2;S3&3ly1mT0B~ z7JyvUHFx4+La^Be4Nl-X$uQpMor;;>$IJ@glEkE%gkT4`Rvy#DO%(R%+PLP9as{+ zDAPn+aDqb75Q{b7SPY{N-`c%QVJf;uW1b{VkG%6vd@^~8&>lW|0RG+?Fr`WQ(I1BIGMlv)jXtlpb$Y$Xh)Lr?w*Ahp2 z=^Z*m5)wT5S6k*S!fbpQWK@lPS$=0I@Ntfq1p${*(aL_h&!Qnz9x-cfF?#Ag23r}; zsddI}W{V=o^D%R0Ykk7Twza-vL+tz&azEHi5xAnacioLcWD~H>l~c@MFl?g3P6vZN zR?3OH=;Q8En+CNe%K|%eP<>^~^Gv6l`g&`SKS9mhPelchCm~8Qz8}KT-O(73*fEMD z8jbq?C4kCg^D0iMfGq#m=Nt>cxaAcgb7y&m6)DGu|O zqWjg^ZmXOYLK4H9h#;ZyUL9(nMKYzB@0enK#;l`SZ0>$IEsr20zphGtcBHtod!spw zAjc7p8}woY!f{DDVm^@f9MhH}D$hlY0Ia71Z=7-@Nzs#a!}tKx2x7+&(@&wkrjJu} zJ_)xcX%WhFPEm;HE6E)G-YzKR$Q4OONw1g9Qs9S>m#^qV7TexTAP}R`2|puIlvFsU zN0wX*vYKqHOp&UjqEyLb8a*YY@O*&1$Cr`8G=0-wuFr*`l~;a%oAO5Gq6f6IVvJ5U zibllML4x?oTsgqB7=$ZEixoagG+q1wqh%H2GV?h$O0r9o9b16s;q_}J8DS!^QRoqD zIf*U{Gq`)t+bIDs1;dbKXOyhAtVW}1P2v@m*Q|?+jfgHMfF#c`;w|kn?Lj;|8JP>G z6%yja4oB9bhA2nGWXM(=X^ymD(QbMotyscCnVSybitJu*Zz$||QVku-Tr_p$l#_rJ zZcbhBnTWj&`p%ZMbb_$TWPt`jYX9Q+@p%a>&ObZBL3e6TsfxYx9!=1A`3!jn^Urb6G|8BT*NAHE4vQ z7;P*?nf9jCLDb(tph5b2nVDYw1=c z7A992v!-`~*Tn<~R-`2^2Y_o7^3ue+xO(MR#^Yfdo2jn|;MF?x2iV@-;L~PE#G@|G zg<&kf^4TzR;ivZj0xddPDu)u;Jgq|d(@aqs$HRkaJ_+~Ld~;{%P$fzaZ8Ik`sKVH# zT03ou0@0^pwGz^}Af-=DFzUC4c4vwuQr|>%&xUZZrjX-FomSICd&;7Ct%035iO>SM z9B^T`eAw0UcYSB_5k)?I5Y)f`DMf%45LDtc^370%r(}L2&ul#g8GT}PRvsWy{$dQn z6S(!I#u8D)qQJEWdynf zrp8HIvBR5N*#pd)vcEX4r`y;STv{)L*-p>RFNgd9e5XH z%$-9!H&6iME0&&;Y!f1s5xJ<#zwDjmY95w4<5_?+ncew08Z#6HZ+6z17ggSI(fy{r z)Pt5njtd&+`-Bu6lrHV`TI9a*XUi0k_e134NU0|i!6DS^(}~ChE~nA_;*xPtxJY?y zt2kDYw;l^kkuZ(ja8)gaoP{X3yX^0VnalWag7D1)ubwnctKUY1&QNm+T z9JgU%IaeUyarYyd@-)vTvQ8kIdA`N_1eI?rQ))cy|4FnhL`A6&5B4Agq(bDIbU7_|J9t9B+^n?JxEHF? zYQ`&5Zdsc-6hwR-6gk`olcdH+k1)la+B}~NmHABhfq5&bTdA;o9zx_xOjN?;ZC>m~ zeJAd>d%;tD*fp?>Hp5DkAB&b^N%H(;OinsH>1Sjn!r9^|qC3A8k=Ewptb6Z9)P%C) z(68{5%*B43@Bm{aI%?pYI?})>V6!7;XL0d`M5YW>CcP`*7}30ki$nA36kzpUpUh&X zAePDJc0xt!o^;R)^|KHq&6mh0#M1lVo|mBTZU3X?$Uf7_^p;z?Pagt&51?fS`?sWO z6bp;ZTI$g42OunIh(5WrP|8O}^^3A&C0c$w6?$rafF{bKWVemnXMBadWJ)clp--7ze%nNPi3bxYH6Hw85M#+3)y!Qw5VK-x754oQ|hVap?k2BSdGb-3W7*A6kjz4 zkt1!k_KKe0J0&+wuvzS$5J7{Mex`M}Adey{bn7Pf8_CIC$cZa=2Fy)9sUv{4IFxlg zD}4vHtL5CgFc{~Q+F5ag79G7Ly!+D}q0?sHxNh%g3pKG)Cu_yEIhyqWn$J9p2jy$1Px-u=<6b&is=$y)-33Xr79 zkYROY4k2_EuHdTTYs1$RL_Fud9Xvt^lOS_rwFByu2@0sKJ(+=-U%a!05r8}yRIty4 zJYQlgeXkZ~E%On4KlGQ8^dKKibbRj$yer8akhorh!j)Yg zvMr;A#7r~&!TT9s4^I@Vtngh!OLCw4p%o$#HR2h5I% zr0ORV*m;}N|4^yV4`>gsAWT&SHt=0zdvkDFz^6+tmTJ3DVHJp z(h+8P1Td($VQUT+W$KGKmT-)s&TQAA&39(2{xnO5DSc&-b_s4YiHvIy3gzG7;agR4 z6EH1Y!{ZcP?>W@trjNlw^VUm2>ZW8_&(<0?^se*xlz@JY>_CntURn+{g-U%T>BNbN z2UuPeXB10rs>z+%IG%mIB6-ZTJc@gaCMIba_bH7V*zU+J_v@HU{Wpl(yaG+S<<`%V zDj8qpwS*@^;&;>r=ICHX%i|V5&HHYclY`>o(@vh+5Ig8-G=!-4SxnI82Q!Lk@~J@k z!&YUDZe1Jl@?H>SVcEnu)~a|54PjJGx6hE^zAmYN6Dj@oB<84U@kUuXbZ=gbJZw&d znvoLi!jdGzG|n|8GW3jPC_dDCEowvcW?JftsI<*0SW=TuD|c4X^)AR* znB1QPdTwOZO@FgrqCIQf<1*JKCWIcK6cLomsM??(<-x84VMoFW-r)ptNQh(MBWS_pt4Ke$bS~O8( z!v!y!$&%V@ySf@RST+c470Om_H)=A&tbNipo!@{PiXZUgBkTJ16YeK%>Lp@&Y7xJ_kA`I?Jyh0H}2 zUl?~LYRXTmz{tt`Uy|G2-?c#(XxS>gGoZ59x-lW{s`1ip6;byVU~U~1NgO07T5MAI zK@EG%{2xDEr3_ymrZ$}80OHC_#Sdo+pWQI!5W%{`gO%I(jB?A*A7HtW7$ggg+_173rw zWUL%psUl~7ACT%%*zX!Cj-JZxJ$P8@AOWkGYE8ISE(dhj=(OJQ#6SD}JxVv@K?`-Q#wdM7)t+MUl` zDwu5D$it&1b4AC?u2G8T%bGbn`8kh3qU?PAZsQN<(j$-mE1K(~%B->ovhUbI;&uI^4|kqzSyv z`v|4-S?hOSO6Rz8H+0E(-d?F5(vgAU z3QM2Q)VBSP#Dc@%+6Ax>Zyc+MqxaXBRCQ=2js-qNZkP0WbM~SJrj(5J%tqVRjHD&; zF$zkZ*)n7ed6Sp@gaKYCJxeaZWq-6u%2whxmLnp0Xd^Lk5Zv?FBeeyJ;X7Dar5=6? z|4^L#ssaxCCjL%6_8>3K4U6BlK78`)V+tDcZ4=3C9UXX!siYr=51 zRS-|fFcTz$=!Y#CvisEX*)pFtr)Gu|+I|Gs;V&*9K?zrVqM#3z0NNmo7!%T?^8x=UD z`HFsv%;Muqmz6{Seev3N(xXs&9S3nw1wlqegGVY!i+9rTzZ!WMJB$($rQ!a<} z-Co8CKJ_TA-J?IUyX9^E&-umZdE3vpk}5klM$9&;YPl6YBFX6<(m*??vPyB4H`_U_ zyyb>Vi7N5ke3=Mp$R7s?_m=C27(#Q0gte?b*D@oD&$iwmpt)<#YRx6TPbfw9{mfYz zN=1x&ftClRcPk4xq@S7EjYx2?B3Flx&brFH|IXFa6yYY^_Zdu)|Ep(La@LE!MJ~tT zc+s0*?GqYWAbf!xSJBefUYJI<7QXi%+_AI=M`Ox2q4NurT4%2nORwf;rIg`;=njTk zpKtfi2jCWeeLEFP_0c4D4oE2I_%KthrV3@YrwY(Z;dp(L7FW32Pp~Czv__ayh)%DO z9XOA7@hTN29_6fxKl2;eBS88)O3Z zyD0`;r6!=^b~fOh(~6Z91tX*Aepwpd?4*h(UTWopimFXqf4p?CHD^r`I=X0c4igC< z0VVvZC|y>TV>U7zXhvy*g2R2Kfjl#5gwT+xSjK;Ftbw72K-K0^ryKOK|80-kH-OCM zCS)t4Bm7}@6K6UHhI_R`b{M`o^~%9oT;}PG&3Wo{_t!EJkeEwW!VnD}nJQM=g? zo;W3?0dZJuN}JP0WUEG!GSSSV_?<_{ZA2w7yp78#m0lo*o*3Q9{EhU6#DIdF(saab zTk@h-M$Tt;b)3Cig?UN<0A1V~^1g?TqJn^_qdg1Q%+bW0#mn9a;sXF6_{Pf#Y-(%n z1~M_Xw001pJZtZw1X-I2QEGE5vMD-=n_F4S__&y>`zUFc`q-NCn^C?IMiTTAfDqW5 zyMaMo_I3`g0$xIte|QBT=P$*ql%PK*Zni>{I*KYFaYq+(5Ely<3mdbfm$e56r7#jm z(8bI`KutpG9~6))AxbMZHzxsBR!>h)7EewVM;A+0c7A?-RyGb+4i09B1+%NSgB#e3 z*};|Sh2k#`33FFd7l?4yjt-y~POyoiyPFUtCFDNnALK8xN_s&G|Ixt9^&fgyH#1gQ z$ORYV^FRz(IoR0vnAtd(Irv%sULSH-QSqO(9bEsRB1BJCFR&9UI}01Dz5Rcw;p!&o z@t^Je%Nnj4kk@Wl)y!QT-Ca!0B|Xd?+^GKEsFR($>)+dScQt=0`s25qnFTAvsXs0M zy^gf3qRKz(yvS&2ZSVA_#*6jeEzL~-Y3JnbV)w_!%#_vK&fFg2h%1Dd{lC~l>i@IC zzx+6V$o~i>AmM20{=yD&fPk5!skNEFpHnVA9&WHHuNgBhJHG`p7at!NGe0lb zl$p!KjDw%kjE9|z)AVmtvJS3pUt!i1flnaj+Ao0-ehoR1mI zZeq&J&tt}I%E@nT&d0{{HwtAJYe;B=?f&l73zZp!ii^+Of|HY%mzmdshn<;=ozsNb zgoBfhnVZLgm(7Hq-Gam7FK=Fi6%bXC6{6%|Vf#b=r$ogL>}KKUVlPCgVC~@U^`AF1 ztnJO!-M}xRvGcHT^0INW@$s@lqM4WbKaI4^U0fki`@+f2#=`gKhMB2=6oe2A2_9>E zu%$VxlY`}-8xWTT#9hq6ZjLS*j*fOhlrIi|UTXds3LwFM1i65Mqbc}hF#It#H+vZ; z{}?G^U`y6Nmx8SSo$>#NN!`lP)8T)Q=RZyV$s+3F=IQ8StL&m|Vq zSFne<*`F?e==j$yQ!B88r8#7l{KpXak8EkLOM-N^q)-+#;XZ@KNZ;LX5qL8LEVuEt>=#k`VDWcTubX01m(pbt6@?+%aKr{{1Nrp1jS@xV)&tCeL zoLT16^dmXsDE05Nv%Rl&JFgu0Gj?`|->NE@fS zJ4I@;f!eRKKN@@h5TLxn{ZTx%S8g4$ag0*qw^#%IO5W65Nb0cwmNpIcfB2D1B^_78 z8%F9e155h)&70?k41ih+axAAB@S}mQ5(eO7c3Cl8&s9e>J`e@2GXaZO6~qMi%7!8i zSXn_}Cjcanbp|lABj)KfmniBr)-_lEp%%}t;SGkINu3#98D+o52eC5_@Pba zYbO#2fNzxRcTNwJLQ62kwQ0QeEKKGljK6kGfM&Z``V`~h`+6DtA_yLVFZKdB(mk(u zV0n2^ZyU(wxwg;VNWsH2`bx*-`3wcRo4#oL!f*eu?kn1hAWBZhHHDL#dv|@<+k?0Nkb6CZJW;G z|I8f}7gy95n*rccDtBR{(vV~-j=-TnfFMI2$u7Xh7l+jYp!BV)|w zPaK>(YHH(TgyFT;C%;b2eb`D^ZwZVeVE4YP&;_utoSqV)2E{^Q_ycF!Cl^a7X;BA7F>@i`k-mM&|8SBnuV!>%NmsVVcW6qz~|f>fa> z`o`AQ>A?v!oBLsbBzXYLM60X9Se__A(2;`>Wp}T5{q7DOEg=rZ$=TW6)%EkHC&E{# zh0yquKV1Sdi1yk>)GjBR=Vy;Fd%6IR3qE#RQH8l^e*eJg>i8Qz1moVYR#&_)up4{$ zSW^{*K|RK7kf4a(Q0WcDBjx3dFU=_Z;k>h39dN#RX&#HW7@hDZNU}E|T|ihXD#-7l z@|$c@EuOx$fNfw&Mxv+<79KHaxbF(CQ^GDM;Bi(vg9#P^4GrCK5=sQed(EuQ-(Rj+ zty}}@{yr=`TpB@)cn$ z;S&Aa$o==`)xaM{3HKwO#m-1D{Elj5gsu=0;XiDtczxAyDir) z%d6IY`a8Iw&#}*~OE2-gfS5pfM>7$gnx(0srDpt|wBI=l9Boe2%nYjSAt0va0Rr>$ zncwOREG&f3V--N6;`{fiDxzm-%u1||c&ZLpjVB*`> zauWzDG{1VM_9G9D;I+qqYjuZypa~WH=+wG4eVSY&QINUjD``s~*bvzm;N|TF;NCWZg*K0t8x9W7goJ?CJ`pDqK!6C&2X1H(O!r`9)f_hwKny`v5f(!-eYF`K zL~Aj=cD3i~8u-(BRY0|&+3agj9~=cbWxDoB`q9D=Vj>6ust}-3PTxboZL>SpdIk8v zW53+wy0_F`V1vxtOsgm;Smf{R6SReVj?jMdUAbuwmb8v9EEGk7pK3EHeo^1wv z`I7iXI6#mB5coV>?Kqf_b{|Isdp>Uj{m5!`dPGdp;c>Fo36Lx9t~NAy_VZW>5qyml z8kL<*LW(0dy8T0dN3D(btqZjzSPIDIci&*m`UPg9$v%Un(-(T*4K8$8!qkHZnjo}L zLx7+EwR{+oY1l+D-j&Gu7k2cCU)MXSw|fo{iB`t1P7~i$89CDN-SvegF>zUb-{%2&ek zaH51i$Oyo!#-L4*4v(ofu%TiSs;kiHBgA7fq7jrp>U&MVB~!P+7Jod33!{ny1E7OI zTN_Y3HN04i7&NJ)rKSM@baOCS2Cn^?!geD<>2hJ%h~lLRG4pDiM$;9uD##rZds>nE z=qSZ7TwJH8Xcg{%WUQ<-G{`F7oS}na09`-Dn1$XvOCXLXzIl9vgR3$iCiL!V&Jv6w zVCEI_(PFJN*5%0e`9?pCE14*6GF_s0M+Q->Z$S8VVLOpma9{w>t~hn{U3_c|64K@6 z@tLw|VZ{r^*3di_E*zl-ok<3PeS`HChK|pC?XY_}6vBjr*mU;GyGNfVEA+_m;Wze& zh%=a>jR`QYu>AbR#k2yuJeY$fhmeu+cXur;mEWhlUsUN05_6H1^br~aS~b3{)I!di z^zz}chT1qBsr&H*;3G8Z;|=8FueGzbzCkP~g6W=xKyY<&X%8Va`mGca@{JEZKG9R} z6(B#Kf}*Df(BDr30RZss-NVD2sXY$TCwwYM*v1%7jelbnxV|elr{iic|9pD_luG!> zbMiwQfB@DFFSzyLxq)O9Ugv8=IB1bUq_JJp<_FWyQ6&=IPMu>HdOF z*XQ4lH%IfSsm1>B5o^_zM;I`oEt-ZT<5z;?^3Yq2w)0g6?NU_RV^kYRNH(-dn-C~w zt+j7QbgWkN80WFf;W58$u$t@@UR%0Y@2&xx4k)}gS#_6maS6BwuL}5zuYNwiK}FQ9 z7od%J>!np)lI!C=dBRu?=<7RvbAB^_nP+a+bb1N|CMN?94hRW#bpgV{EG#~q5+Wp| zvo^&kN;qkRj5y6MgXexXi2W`;JdRKmhx5Hsj`3`m>RpqlK7|F-=0qo$yAZ(zaQvCmYYtN-1kA4S-me1 z3v%82p8eWWN#Kj`-RWw(C%n@ilnFV@E588V3KET3JodkQPb^Wv;IuOE>xJm=ox$V* z_nVP7N5GWS)YNJNXs_!@X>$K-)gX_Pr5DM0wyE7`LBU-{wXS<5it7Q$6Rn)%pEWG5 z5;|j7kJ7Un8lqFt$V&|PULgU3*nID%x~ks7I_(Sv{aS8TA5Bc1E|#yVqQwqU8+P^) z5-~S7G!%mhYHkh{w`OSkXw{hBH{e%n$t5QN7Y*kCdDv`uTQg!3MUMagQIw5CG7XVS z;^#jvuZZH|LLYEH%LH&y)vtW#$0vmv0X^jX@%# z>8janZYc)rRR|1LNcC>+9qon(((i3bd)iW+_a% z9xJ3~mM?%NdE@-EFFF+<`v(9xXd0%*{%0k-opciZQ$755)s6~d_ZOR+f~+wWpTyx+ zsU>ih8mV9adFGG>e)7B(0uWTu{<<-q%bIen0gVj>03I3H4=|?z1ko22VTd7!sHK1~ zC<)NXwdhAi012d{--LWUR@)wx^IvKFhCyhs#?Abz(?J3E8|hy~*#eeDf|DAig%tHC!uh~GWW%QW^T z2yGt@T0~S-N=j5XC{kKPWLjpKyYQ4};ztC_r{73ee*pNvqcv!sx+##8jH2ft0gS(X4QZe2s$JdEl9D1VotC~tNjZlQ`y*z7h`n6tT~bh9tn4qLBSr@wVH?+0+>87N%eg3= zU&5nP{*Gr!N!=hHp|{N4lZC!_4off?7#IWugoqp4*hEVW3_)*C_V*8co=lx8fbUWz zLC1jyKl*SP(T>+3XpClf#r%SIQTwMYMuDrpu)BkR&~PXOD!%x$&m0u@PwKI#P4yoq z@&thn>=A=n70HmLJeh`u7UcMVExWWnd1)1!w;cV=U&@K=13VeQn_t23kR@7g#{(?@ z@D-In<+-d^3?L>E@Z=#Tkz5n_lLDb&$O)f?9*4woik1d={{(GjF{hQJJk=>H4{bFm zhJgTX5e=2V6xoSHD-N?>;S&SEY-1~DDjXc3WTfrcW}Ul zORq`rexu63+uL*?Q$a>z2M;$@7GsQ=5Gh=&r!Ivt222gfG-jhwKWKbI#QZuDW~YZo zy3*_+h(-Ev;XYRwfK3;=_ZlkJyQ z9u`O&kW$1&|&h*grFR+F1Pv!LePCkZ<7ANk%RZ>ZiCEB@xE8 zZ_?zE9uau)FhLYbykZtg^2X5Y3A>$Kx4LP9g)@%I-Z%NgBW;`<9am`SkyTHt zW{Bw`qGI7jx3}k#iv+zXW%~fos$PD$%Kr)o91MKyFD0LShV%1>ESug4bEWMOMzH1j z!+~N@?lwZNt2H&<+5V zqfowfcX->*eVQFi$jG?rpyyZ_d(RbVdZ=L|`gp6Cb9ZUdGH-OYZdB-f8@`vb+T)7R7#8mj3x7Z~dKDDe#xJq}a73G8YvJ9L+k zs;Zg^7nFXd&#Pa3vJ5i#m}F~T{58^c4wK7*L7?Q;cd*4x5`7u&`0DFt5=z~)b+ntH}~ z?`V4Rd-@4Nv2kW<4W7{Meu;#nV@d?P;7c(qu)fd+8Rg6I#242+mPx=%X>hO__w4}3 z!EZg<)3&#HkQMvV%!+yVFzo560|Y7ZMLxE@$cr17`3&uM(F&mq9;Fs`UV~!P8Mpd zFlkgAJA$iPvtM&^kdfR@D@!N*d>lP(`B0Zfjf?^i(a=~A2!)qrXW_=gcHJ^jk{ElF zf$;X5gbZ3v1{1qYIeq6enN4>-zOq>xZjn@4qImvIXZKkv zKmVh%sT509T>L$=QcIadqkw=-%w$Xer$xurcT2{zRYWaF$GZs#faV(}dd_N@Mn5$3 zmN@GX112SD=(w2VW0PLJYb0i4FXQ2RfzBi8*p$m3q*NINbk6C+H9xst-C;)GS1v8S zZMQTtGb<`q#n&>nz<3a@#!?Iu5KU2WDeW^z)4Piq@~sDkTiC!-Q%EvR$X#&S{Yjv z2l#mXo-e%%CtNBG?J3 zA-S3~uR~FheivMg+hUbLp>!f~vzxX43brx~tZuWyi~>E|0zP7>-+FIDnF=KFKKMlq zrM?;xzAoJx^0Xkl`-Gy7-P3!O{{ues6T^ilRPnqzyrzSL#cr`YAn>>Uv5r28$lIl2 zdCTuAHmgaQq^Yu{^Mus+xU2}XFvw@PCZX1Imx!Zt-Qn0kw4s*%@k&J;0<$=5atB*^ zyPXBdreXvtanUhz2in8UXf-}!(9cK5yS*044fhc`rw2Ljm$h}^1MJ4nhpWBuTzCW| z2oP)ibK@H;kNoG-7mSl0d&80OS@f-*edGP#%so~zLz$fj^*-J2W@&!bs)Sl-ao!&I zmIWLcEvHdkgM>ikrxzd@52y6U;*b#yYXjMWMdxANXq*@2F2oNoPmTx<9lbNcjq&_&&`&%7{Mvz`^^B=sAwPn;~_WDLN{Xb#{W@}`=L>rE>2ml zZCNwp;_l6_``++ad>~{~jbyo%NQk{ zpb#KedW0p3Fpf=0aPSN?vs9;?uOjXIZ8}I6z{lfpd+c$dl(W+6dPWwsvXYi|%+yxU zkC?R$*xJIvdc2lIVz(y}%1uNEjJm8moz+)}<+J&U;#TOk4inL7K>@@gFd~9LcI&^^ zd^1>;vr1HkLenqqlDjwdY#QI593nyTRNu%*=&&#e3AbZ}i7Ep(H#;Vgqq*$Y=p+aj zq^s?BL&*SxHo^05szku`F~8UOcA~uAPe{h&|CB(6I#D2bG{?>kNKR(f^EgA>I3gxk z_=Fo2E1ya$EIf5ad69z6)L}TfK;D{w-k6kcJ8H#6@QM*wrQhmxaSjeDltw4}`Cu7z zdAVi6;Q5UQ1@2Xa)#B3io}(v90ymA3zV4QU%PC1V{ntM!*BIhS7o)uO^sZtSuRYv^ zRY!-PA7Ev5b(LLnV;$z>M$&#>I9#r_H3YhZB7+H}uRV_M&k}_M{2#9mrb~gl-?Lsj zo(jsc?i%_B%rU*YCs9*ZSBI>A+!WarR++2`{ERduo9}G2tPBiv<6*`e?SlB({1a0l4f4%goD=b+!=Grw&+?#^dWw^I0)VYJnjvIzOQk=JP} z@4DaRFh#8(ISxWnE~~EJ?swg0huMsj&$hc`J+)NQZ@a!21sp6l2L?(@S2h(ufvCg4 z1QFXLq~3-&z>nFI$r!28V4XQLHTt@G!U%JDIW=|ZcmeOrd*@EF<+IP#>C9QY=pcG} zE-re6An-nS79>AXqEjp~l`?8M-??vTiO*VU&}~26j06%yB&`Sd`q*e{HlG>=Jj~7~ zBn&3r92BY`Kz)7w^`z*l0vJVt`bsKz|9B*yahhV#)n;47!2OT1OWK? z3o_p$iUcKHYy+pJFRya_)G*#QnPtv?h7E3uvuc->kSfd$8pkL3AcSqBDF^Uh((9ue&s?N^V4Bf-(bjsO+ux#cdX$C>rn9~GRv(ko`vPp(kUibE_RXgxcQ?E*@q|h$7maH3&c~;&0aG2{0Spsya{`R!0*L?pfEEH^j1v1#}y)6+smW@tF|Ou3mf)^yo{CI|R22S~@2yuywCNN=1} zbL}aYbk2!_G*DUXXl(4&B9Z6fQdc)M%^Z!6g(u%D{V!t9JE) zf%%(9pt53Dl8V|V4YYXs$^VC@vkIu{`?~g_8|jkn?(XhxX+gTXLqGu$knS$&?r!N0 z=?3YJLw%dy|NX|g;Q}sT@3Yoib39{G-acm~X&M4t0O;wN5>2H9h2Hh?twX}}`gYMc z@a1+9=vBQ}qj4}fm7*Ga;Pp!|1O2-wM?ah;|0n&dq4B8J-*ZPtmGE>&gF&iEcy9VDq=PpT3Y=&zMG={&_foel15R-E<5Hz(6|GLytfY;+BV zV#ZwoFF?nRGm?fT4A%YWaen<)O&Y+568RFPYmaB*(g$j5g))a6m1@bETL6ZoIx6s57@7P9}n`Zm{5FHcPu9a`CiYvc%GMX`@rsi z!3PTea=cKYqND9`oE3Yy)`W_Bc_1BKV7>2qH^l&ty6^q{v(`$ZQrgW3!+HBknU2Bg zLIs14I+5wzR|wEj0|SF?fB1==&9L{I|1vBR&R7bYo0X~h!9<&q4;lEL$aYSOS@nOKcco8pNR z5>c62qa>Z7`2;*0Qc5l`QYSHgqJOZAdiY{lTtrO`+5Yz0dMgtx+ec2tjS>hEOKR8( zy}5u23etcC*{w8!eZ$NdpXPOl@^7wTwmi^3LSuZ?)U2q20Y&t01iro8Zv-k}7826^ zC(vSC6_v39tgK@DFSI~JQpP;sShe^hcy&T2Df_N)``{2v9%aeS|Kv`?%`zF_eK%SM z7^j+gx+qTE~23!u$Aqp6_88HvgauZw%pX>hEr#d?oLf$PNTO53R9BG-b zWkDXdOh53y;_OOY2&X#(zvq(pq#=|D|HE7vnI++kX)~D^A|Y5+15IFkd3q>RNM<%{ zo#UP^aYWB5yuyIL{Xjj+v9KF%nL!C0S-!pnN)ccGz7ACQ~eXHgvFY2 zfjp^J_M};h$4b(mB&`y{Oo;V>r=M#wl>eUv=(xW>vtGdwMZi$m<~a#%=6 zFr@6;^eK2no{r#-1T0Ecmr=yZg3AF80_!`~PoKoZ#J=u|vja6F!x)xOS*csAd|hHh zNQmC)E_4pygr&BXuC8^oANETb>KUt*x4nINPo{LctIk4r#IwClpu8ft8! zlUYK(!q4Fer`!9|vlZw>0@6}aGEifgZ4a4Mou$5SYGqO1%NfPh)iu;-ISLTU8 z_oAhl*T&oKFGi046DpC_$zp}?_G$E1UCW?Q;N^BhtO}nvuIiaN{cZOxKxYS z0P~R#!sB%sTe^&a;jph@xHpMt(%>NP*<-skdp=BaUJD`SxkDku%`lc?n*sE z7{J%`W(W=gzFB(!*zFpRh@VW&Gz3~9-}|_t;n?TCNGoZfQfdg=KQt1@Ib-+>XTX)5 z$6ap|wF(_$|FQRJL!dS+ViKqtxkCOFKwJ9JhZ}Bt!d9B9KA}u8vU6N-4?H|{cTcGX zzCApY>E!1R#RTqQ6F7jo-qghJMi{JEE7yO7z?EqRo3Ng21RfMwaLgF?D>OB zhAICw$=<XwC!%*;$fgMuY8$MYbNh)7U%_5QekM?&~7 zz0+-RI9|8R>C<=>VUE*=#j_4U=*Q4n_v8Bw;6^8cO_sCNXn)>WXDJoyVBZ8avltxQ z+dHG~+G{9)7{o9ZfqBr?`X!J zyA;y@`PuM62OJ#6sZB10-lsG{GwMK9X(ZxtlJ3~~boNU(M67D@cyyF1@%1YdHX=_?m?_J zlj&SYMGh}HA54loN`BrNL?IG*ZT`F^E-xwk_~qFv`gpm*^ZdNaGG+GQV2n%>4SMHn ztvP@r)hlbuVxqwF;%d|-6L*+v@S5>{oM#U9dhjC%5oQR5P?m{RztN=l`s(W5ah)&- zK(u5S(gN2G1__!>%Bh-Tm4mt=Fq)EYfXlGw&&B@HEtyGUS1; zU)>BXROjRO@sfo?g!Rqq@95{OtHrXJ^G)TgSsrKCC_Zuv2#_|DADJtO#PNSX7qvSH zjZjg7)orxv8x(R5eE@fMJcN;K1ZHa1t=9ZNLj3+1tKq)9ffCnNJn z(Pp{=>nw_u?U&tl1}kb^$7VaqN`Fc>96g;|rza(_N@5|T3V3dG=F5l}5a7zJoX*je z^o5gm?+(}0d=R`?b&Za8@yGoc^tVHR$8#wJAOA+*aw4Y?A;#6s&3W1il*Z$@A#fzyB7kf@N4(0kS|158v9EN z3C~hl%d-wOy)6#mPn6O!7#U^g@_)0Ocilvf*1N?L6k4Url|d{N zXZkDaEH6U@tVk@BoUF90vOm7|ke-6|W{wbTaWYn<>~=$u6H|^ALLGTNSKcxN+$m~n zfBlOHVdku=QurI#Jo$!wusYOJ|WZ933k>+P+OJabaK-a+^EaAADhekeLI+pv?7hE`U#p#CmRLWfGor1VX^ z?gt|i_f?vlOE9?(4k`j)fM4JD?QP&ApS|9ESvRTIC>R(pn$-0g2XA`2ERDwzg4oe4 z@_GC5`h$pp8W{#ioOT-GaK-bbwb7o(0U3cz5=-jyc-oQY-r2-8HD(!skY0eHtQX~1 zAvMae^^SyISzAoEf0`tN)^foqW}w4Slnhgro8LsnyF!jcioO zP+DrU&<8w9%jXBnY~SOG6&X8%kDiRM#h<=7g?EXFy4YBFRN}|>nC#@!sAMZO+u%gH za#+C7{5)Qq%oK2y#^8@%JYh?nv-zGbki3pe&AQ&)Q%fChk|Cf|3AW-)Q>4c1w#+Up z#>G)i75`|~4N8 z5$G4KN1fP3JeUwvCY(yawFU)Ugzt|-q;Vb3m1x;oi`Q$<%90DuD?rK)X@vofZ2;oX zH0sgW*-_~%aQz%l4L+`A2Fd}t3%@_Nr z;R)i+Ht#LQRI-A;qd&MF{6@07J0X*hj$x)ZO}Vj~-LBfTH0tNlGnh%Wn zrCnhaD61^pOWxEiD<15UCw^aMZZJ=dBp+b(9UU6naU>~2OqiWepef^S^B`JnJ=?Uw zs4oq#N6&;6#Y3B=R<;4kR4!v;fNFN8;Ns%LC#Cy$wP!X2>U{C=G_bHZt?E;@v*Av$AXa1fuhkyx-OayO(Ae@r3zgPFqMpM0-FVj=)B zWmi1g?O8I|TXxN*=8Vci%{8{(23EY;G3iwptlNFDBU=dpREhX;r(}7eQ-E-I{X}q5d@S0zB%jUIh+yR;c zmt}AW%I$ceYU5%H1WHW}_3~1sT0h9HT7Vy0ZGn|A$uV*i2CmvK?mj+hYLd|QZ7tZi$8NAtN15=!3Ht&zb8{ti7HWo3aTq~!a|}8YnNYky<004I7lNH5 zzKY5aik5D;D>f4WjbOP}>*)@pl$pwfRsSW2CG}4g#ghdg4vk%i@TImUb$mkPi_0Ov zDnboASiqLu0su4CH2)ypm|+(|DYQiCzdKC zKLW<-C0Abm{*863rJNHy1tb{+#6AwDyd7mS2F8c|#<}VyN?9)bBLcWgfwtD&eKePU zGyi4-pCN#zyyhI#2iY(37_0?gVJieA1nYTvdifE^bZ(^*L7xOP#=91u+pG>gJ}zWU zxB->{x=0s-W3Wzz&sztdEBt>a?|COwbBYt&)`)o!^R!`Jng{&1$Q% z-__AJd^x+Y<-|&4*J~>}>`}lMg2y{0ktFlZ5Obs>qL2`NvY{9f0qVcTg*oPeEJs14 zs$Ine1^hLo4AL=K?C!6AYJ{vgwr;w3WEFZ1HuI&}*guZfJGNdxA>o0q-b2w9`nIlu zh36a=iW#h5;K{C@63+8cF|>P*L05A(4_o>iZ++g$cW5=WB@87cL< zjeM*0?d<+tuHKTG@hw!Yw4EQK2c=GmfMquV_UB`)%O(7tze4%mgCwN}`uhg~ryQU! zW{YPXXZ@ghGx!H;dwSXfPW7^?{tAiC+Z{~eN{Rm*oX#&+`S9WXDy}wX*M}b7V2kv# z)k>p6@_I)h0xb;<6BCw*|7!?b1U%@=606<-;pXk4R4gkli~3i| za-QQ;CEKYy3tRO#?UG0GxrJi0T&zlX2dmL^6yI9*8R>Q zpl$NgY<};f-IDk?;V>qD3`%a79%k<(bmamUF*Zpr-U=Hg5|fX%y`_%G(ZiBV!z5K+ z=N*OT^4a-DDkBZMyJb2cVj?z=lXy(Z4&s*A4@FI8IJ$;aBnYI+&$I@X_RnPuuMgLg zUD3qxrm`dQSJ&*bjOUn_C$20Voab7j@9)z3^#58+(A{*OzMBK71;aIiH4tYOfl3sO z*2vkCTC2#MS`S`KeL6H;nXNu1xXtiIMj8J8_Gj za1kJXuTX%}=oMXr!(dgyn+}`N#Lr7D$^?w z9Je=^69?v5MhD1x0BR&%0&Z$I+n6e7;yV5ABvY3@K-xjRu>ppD;q`g65}-=}UIQB| z1+#v(SS7m%=h$Jb72q~K9cOm69U+RE7O_*-1^;UrhGA|4Z>g@vml!UEh}(m~T0%G= z3Ug&Xnk+YY@PBy8tB{{V;~B2u84MtA?}VUKMfFyH!(0G=a35wD@14~R1wCE<$AJ+* zPjv;py+Xl3(k9X;hDa!}g)~Ume?xcFxo|RD3@&AIZrKqVJS-JYPWV>xwtvvVXI@yZ z$6-OGhWpjXaZ2YONU`X~?VH&~=Z!uYnOl0=NUfMy`?@+^5Uhe4zL40Tu?%4$%Ko*N z{)jUO;?)nL@H8AGY#;#6+_ zgAQA%tp%Pvh8!PmnT8o7=AgsoJpvMG5LWSIwcsRR2Xp$4tRAwsbE;V_YmR{9HXOCI z5-WWSO~ojoBk(bZrTYxqK z+T4b1tDv6mRtBSfk18QBEv$+cnlFp6S}?KK8ny}hm+O48{KOwhEZFQ?{OEm*gjFPA zuDzP)giHUC$IV2dH-rj@l?i_~);UK)0nOpKjXbHUS?!R8=Uq*A8#1^=dSk4Hgtla4 z5RzhoJUs8Gw#)I^*}s2#FxB4IK(+Kq{f&#EQQ;j7@#5`X<#Rn4%cLlz%Rg2$vR_Rq zgNi^Yq8mNe=p1+&c&hd2N>PqkjNC{Tv9w*$G0N@rez*NLnzC=>h?|g>SoZpf_CUXu zR?ku@S2D5Po17NEy_SD|8SH?I&Vu$bzcZr%-{#H7jE6)6l{~93m==dC=dIFEfr%%n zikPe7$M#SB+*}8Tg9)y?D5Dma*XI%qj2bn7W!xJ-AzGfAuggP|`2GMsTUyVD6Ec1F zl1FcK=kRQKY2=^+$Ovz>)!J{BpSbN<@%TMfFI_+3W8gD_AMQ7Xq6Y>b3|d@{=2B;q z#66Rkq4`xMCF|{1I-x*7*d{N0zVPCA5J(N0R8bqp9d~$gd;dEoHBMiGfgdU=p!I@D-F^Ytu$h93IdJf`a%@Ij z&t8awgKF>DyF{;@^FrO!?NzYiiiw3t)i?Pg72zShXuN=O%6WU6)7Hl-sCNFhaUR?b z!?#3Fd$`6y;)|)7Us+kPv8i+ezcwYK8@|~%URvpnXMA7Z_#HZIJaK$~7iE8{Ez!)Y?439zrUVMiu%^HuJ6S?wR<*mHtog-z$!r zFw@)2QcId(WX?)!AA-x5d0~mn5MVM?4^MB;W17lTS$~=sG@VVbNgOQ?kB^VF2N01m z0R(r~8@DGLS!}GSy%({`A2gA!Y|nZdt}o%)8!RFuLh@nt6f(4#Dcn(6ME0Dt-{!kS z4C4bIsfhTijCJT$GVr*|JKoX0AflV5o36(JfU3MWH0VHa_pq*lD;cK?pSV~))G$w|)nfDZx&AMqz z%kXg62ZaH~<46c7@csG9Vr%6MX&zng67XSXT}hIc8H)+7KJJiy)k zO7`4=Wh(OVthQe{I!|V)dfJu6iS?Sfb$8Uq9R3RRbU!pOzaHmWOmjBa+qK7k&J(F* zA8~4k39j2K6*rk;TX4~<-Ocp8C$X9dHFB#1{>xP;pGSH1uN`1(i!V%xTS0O=rKHLf z2|WDet>-qL6KVl=Tiz{JnH@G5(b#-^_G{p0D675N6zd9lc(}SUY=aC@$>Jo4k25eB zyJmogxVS0k>HNt3lYqW0(9XRUeW|X! zoS=<|_k89d?L5)40@Sb7UP}1ie|{!WfS-RI0#4}i&6;OYs6j<#r7b$XoS9dGeBsRM zOpqj;q4wjW<}gl(@9~c;Av05-TSz=M)4AVj`Q@0I_9FIA)+;KY{|NohAqnQ8V(qei zXNlOW|8?A!NKehsE+Q~#lrwnA2GVjEkm}0L#t@sfm_ji_1-(8-2E5+PHrl6i%SlNb zD|nr8S9gs@%CFN2m$%Hi_FCN$;JsIkJ z$TPoiG}}3vcRf(fDi|PeZ#`;d+2;;h(ghH?#_1WvP``_>&w^T7mzP;-b(SdK8FW@x zrx4ICVxV)heYZoKJ_N~YeHt!N&eALsaHFNqS?&tWy?phhZ0o}& z32hQYO&KX#C#LxPZ+1?d!#1hC4zRA-4NS?4it{6t)w!ud(dy^-4u*ypu&xi%6;GG7 zKDgjO1epU?)u@_;3=BwZY%-bJYc9X!t4nH2#)v$f8XZFwZ51ONEj{xe7JA4jZGa3< zMMswb;Cr|_2*Q}U#`CSp%c~2Jle@ErvkQci>-|G9t?7=QTPbGdAKA>iF>5fE4fR~Y zp@}N{_Es2;VhS6SDB2&TCqkmu%nZOK>nL2xh{WC5xj&6J(B{3Mp~)8d2&9`%E2d2l zbgxM_mc@y$uVz)=(Mj>T2V~fw_K)5?R}LUbKnCry2$ZApY|JTlk=bTo&Y};C*paw_ zSN{g1fTns)_?MtSSy@R9kfkL-hQ3QbaOvp8D z%~hYx!KaQjXcZ$Sl4zIiyuP!Ma(a zz5Yu_AA8ao;9ng&I0vKQ;=(yEj^iqF!Xg^ZMxkH{0>>n93uGuH(0Az{eAjxw_NU`q zVkSNpf5KH6g^3{sNj0?mJOJVag?#-CkNz{AJ5#X5^~7?P zoEPsgI)!9PQwoHu>94kb&;sAGJ*TLtcRPS+2M59IY^EUwCS8s7hEeT==0T6!)9Vwg zgkEc;t52)mT9J~onh!r{DD|gf2bbqrbB#>QG}iTz4=Z<+El&gr6@LpK(mH(^un&zO zLBXl#CH>mmx!(VHMvRXi+TIq*y4I#K8Y}6Dg&03vAmmQZSuYg{#KQnf3bD41Dow!OW2>gUpPe5bM~76p0u{8p$Ih?2$(8Ce4QD}?J;A)mL@)DmkxzJ-XN zT$|3($`i_{T=gUv1bphV8da7B5TZWxUkV@qQ>@ef8V59^=Qg}vQ*k;UYr5=>^%h@5!!f4V>2fcur63@jRif7r=bzyblGJZE>8YQ^lN z;>ZDHriS~UhRznr`DE#JAVH68e2TKD4eP51CfV| z37GiEhx7l>0(_BWp2VM=^a_wpq;>e)ZhoDFsDLyYM&kF-6GoB(x4|>!f=M7Bp&lTn z<`?@(iJo#}Up*mltUY-i4W=H+<3>+G1JwJ{TAXQ229}P*um> z$Y=;GF81f?u@Jbx7xx`$xnEVCttedX-kGSRY?sfE`7%@h7%ZV#21UxvO-}9*lTRV4 zg&md3)^wDj?+{IVIkQQynuc!wc;&glMBnb?zApHkjwQdcpsI^}%rYBdDoq|`F(g+~ zh7xFep8S=B206K5MF7xFRTuN8tBE$>`+6&}Z&-ylPCf$%6ZlbNWP-+eBhFUnPR^G% zoGLLuTV%OD7y4jZDqpRtsx;2P?>CJk9=c?Wp#aFVfeVkC?^BOD`;haTl&0=4V^v){ zY0fX9g_YHJLiXlT=Gs|f+xgYNS#Zj!S>LJA>~XpvX|q__V5?n4MoCJ_%F2#G%G>Pi zYQs`M4V1FK%R-X~uM-*jKq-o_A=(NNc1Bt59T|gZ@Dtf8lfPA#uTKY&SOmHL^}r#B zkts2W%<_got0Llluv3S`7$h&SXiKPJuc_% z-Qk&Z@o?HJLD5g2q`qk*Z63c1DQ8|=Ga+$a#NWVSI2JQA^j*-$V2MUjn&2rClO+it z)q3@m8;L80evS)jYV4+ig0v%%n%y>E;AIKou#AgSP*B@EySpce{5CiK8mfp`Y$jA{DW@)-) z!*c0J1STC!_l>)2T0(Y}ws8mj59+MX74z3jOxV!qlDf5$^k=%ROaXiyuKx3f+aC0e z0a(|z&_YVeXv6^lhBE!88Z)PXq%725si|pc ziJtecpywCm%vR|p=j53dn6G++Q?;g%L929-oQ~^ZB=&zHFJA7m{Z{Mg$kdrw-J1xG154s9_E%6Uu8%BH46F71co(Y|9K2q-R#%I6tj_ap7h1mm8jHd1K>KQHqWYAz01)ynCF)^ ze&nO}P+IE_;7c5xfm2dLrGwRV7()#poGptw?$S87oHOM24&gV?NeJX69xDEF zlu#W6gfNYwU=UCe|1TX|g%vq7#p#sc#hSt+Ai%*PM3hteE_Hs?kQz4Gk4?8yW|;X; z*eL;Tj%3^(oa{Z10xJoaFtI@My_Y<32As%>3;`+NLCaTKM{W+mHRj^V^w_Xi z$DS~9QV!#om?ZqfI0_F5G^;lX5<9&No=_R})qVCAHL*sMG-2Qt=h(@+{C&M2Wk{6L zzYln?U06oN0%~pwUJC z+|i_ut|P{rRn?_nYz&_OXsfFqk%jfH|Gc#W9b(L7NOmZ0d?*F)M@pF;DFU>;E(qSCE&8fP~E^S95W;23l79obMbe0Haa?b|evh zfdt$Wv;_^ShpDR$JSt>e8Dp`IxTIJKG%FrxWYo2`lz~`b?yL5FbmU62^X+|tUQTu! zb5eSJz3t-mj%_Pyi|vS&n@cakMk}s5K%IS?(R-*fI^W(tI5_Y;!oqRnoM(@wWO%Ch zW^Nu&ZEnfrRaSm-wRcj^gPV}(e^0dbcFF?>_pP^3&V#$-E|KA16D7KvqcN!C_4yH> z1M5eDEs=oUN2B-5asM}@lD+-YrpwkQJL^SePR*)=<`NZ^)KYDYh!*D^E4S_mj;t~OyHACf|q%aD99J}Oxbe88a-+iED{Q5OF7h)Y$q1R}=!q^Mu=H%rR zq?P0+ZgSZ+V^8x6`P53SmrzYI0s}6G0Fu|zUV~BT-2PkQYB!e%@ZsUrn!?g~@yW?? zE+OA)e?=c4^VDrgqR#wzfL!Iwzr?3R}JV; z2+O?9SZms~v9POWt*lf}E6&1sKB-jiJw9Gn83;cobHeA&RB{y*G6fXZ&kcoX;6;V{ zT}4P5z(Z75Ae3EFOICGxIZulx9`z=2+w0y-KK-GntPBOY9YJ>k^v9gWVVZdGY}2HM3O3fwk(6cNs4kVyYiQ_i zWf+(bAG*9^KU>)$L5BE1fO5WX8dK6&DhaM;5L!8IX{ygVwiHU`m1x3GYwQ$Wa_Zy5 z0fK>+^Wn9s5ivV9F?spfB3LF9jJ zQj)zY-A!RGpPoB=b@CH4omK@RUSAZ)u|l^2nbQ1Uu6_c{`yEVzR~Ayk7xAA!$R&&_ zEtRV9dGQLmUZ-*~f``pDD{mXj<(6fJyMLvA+lCAXUAjIxM@=|6fjPUd0%d)!uE!2@HMYYRGy2wXha&BA1O3cUs=v|5jf{QUfQAcuyCe{@S4gxK8> zG1xb*R9j8D)iW8}og)Pk5tZ@h&)48^Y9lN~6XtN)w@USCb%dUt9i>coj<>f_Ng#gD z{JY&}<3sMNMbxHOe^@kb^K@Lb@;Cp+l}Sm28?iYzhyG5g=`|L}Tu84({0yb#ExGv$ zL!z0GAi2#AeJB5?$>`Bv~qaf>L91=-j+uP-}sp5L1jL9=eMQAz@w~VkE28L*IwQ|HdT|glrxm0%If2n%T_s z>T~+{bHi*p*K64!0khCJkm$eoELITdMLYa{D^I=9FB9H2)m))x19E~mVYI@*dF&{r zERX^f3Q(a_k(9O}?}ZNM?QHmE7Mz}{NoMk#Upfz&!ib$6_1Z-Zf{83Gb#$Tzp?F>QyL&c10C&UL7T0WHAgxPA z20&cFu5@&AatH|f2~Y~Cs|H&ej8Z{`2&$W?q!fL96nywOzkfI5MI_6c^Idv-9o~NX z7W^xI=TH^%9!pBi?~D)p76Qk_$j$z_tqI3vwQ!V184C-o*I7(#Z!hl;9Zb)_H?;ho zH6g)_UnA-&Dm*;m$fov1K)wf{6Okq0t4P=j%1;_}va^@f-m(Aj(of~hp~bA z)o4NHQn}S=z?`7BuN}VgHd&tTFx|SS=y;$M0iD|ZdC5xQCjhc_>~eNxpc@{MSMqmh z$Ks4;Cilw%DkMkt1w|a}3`wWL1Is%`tfjaG1!j10cih~JYSQVN2FFM=F77mYR$}4e zfIc{Kh|SfHC?3uo|D*WBw+rM#;2s~*dutOeMsJ-7kUaUBuylSD7E)13NddgQ3lgfH z!|&)wp{GM5IK;nEgna)>_*{=V@k%O=Q5C2Og?w%fr}N`3s9JwJ;Ic-d8YV65q7bBa zuiNV^3F#}Xrcs6cnwq-Y(NN!|=flf)efU$NaexWpmxO_~Y6ntt85zGUXth98RF6Eh z9EF@$mphh|M$f20+GX!UQ3?xTU>2)%bZ9GwFJgkNXn$F7N=ud-nXx(YbWUNRMToFH;KIU2J-;)6sQi)mp|BnmYPOE2E0)rsx@J z*P2Q>RRckG`hJ-u2&kilR%*;BLcJRC+)ZAiE)y~5OMRrbd*mTDpoLF z9?y`ii_g(WC`>HHNi@Abi8Hf+7|h-%=SP`hs1&xHNS5VB6hv}l2rbbk;RINDqrZ0fF#CxRH#ctDZXG8kx~7}%yBocNh-*JXR6k<$<+JI9kV%~f~f`# zutXW9lIDrtgE@;;B;CnC!j5Xh?={)E&CKNttJ(v%BYWju;P*qM)?a|a_ItSaJi4Pg zO@Lj=q$VIHF+3ySxZds!`oDmNqd-z&ja&Sg$J@iAt`lWE%Xnoi75u|va@VuRA!|27 zo%IFVC@W8$)9+9rJ!ob_et&R`2yh(=38A213i%O++Trwhxqg4#^UQ9|XW&Pfj=w(? zlzu}TG<3uA$VeQ)=dgiOiesuAUnCB? z^E&0?xxc7hTB1^r{}CS##NGmd?I9AkknpC>^mZy}C}vh2SHJ1*bfqFaom#;6U?TT}@ZIm24}I0h zU$X-{tv^^<4FAL~hu5j(75G4$5WC(fgd*{JtrCe4Yf+3lh8@>)Fr=INQ@w%LRrWQpaOq&exd55Qo6Z>9=&EPioM>YSRoc z@*?9*0y7AdRg&Rn=F5t=RWcIbS@c2+eweB&vFU+>^!&=vvAh*yn2;ti8xKhd^u1J# z{0T#%K7PDX|9~>^{%~n%HiY+P{e_~D7I`}TLr!Q!Th{~o(P>miFV7chC|z)OGo>YH zJRU=%lSGjQ_F;qRg%)4E7?qrhSNinYR!dB_0;6DLP;Co|eqET1p%%r40Tsy%n!!3W zBEjtEDX8a5po)KUJRj*x-QPgS!4DfXXn1K82Q3ce2)FzZ=dQgFaZ1>g4dax>GY})c*Ogut*yBdqoYlB zKy5cXLPh26{r4|0iz6ZeXkN^!fVy7!O&>b_Dbvm8Xz%U>_zEdED&5>P=>s1JHa--? z-xVC3DThzwN+97hw}gFTF)UU6NrZcQXqj!^o*nP|Ea`gP;##b1Jdxjp$LG=w;=u{yLui z))qk^mA4HSlw0nLiRBtPm|+_HW8_8K<>akjvR9`O7^Enun`4aZ8w^-1>Lv9%av{16 z7+8QXOk1;}QJZD^Q#@1Z6npj8FK8fK;eLne`V#)-Q#rMNoSJV<8M=)*e%ofuz1Y2s z9};;}%>Uffe25%u7CFQDJ|!te#3A+9vi@{x%FA=IV?n!qP0PX2zw<9lS2ec*eP|mb z+C5^rHm9QLZgIOiJnJb}yWv|!=DX(RQr}uyfSh7a4_Pi~VuG0&6*VRGt0`BE452=^ zgPZ%yjYi;G8bO7}Fh+&Pxsi*jT36;ro^^j3ssR(-n(aNE8*tZ4l%ioWbL`#}J&o|j zP;m4vk_PAQz6~b~%mgz!x<#lG0-qLxHm?8=7Z+E@<=_*3kJt;C{?PDsuFggWZDp2QVht=7# zat%q+eNbjFL+Z5fZ-HGej$VSGsM43Np{a^XU*Z_xyxnO6GQ|9mRw+;d_uUw3>@vTn z0%6l_O)FJpu#2MQADcTG{*xwO_=pTl$&4dIBF9g{)#Gzez0kt2 z-$a5?)I#{{j-EHukZN`sL5P-=er8;&V&V^god0G29xD&9i0VOrD>31JJ71~M5xN-J zaQ~6NX2r*Um8w_vx$EmcP~;f~nu5GSe68Hy0#5q{a1J(Mn@D0_oY}-9Uc^Mi&VW=R z_8?8tZY?igOSAXmFM4z{OH-HlT9n7|Kz31!qL98gDo8OuKcn@5NE#K4yo6+#bjG6M zz{?g5(Op$$O1AX93b3cZ!$+fscW)%#o&`*qlj8(iF?8 zTto_m?EHfcGX8jUL~w)+67Z}v?s8y4f$@0$?ocs6itgeZJM8BVk>z7^w%U{oiHy%~ zef1MJe5QDQ4Ii<-Xx@$>O4+s?Wb(JMVI@Q|Oevhd?Fg|+Kx9JFy*FU}Qzf7VK;>Co30+0rW zbh3KRy)-5{dbqtDt`U7d7*_{h!=nNVzkx-#~cW1eEP&)Ak?>6E$ zkb?ue3X6)~-H*M^-JFzT{Jj%Jam21?4D1G1OBWX}Ugc0tLsCprAMimo+t^^#m*H&x z1)L#DNgBG6ZI3Sn`8(ZT6R{s3cdy}`%dWj(Y3ZEZe#TT)b~^R^eXJRhSHQ%?m!_Sw zjky2SbCKM|Xw>f05R{#o`is@#`&*(?8L7oz;r z4wdciLrW5vRJ6jsIq256icFG(;6 zZDVX@B!o_>yw+OXj~6QRpJFJ$t)yH1FWvY1ua5tG_gy0F2L5jtNh)n_-rzd(-Q8b> zVX>31V2Ry?WX`fXF`*^a_5~m*x4zpj_HVC35R+pxHJE@w$`|VzeEDs<%jD# zQ@Np`H#a|4O7hdwf$=z5ihf>w)YPa14_Bi=_4Vd6x0d;ZLGT*cH-cQv>bE#LF*DZP z;q+XAIu}ni@7AgBUAeS|HnsE5a8muHB&p9&MM&S#Bi+GeIs@C`;mc|J7B#%&dAYej zGw(aw;q>R`<`ltGVElvMW23#WFfNPm{p$0h>nj2p;cBsp0bzGIdf=13`)#c`tVy>? zia_$Sav9a)0#N1p-i3->T@GovtTdvbJZJppO4Fg&;4bA>0Amd?ixnaMj0?FRO^F48 z!6QGeT=F2dL@BVKNXh=4oQlcukVvBXZ&kn*AzN|UxSQpdyrFzAYVYv(vnx5O#?kfg ze{J{oF_J5s00i3F>Q@OnHS7ES?hMDrv(=F8br5MeGy=q*`>{3mC}%#4v=sF3m5d?m{7)`%N-fym>;GoBmql-n=@1^_ec_7&H&vb`cYi? z*3>vVzdS*K$_<-*n{JQwYfJ}zV0)ZQ5Mg2x?;nk@cD-d8s~S5#U7CblEai$d=6P)O zK3?OpK-#UfzPCJpQ+b!ap(##7SJux52${8=H`+sa?L_gcd+nec3G|_|d1yPJ5_}eZ zd+tYwh(HeElfb(o=Js2<0LF@Su3eobF>Sm=U=ebUxl{0vNqWY`5D^us$0ds~^CoNt zzVgxA+#YS4#=$DIB{fxaOG^E_jgAJrz49=J36&QVi@YRb(%kw0ZGaw$A|;BnK^c-% z<5Jmz*@yuQIr))_+GbwdlIURR1S!orC?W$FnnfcV*N*cqt!4XSTo5MbvRD zb5kJF&13h%Lcy$j$>J`zh{^j)YX^SsnI1C!)*|q;x8=d*j)KC`v7rIAN~h7y9|}|F zY~fpXHnz~Eoc&s0oT}^>*8U;KC8w(|2CD;+zvn{3fEhyugfTpR{bRVLWg?ILAlQzc zYA3Qsb14`o5ORD{(fkRRkM(dTra~xiX$L_aZ%ZA+!14r2)qF2w-z206#h&uOkLk>+SsMl|9!4GB}4gGA8d{fn%kfK zW?H-TAf?g`_yrUSDJj=t4G<&ZOADLBjd)H@>+4B)FR^iOu(7cl0tHz42u70v1#VY> zDIqIe?Wr8b{`QY9Aw3Hg<)`-cz=+CA%pn!f?*6+xp1Hb6&u!MVz@61Ozyjsu!=|YS zKlYCCY;fY0Yn3|aBqS#$14Cr#6Xm6vMveZw6A_ceeER>p?!$HK7^BndzmF`NQJ>u~ zx2V)_^Yb1W>O%SG;TQPa+!KU|VRZ1`E-kui3M7Yt`?~h$uY9yxbTqtV5l@1VO0YtT zBwZ{o5Ey_&1K&R$?2=X(2c9={-Ka}T%O0+mudaSWs=_Uf9xO_-M<)V(zhAb+$FH;a zctfL%7F=tC{g{-jqaP|$wRb(R{pU~Xaya~zjoMo^-CFEcrZ9>L>tVg?e)}tUBxa7O zSVcw}l`tVg(N$w+#wepuv$ch)_(GI!(4SxSl z;rV|(opo3g@Av*^X`~y8r9qLFZV6#&loF&ty1ToiyQGoskcLGN1W~#a>8=H(^E>$d z{C?;8b1yD-W@nx_=e}Qu)28<8cuH%=ZxbzNr&q76LHG)98@aT6S(DKOmq<&=UuNA` zaZoBMDD*MR`ID#_aEddG=EdYB9xl=*BnpxA^i-TgY>_iREYU>QN7vu?=aVxpzmTCJ z6S_093j3IZpG)ZmXdeJMnIu}(tt5T;d(1m)1YeMg|_?DkS=-<`IZ$zo>t)o!?dxMAI_ zWfMIS#g072^6_DbsdywUcOU@22DhrGaM=IT0!V-ue>_MUr(w76rSrF$s{>`y#oRVA z7oQTVC+Z;WR6at|S!~6r@yz8d6l(a#KXFt_$KU<8@b%LQzw5Jq*@jue>Ng$ls;vm? zx^BH6U`DTBLqM-Q7%E~lD2=EA!%M~!JluB~x7VsU931xd z7ZEapU%>btYb^CI077&oTm>o_Y{Tjyl&ij{g8K<1A~Ip}6r!${6Gp;DjoB9Ndox`= zo`OIgCn3c5y4tC1fCn_9&NnPCcfC=Su-nPr*{Re%MiFrbKpHZ&mU_Wlg~rck%YmKQ zow(Flxp!Z-bd{w(@731c$XA#2zgz8p(`b-~&c%FyxG$@Wj^zXJnshaq!tq$vFH*HZ z&veV;V?jW7AA+Dycd-vWhP@; zb4QnGA-Z-FCL#Tpvk`PWBlA4l+1ar!)G-m}IW>Fkm@T9(n@X7rEu4Mi*wv|&CsBXS z@vtblfc*b>DTSIcIUCPHG?@jDix}gGgbAs!?dp~o2zr;+?vICD*S~^H$QVe*!+j07 zL8hfIR0Ye$Y!2F{55a)5W7Mp4Ep1l)ZRt3*i{=9A!ZlZr2bY{sO6I>L#;|SURHKtx zzU*&6oE2RxT) z%^yFY(1CjQa4Y>gRze{m*hfJ4ccCm`&DTau#`($Jli7UZ{uXhKKu1Mqx+q`yss)ay@FA(0H7Zi0$J~wEF}svABFBk;u(O6f_1k^=0C!A z6m+j3kiT02$3m)H=8wF@e93*pjQOTO;KKQWVgS15&2jqHt}7Pl_KR9nLH`d=_%1Ke z#K74=R`y`N(YiVN*C366K&6H*dzWz{c|KC3?YxH`9yOZI=|*l$4yjBhlDR(hW>>3^YkgTIO9o@K7*?E|stba@f?oJE#!;J+ zLy@`syuH1hoOUf489@+tW%rb&jSU3wM8b}(Hq1+`zx>rN1I1guI9?m{^MjDTEM*Ey zM@p1}a9NJ!2RXMnJ&6%>TiPo&s)_ETy=l5!M z7bh280^>z_nX&nd*k+r%+m&I}vc99szvy@>A5du14LLd3xNf_%f8BQFdWwcy?M0Cv zpq+$^q`a)1rSzZ?$dQb6P^mTOSD#Cw%kQc;|F)~Cn8r0ST{%B*@dH@seDn50jxvj{ zyS(+q1Go#XC!oKi5=edrl1#e&uH6ASbO*#&aeWIDsn10Juo^gyN6Wn-=y*TH;n~l9 z_o~b$Bq;7I2T^I>&b^Q8hyX{T1i_~DkXdeSO%0$bdK_>sU`43e3Ys^;01P}=hMr1C z@Qh^f>9tS`Pu;CGI*c3Zi&=Uog_o zub2TW1*mdz4`8#k87!3P=@y6dbV}^pTtnX##QlU~D6a9r;!Oxy{)5^bRrYen^;b938#i;-YDc{ee=)TRokw`Ugm0J33g{Kpw6KbiOlzAd}E?gv*Za)DtEVQ3K% z5a4Zlh6jnHy?HYU^Pcf^a+j2raE?}`)}(>9R6$XZjQ19X4UFT*?@e4g{+)h~ElZ3! z?`Pkiid=NWX<6C*ZgSagy#?8h9A}vPb&!gXT%xww_x{8bYT&Og zBofT`cm!(=F+K zI1lK3Qv0~ATDiQyQE63{oQ=>7o1kPSF+GgcVIvh0f^55Dn<_avn%r#{-Pi==?kPkX}mk-1dxHw%Xil;DaL?-Un(ODVlFY)KqEu=YB===c^QHbhy4|01uw>hx0ujz zzZbclCPvuYH(2Q&hPqn0{NIVrPBOy}$H87qXmrV_s1f1gh!r3Hqx-|d#l^e3fo_5` zI{y9JUgliyu9rnxneNX96Q+N!*_jGBxv;{I}WYcS57 z{ABzIE4`*Tjo-z11dX43-U-`N%zv#2+}V{4+(E{E9ZRp2H2=s@hA@cxD1Qy629iNT zBgE0o4aA%S7kAeqBO^+{2kE`N$_=Ob(m|4W5{RwJqQfaO;*05mZDV77_2dBb2#7#m5>tZZV35&v&$Obg}dcWVoE)bxI$q*Nx`gmBG-bhJ%w8SSyjc4_ICf3WXwm`0y^igxjg?(UD?ox+iN^3&=m(o+})z%QVAy9-A`;plW`ap z%It#A(VP_L5wPb9@MNZ^_w>{w^=@II0B&xlr+j=K%)(4SJPR>|Ouhz#?SNUE*;{INQN^RjoxC%*f~uw>xvTX_y_ z)@LPI@^Vb~Gh00kNxTPDwdvZwYl{2PNVrYIMkrRL^hCFt`Xv)Cb~5cH9Rytbb>{ik-v4xlWGn&MFv79JXerl{%J#& zgglxuk$v?~#~GKT4XG>edHJSilKx8jtMZIIF{Yo+NwW-=Qa3cz`*pWAZV=KD{18Zi z>vYm+cog!he!Mlg50lmTm(SB%a)p-RXAW!~-+C z8j?q>GK@pyAZYlZp$nv}DrNR-N5W)t{$8E}KY`?`G&6t5i_%GJ2n8j{`(5j+dr)6w z0Hdzfs?{MN?G~^ZCU(xkrJ}u;4H4A~D!uzchKcY!mX*qGqTHxZGip@^wcr z_YXSXzguI}!EUqU0~Qxo#H8shQ`IaK2Efh|lJJ{Lhb~k#eZQTFORN$Z^r+a=Z`1oM51; z>)+bpbA7T6!6!&e;BqAgo7z0E^MU29*=jvWpx&BsP_@#|ssKSrX=AhD{8u4Xo{)p9Gma8AsuNq4V8$Po^*zCeiy!;Yjy%|>8XuQ>EcmxsH6^T??&5p5M( zql~TNXHa{^8XJ{XT>y1=;Ibj0c?ea13D3Gy)v>bv!r;JuxUN*pu-5$@CMGhv`{HSK zMn;C9CzoG5ouo~Atr}?1L)An>kf{kZlE|-%->t8yir=BoigSPi*XYmsP%?`ue>I1+ z4@57hfT44A{2Xnz$8x+-Hkx#N&*FTvBVh6Nd0HF>tOU76!*G z=VL_4qgl)olaso<;j!!<hJ)CRx+#W>zgm*SqLdcoZ8)@pYT3#B|d%xG&MIiyu5f%hPA8{=C)4>Ve;}@ zEOe?Ce=~QiI_y=sTGNJ(-`Y#79ng^KcZE-H zwR5$Y&tJ(c^N*scI;W~(`v9ZA(fjExk8#L=_(wa zD6jM_oqHDPplM>Va-+ORv*LU)S>gO04vh*`LUi<{Zvh4^w|ebt8RXq}dKpHB5VnsD zei2U3umOBZ#l^vaq@C4fuzVtpoIjbkkQ(190fBm=M*YrWmv(KppOp`aPf*S`=_qL!Oq~FzP`1X2 zFV&=EAxqwaRZjo5VpaJ>92Em@I=~ z%0A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 diff --git a/src/backend/downloadworker.cpp b/src/backend/downloadworker.cpp index 0895d430..6e3b75b1 100644 --- a/src/backend/downloadworker.cpp +++ b/src/backend/downloadworker.cpp @@ -1,9 +1,11 @@ #include "downloadworker.h" + #include #include #include #include #include +#include DownloadController::DownloadController(QObject *parent) { @@ -48,7 +50,7 @@ bool checkMeatlink(QString metaUrl) void gennerateDomain(QVector &domains) { - QFile serverList(QDir::homePath().toUtf8() + "/.config/spark-store/server.list"); + QFile serverList(QStandardPaths::writableLocation(QStandardPaths::AppConfigLocation) + "/server.list"); if (serverList.open(QFile::ReadOnly)) { QStringList list = QString(serverList.readAll()).trimmed().split("\n"); @@ -87,14 +89,17 @@ void DownloadController::startDownload(const QString &url) } QtConcurrent::run([=]() - { + { QString metaUrl = url + ".metalink"; qDebug() << "metalink" << metaUrl; bool useMetalink = false; - if (checkMeatlink(metaUrl)){ + if (checkMeatlink(metaUrl)) + { useMetalink = true; qDebug() << "useMetalink:" << useMetalink; - }else{ + } + else + { gennerateDomain(domains); // qDebug() << domains << domains.size(); } @@ -111,10 +116,12 @@ void DownloadController::startDownload(const QString &url) QString aria2ConnectionMax = "--max-concurrent-downloads=16"; QString aria2DNSCommand = "--async-dns-server=119.29.29.29,223.5.5.5"; - if (useMetalink){ + if (useMetalink) + { command.append(metaUrl.toUtf8()); } - else{ + else + { for (int i = 0; i < domains.size(); i++) { command.append(replaceDomain(url, domains.at(i)).replace("+","%2B").toUtf8()); //对+进行转译,避免oss出错 @@ -133,7 +140,8 @@ void DownloadController::startDownload(const QString &url) command.append(aria2ConnectionPerServer.toUtf8()); command.append(aria2ConnectionMax.toUtf8()); command.append(aria2DNSCommand.toUtf8()); - if (useMetalink){ + if (useMetalink) + { command.append(aria2NoSeeds.toUtf8()); } qDebug() << command; @@ -144,8 +152,7 @@ void DownloadController::startDownload(const QString &url) cmd->start(); cmd->waitForStarted(); //等待启动完成 - QObject::connect(cmd, &QProcess::readyReadStandardOutput, - [&]() + QObject::connect(cmd, &QProcess::readyReadStandardOutput, [&]() { //通过读取输出计算下载速度 QString message = cmd->readAllStandardOutput().data(); @@ -188,8 +195,7 @@ void DownloadController::startDownload(const QString &url) emit downloadProcess(speedInfo, downloadSizeRecord, fileSize); } }); - QObject::connect(cmd, &QProcess::readyReadStandardError, - [&]() + QObject::connect(cmd, &QProcess::readyReadStandardError, [&]() { emit errorOccur(cmd->readAllStandardError().data()); return; @@ -222,10 +228,16 @@ void DownloadController::startDownload(const QString &url) */ void DownloadController::stopDownload() { + if (pidNumber < 0) + { + return; + } + // 实现下载进程退出 QString killCmd = QString("kill -9 %1").arg(pidNumber); system(killCmd.toUtf8()); qDebug() << "kill aria2!"; + pidNumber = -1; } qint64 DownloadController::getFileSize(const QString &url) diff --git a/src/backend/downloadworker.h b/src/backend/downloadworker.h index d04290bc..5aeb353e 100644 --- a/src/backend/downloadworker.h +++ b/src/backend/downloadworker.h @@ -21,7 +21,7 @@ public: private: int threadNum; - int pidNumber; + int pidNumber = -1; QString filename; qint64 fileSize; QVector> ranges; diff --git a/src/backend/sparkapi.cpp b/src/backend/sparkapi.cpp index 8a2a4f5f..e2f841b6 100644 --- a/src/backend/sparkapi.cpp +++ b/src/backend/sparkapi.cpp @@ -1,39 +1,45 @@ #include "sparkapi.h" +#include +#include #include QString SparkAPI::serverUrl = ""; SparkAPI::SparkAPI(QObject *parent) : QObject(parent) { - QSettings readConfig(QDir::homePath() + "/.config/spark-store/config.ini", QSettings::IniFormat); - if (!readConfig.value("server/choose").toString().isEmpty() && readConfig.value("server/updated").toString() == "TRUE") + QSettings config(QStandardPaths::writableLocation(QStandardPaths::AppConfigLocation) + "/config.ini", QSettings::IniFormat); + if (!config.value("server/choose").toString().isEmpty() && config.value("server/updated").toBool()) { - SparkAPI::setServerUrl(readConfig.value("server/choose").toString()); + SparkAPI::setServerUrl(config.value("server/choose").toString()); } } + void SparkAPI::get(QUrl url) { QNetworkRequest request; HttpRequest *httprequest = new HttpRequest; request.setUrl(QUrl(url.toString().replace("+", "%2B"))); connect(httprequest, &HttpRequest::finished, [=](QString data) - { + { QByteArray arr = data.toUtf8(); - //解析Json - QJsonParseError error; - if(QJsonDocument::fromJson(arr,&error).isArray()) - { - auto doc = QJsonDocument::fromJson(arr,&error).array(); - emit finished(doc); - }else { - auto doc = QJsonDocument::fromJson(arr,&error).object(); - emit finishedObject(doc); - } + // 解析 Json + QJsonParseError error; + if(QJsonDocument::fromJson(arr,&error).isArray()) + { + auto doc = QJsonDocument::fromJson(arr,&error).array(); + emit finished(doc); + } else { + auto doc = QJsonDocument::fromJson(arr,&error).object(); + emit finishedObject(doc); + } + + httprequest->deleteLater(); + }); - httprequest->deleteLater(); }); httprequest->getRequest(request); } + void SparkAPI::getRAW(QUrl url) { QNetworkRequest request; @@ -45,30 +51,37 @@ void SparkAPI::getRAW(QUrl url) httprequest->deleteLater(); }); httprequest->getRequest(request); } + void SparkAPI::getAppList(QString type) { get(QUrl(getServerUrl() + "store/" + type + "/applist.json")); } + void SparkAPI::getSearchList(QString keyword) { get(QUrl("https://search.deepinos.org.cn/appinfo/search?keyword=" + keyword)); } + void SparkAPI::getAppInfo(QUrl spk) { get(QUrl(getServerUrl() + "store" + spk.path().replace("+", "%2B") + "/app.json")); } + void SparkAPI::getAppDownloadTimes(QUrl spk) { getRAW(QUrl(getServerUrl() + "store" + spk.path().replace("+", "%2B") + "/download-times.txt")); } + QString SparkAPI::getServerUrl() { return SparkAPI::serverUrl; } + QString SparkAPI::getImgServerUrl() { return SparkAPI::serverUrl; } + void SparkAPI::setServerUrl(QString url) { SparkAPI::serverUrl = url; diff --git a/src/backend/sparkapi.h b/src/backend/sparkapi.h index 1780e7ca..56451b2d 100644 --- a/src/backend/sparkapi.h +++ b/src/backend/sparkapi.h @@ -1,16 +1,21 @@ #ifndef SPARKAPI_H #define SPARKAPI_H + +#include "utils/httprequest.h" + #include #include #include #include -#include "utils/httprequest.h" -#include #include + class SparkAPI : public QObject { Q_OBJECT + public: + explicit SparkAPI(QObject *parent = nullptr); + static QString getServerUrl(); static QString getImgServerUrl(); static void setServerUrl(QString url); @@ -20,17 +25,14 @@ public: void getRAW(QUrl url); void getAppList(QString type); void getAppInfo(QUrl spk); - explicit SparkAPI(QObject *parent = nullptr); - -private: - static QString serverUrl; signals: void finished(QJsonArray); void finishedRAW(QString); void finishedObject(QJsonObject); -public slots: +private: + static QString serverUrl; }; #endif // SPARKAPI_H diff --git a/src/main.cpp b/src/main.cpp index e8f93934..7fe1b397 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,13 +1,11 @@ +#include "application.h" #include "mainwindow-dtk.h" -#include -#include -#include +#include #include -#include -#include #include -#include + +#include DCORE_USE_NAMESPACE DWIDGET_USE_NAMESPACE @@ -18,35 +16,36 @@ int main(int argc, char *argv[]) static const QString version = "Version 4.1.2"; 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"); - QSettings readConfig(QDir::homePath() + "/.config/spark-store/config.ini", QSettings::IniFormat); - QSettings *setConfig = new QSettings(QDir::homePath() + "/.config/spark-store/config.ini", QSettings::IniFormat); + static const QString buildDateTime = buildDate.toString("yyyy.MM.dd") + "-" + buildTime.toString("hh:mm:ss"); // 设置桌面环境环境变量 bool isDeepinOS = true; if (!QString(qgetenv("XDG_CURRENT_DESKTOP")).toLower().startsWith("deepin")) { - setenv("XDG_CURRENT_DESKTOP", "Deepin", 1); + qputenv("XDG_CURRENT_DESKTOP", "Deepin"); isDeepinOS = false; } + bool isWayland = false; auto e = QProcessEnvironment::systemEnvironment(); QString XDG_SESSION_TYPE = e.value(QStringLiteral("XDG_SESSION_TYPE")); QString WAYLAND_DISPLAY = e.value(QStringLiteral("WAYLAND_DISPLAY")); - if (XDG_SESSION_TYPE == QLatin1String("wayland") || WAYLAND_DISPLAY.contains(QLatin1String("wayland"), Qt::CaseInsensitive)) { isWayland = true; } - setConfig->setValue("build/isWayland", isWayland); - setConfig->setValue("build/isDeepinOS", isDeepinOS); + + QSettings config(QStandardPaths::writableLocation(QStandardPaths::AppConfigLocation) + "/config.ini", QSettings::IniFormat); + config.setValue("build/isWayland", isWayland); + config.setValue("build/isDeepinOS", isDeepinOS); // Check config file, if there is no wayland config, then set it to default, which means use wayland if possible. - if (!readConfig.contains("build/useWayland")) + if (!config.contains("build/useWayland")) { - setConfig->setValue("build/useWayland", true); + config.setValue("build/useWayland", true); } - bool useWayland = readConfig.value("build/useWayland").toBool(); + bool useWayland = config.value("build/useWayland").toBool(); qDebug() << "System Wayland enabled:" << isWayland << ". Spark Wayland enabled:" << useWayland; // Set display backend @@ -62,107 +61,57 @@ int main(int argc, char *argv[]) { qputenv("QT_QPA_PLATFORM", "dxcb"); } - DApplication::setAttribute(Qt::AA_EnableHighDpiScaling); // 开启 Hidpi 支持 + // 龙芯机器配置,使得 DApplication 能正确加载 QTWEBENGINE + qputenv("DTK_FORCE_RASTER_WIDGETS", "FALSE"); +// qputenv("QTWEBENGINE_CHROMIUM_FLAGS", "--disable-features=UseModernMediaControls"); +// qputenv("QTWEBENGINE_CHROMIUM_FLAGS", "--disable-web-security"); // 浏览器开启 GPU 支持 +#ifdef __sw_64__ + qputenv("QTWEBENGINE_CHROMIUM_FLAGS", "--ignore-gpu-blocklist --enable-gpu-rasterization --enable-native-gpu-memory-buffers --enable-accelerated-video-decode --no-sandbox"); +#else qputenv("QTWEBENGINE_CHROMIUM_FLAGS", "--ignore-gpu-blocklist --enable-gpu-rasterization --enable-native-gpu-memory-buffers --enable-accelerated-video-decode"); +#endif + + DApplication::setAttribute(Qt::AA_EnableHighDpiScaling); // 开启 Hidpi 支持 + // 强制使用 DTK 平台插件 QVector fakeArgs(argc + 2); fakeArgs[0] = argv[0]; - QString fakeArgs1 = "-platformtheme"; - QByteArray fakeArgsTemp = fakeArgs1.toLatin1(); // must - fakeArgs[1] = fakeArgsTemp.data(); - fakeArgs1 = "deepin"; - fakeArgsTemp = fakeArgs1.toLatin1(); // must - fakeArgs[2] = fakeArgsTemp.data(); - + fakeArgs[1] = const_cast("-platformtheme"); + fakeArgs[2] = const_cast("deepin"); for (int i = 1; i < argc; i++) - fakeArgs[i + 2] = argv[i]; - int fakeArgc = argc + 2; // DApplication的argc要用引用,避免c++编译器优化 - DApplication a(fakeArgc, fakeArgs.data()); - - // 初始化日志模块 (默认日志位置 ~/.cache/deepin/spark-store) - DLogManager::registerConsoleAppender(); - DLogManager::registerFileAppender(); - - // Wayland 环境下使用,防止子控件 Native 化 - if (!DPlatformWindowHandle::pluginVersion().isEmpty()) { - a.setAttribute(Qt::AA_DontCreateNativeWidgetSiblings, true); + fakeArgs[i + 2] = argv[i]; } - a.setAttribute(Qt::AA_UseHighDpiPixmaps); - a.setApplicationDisplayName("Spark Store"); + int fakeArgc = argc + 2; // QCoreApplication 的 argc 要用引用,避免 c++ 编译器优化 + Application a(fakeArgc, fakeArgs.data()); + // 设置版本和构建时间 + a.setVersionAndBuildDateTime(version, buildDateTime); - a.loadTranslator(); // 载入翻译 - - if (readConfig.value("build/version").toString() != version) - { - qDebug() << "Spark Store has been updated!"; - setConfig->setValue("build/version", version); - setConfig->setValue("build/time", buildDate.toString("yyyy.MM.dd") + "-" + buildTime.toString()); - } - setConfig->deleteLater(); - - // Customized DAboutDialog - - DAboutDialog dialog; - a.setAboutDialog(&dialog); - dialog.setLicense(QObject::tr("We publish this program under GPL V3")); - dialog.setVersion(DApplication::buildVersion(readConfig.value("build/version").toString() + "-" + "Flamescion" + "-" + readConfig.value("build/time").toString())); - dialog.setProductIcon(QIcon::fromTheme("spark-store")); // 设置Logo - dialog.setProductName(QLabel::tr("Spark Store")); - dialog.setDescription( - QObject::tr( - "An appstore powered by community
" - "https://www.spark-app.store
" - "Spark developers")); - - dialog.setProductName(QLabel::tr("Spark Store")); - dialog.setCompanyLogo(QPixmap(":/spark-store.png")); - dialog.setWebsiteName(QObject::tr("The Spark Project")); - dialog.setWebsiteLink("https://gitee.com/deepin-community-store"); - - a.setOrganizationName("spark-union"); - a.setProductName(QObject::tr("Spark Store")); - a.setApplicationName("Spark Store"); // 不用翻译,影响 ~/.local/share/spark-union 下文件夹名称 - a.setApplicationDisplayName(QObject::tr("Spark Store")); // 设置窗口显示标题 (Wayland 下会显示 Qt 原生标题栏) - a.setWindowIcon(QIcon::fromTheme("spark-store")); - a.setApplicationDescription( - QObject::tr( - "An appstore powered by deepin community
" - "https://www.spark-app.store
" - "Spark developers

" - "Published under GPL V3")); // 限制单实例运行 if (!a.setSingleInstance("spark-store")) { - qDebug() << "The application is already running!"; - QDBusInterface iface("com.gitee.spark.store", - "/com/gitee/spark/store", - "com.gitee.spark.store", - QDBusConnection::sessionBus()); - - QString arg1 = argv[1]; - - iface.asyncCall("activeWindow", arg1); - + qWarning() << "Another instance has already started, activating..."; return -1; } DGuiApplicationHelper::instance()->setPaletteType(DGuiApplicationHelper::LightType); // 固定主题为浅色主题 - DApplicationSettings settings; // 定义 DApplicationSettings,自动保存主题设置 + DApplicationSettings settings; // 定义 DApplicationSettings,自动保存主题设置 MainWindow w; // 让打开时界面显示在正中 Dtk::Widget::moveToCenter(&w); - QString arg1 = argv[1]; - if (arg1.startsWith("spk://")) + if (argc > 1) { - w.openUrl(QUrl(argv[1])); + QString arg1 = argv[1]; + if (arg1.trimmed().startsWith("spk://")) + { + w.openUrl(QUrl(argv[1])); + } } w.show(); - w.setWindowTitle("Spark Store"); return a.exec(); } diff --git a/src/mainwindow-dtk.cpp b/src/mainwindow-dtk.cpp index 8df18ec1..89feaa08 100644 --- a/src/mainwindow-dtk.cpp +++ b/src/mainwindow-dtk.cpp @@ -18,11 +18,12 @@ MainWindow::MainWindow(QWidget *parent) : BaseWidgetOpacity(parent), ui(new Ui::MainWindow) { ui->setupUi(this); + setWindowTitle(QObject::tr("Spark Store")); initConfig(); - moveToCenter(this); // 让窗口居中显示 WidgetAnimation::widgetOpacity(this, true); + searchEdit = new DSearchEdit(ui->titlebar); downloadlistwidget = new DownloadListWidget; downloadButton = new ProgressButton(ui->titlebar); backButtom = new QPushButton(ui->titlebar); @@ -75,9 +76,6 @@ MainWindow::MainWindow(QWidget *parent) if (themeType == DGuiApplicationHelper::DarkType) { //深色模式 setMaskColor(QColor("#2a2b2b")); - this->setStyleSheet("#mainpage{background-color: transparent;border-radius:14px;}\ - QLabel#cardtitle,QLabel#title,QLabel#title_1,QLabel#title_2,QLabel#title_3 {color:#FFFFFF}\ - "); backButtom->setIcon(QIcon(":/icon/dark/back.svg")); downloadButton->setIcon(":/icon/dark/download.svg"); downloadButton->setBackgroundColor(QColor("#444444")); @@ -98,9 +96,6 @@ MainWindow::MainWindow(QWidget *parent) } else { //亮色模式 setMaskColor(QColor("#f3f7f8")); - this->setStyleSheet("#mainpage{background-color: transparent;border-radius:14px;}\ - QLabel#cardtitle,QLabel#title,QLabel#title_1,QLabel#title_2,QLabel#title_3 {color:#000000}\ - "); backButtom->setIcon(QIcon(":/icon/light/back.svg")); downloadButton->setBackgroundColor(QColor("#e3e4e4")); downloadButton->setColor(QColor("#66CCFF")); @@ -153,18 +148,17 @@ MainWindow::MainWindow(QWidget *parent) backButtom->hide(); ui->titlebar->setIcon(QIcon::fromTheme(":/icon/logo.svg")); - // Check wayland configs - QSettings readConfig(QDir::homePath() + "/.config/spark-store/config.ini", QSettings::IniFormat); - QWidget *w_titlebar = new QWidget(ui->titlebar); QHBoxLayout *ly_titlebar = new QHBoxLayout(w_titlebar); - QLabel *title = new QLabel(this); + QLabel *title = new QLabel(ui->titlebar); title->setText(tr("Spark Store")); searchEdit->setPlaceholderText(tr("Search or enter spk://")); ly_titlebar->addWidget(title); ly_titlebar->addWidget(backButtom); - if (!readConfig.value("build/isDeepinOS").toBool() && readConfig.value("build/useWayland").toBool()) + // Check wayland configs + QSettings config(QStandardPaths::writableLocation(QStandardPaths::AppConfigLocation) + "/config.ini", QSettings::IniFormat); + if (!config.value("build/isDeepinOS").toBool() && config.value("build/useWayland").toBool()) { // Wayland 搜索栏居中 ly_titlebar->addStretch(WaylandSearchCenter); @@ -219,14 +213,16 @@ MainWindow::MainWindow(QWidget *parent) { openUrl(spk); }); emit DGuiApplicationHelper::instance()->themeTypeChanged(DGuiApplicationHelper::instance()->themeType()); - initDbus(); + connect(DGuiApplicationHelper::instance(), &DGuiApplicationHelper::newProcessInstance, this, &MainWindow::onNewProcessInstance); } MainWindow::~MainWindow() { - delete searchEdit; - delete downloadlistwidget; delete ui; + + if (downloadlistwidget) { + downloadlistwidget->deleteLater(); + } } void MainWindow::initDbus() @@ -240,13 +236,21 @@ void MainWindow::initDbus() void MainWindow::onGetUrl(const QString &url) { - if (url.left(6) == "spk://") - { + if (url.trimmed().startsWith("spk://")) { openUrl(QUrl(url)); } activateWindow(); } +void MainWindow::onNewProcessInstance(qint64 pid, const QStringList &arguments) +{ + Q_UNUSED(pid) + + if (arguments.size() > 1) { + onGetUrl(arguments.value(1)); + } +} + void MainWindow::openUrl(QUrl url) { if (url.toString().startsWith("spk://")) @@ -279,6 +283,7 @@ void MainWindow::switchPage(int now) // 临时方案,回家后修改 backButtom->hide(); } ui->stackedWidget->setCurrentIndex(now); + ui->stackedWidget->currentWidget()->setFocus(); pageHistory << now; } diff --git a/src/mainwindow-dtk.h b/src/mainwindow-dtk.h index 1b2ea823..3eab0794 100644 --- a/src/mainwindow-dtk.h +++ b/src/mainwindow-dtk.h @@ -39,20 +39,20 @@ private: void switchPage(int now); void updateUi(int now); +private slots: + //接受来自dbus的url + void onGetUrl(const QString &url); + void onNewProcessInstance(qint64 pid, const QStringList &arguments); + void on_pushButton_14_clicked(); + private: QList pageHistory; + Ui::MainWindow *ui; DownloadListWidget *downloadlistwidget; ProgressButton *downloadButton; QPushButton *backButtom; - DSearchEdit *searchEdit = new DSearchEdit; - Ui::MainWindow *ui; - -private slots: - //接受来自dbus的url - void onGetUrl(const QString &url); - void on_pushButton_14_clicked(); - + DSearchEdit *searchEdit; }; #endif // MAINWINDOWDTK_H diff --git a/src/mainwindow-dtk.ui b/src/mainwindow-dtk.ui index 5399dbd0..ccccf141 100644 --- a/src/mainwindow-dtk.ui +++ b/src/mainwindow-dtk.ui @@ -7,7 +7,7 @@ 0 0 1190 - 651 + 656 @@ -34,6 +34,12 @@ true + + .QWidget#mainpage { + background: transparent; + border-radius: 14px; +} + 0 diff --git a/src/pages/appintopage.cpp b/src/pages/appintopage.cpp index 6d4e0752..86b2483a 100644 --- a/src/pages/appintopage.cpp +++ b/src/pages/appintopage.cpp @@ -272,7 +272,8 @@ void AppIntoPage::setTheme(bool dark) { if (dark) { - QString frameStyleSheet = "#frame,#frame_2,#frame_3,#frame_4{background-color: #252525;border-radius:14px;border:1px solid rgb(64, 64, 64);}"; + QString frameStyleSheet ="#frame,#frame_2,#frame_3,#frame_4 {background-color: #252525; border-radius: 14px; border: 1px solid rgb(64, 64, 64);}\ + QLabel#cardtitle,QLabel#title,QLabel#title_1,QLabel#title_2,QLabel#title_3 {color: #FFFFFF}"; ui->frame->setStyleSheet(frameStyleSheet); ui->frame_2->setStyleSheet(frameStyleSheet); ui->frame_3->setStyleSheet(frameStyleSheet); @@ -284,11 +285,10 @@ void AppIntoPage::setTheme(bool dark) ui->icon_4->setPixmap(QPixmap(":/icon/dark/text.svg")); ui->icon_5->setPixmap(QPixmap(":/icon/dark/folder.svg")); ui->icon_6->setPixmap(QPixmap(":/icon/dark/globe.svg")); - } - else - { - // 亮色模式 - QString frameStyleSheet = "#frame,#frame_2,#frame_3,#frame_4{background-color: #fbfbfb;border-radius:14px;border:1px solid rgb(229,229,229);}"; + }else { + //亮色模式 + QString frameStyleSheet ="#frame,#frame_2,#frame_3,#frame_4 {background-color: #fbfbfb; border-radius: 14px; border: 1px solid rgb(229,229,229);}\ + QLabel#cardtitle,QLabel#title,QLabel#title_1,QLabel#title_2,QLabel#title_3 {color: #000000}"; ui->frame->setStyleSheet(frameStyleSheet); ui->frame_2->setStyleSheet(frameStyleSheet); ui->frame_3->setStyleSheet(frameStyleSheet); @@ -336,29 +336,30 @@ void AppIntoPage::on_downloadButton_clicked() void AppIntoPage::on_pushButton_3_clicked() { QtConcurrent::run([=]() - { - ui->downloadButton->setEnabled(false); - ui->pushButton_3->setEnabled(false); + { + ui->downloadButton->setEnabled(false); + ui->pushButton_3->setEnabled(false); - QProcess uninstall; - uninstall.start("pkexec", QStringList() << "apt" << "purge" << "-y" << info["Pkgname"].toString().toLower()); - uninstall.waitForFinished(-1); + QProcess uninstall; + uninstall.start("pkexec", QStringList() << "apt" << "purge" << "-y" << info["Pkgname"].toString().toLower()); + uninstall.waitForFinished(-1); - QProcess check; - check.start("dpkg", QStringList() << "-s" << info["Pkgname"].toString().toLower()); - check.waitForFinished(10*1000); + QProcess check; + check.start("dpkg", QStringList() << "-s" << info["Pkgname"].toString().toLower()); + check.waitForFinished(10*1000); - if (check.readAllStandardOutput().isEmpty()) - { - ui->downloadButton->setText(tr("Install")); - ui->pushButton_3->hide(); + if (check.readAllStandardOutput().isEmpty()) + { + ui->downloadButton->setText(tr("Install")); + ui->pushButton_3->hide(); - updatesEnabled(); - Utils::sendNotification("spark-store",tr("Spark Store"),tr("Uninstall succeeded")); - } + updatesEnabled(); + Utils::sendNotification("spark-store",tr("Spark Store"),tr("Uninstall succeeded")); + } - ui->downloadButton->setEnabled(true); - ui->pushButton_3->setEnabled(true); }); + ui->downloadButton->setEnabled(true); + ui->pushButton_3->setEnabled(true); + }); } void AppIntoPage::on_shareButton_clicked() diff --git a/src/pages/settingspage.cpp b/src/pages/settingspage.cpp index 1a17213c..859caf3f 100644 --- a/src/pages/settingspage.cpp +++ b/src/pages/settingspage.cpp @@ -1,10 +1,22 @@ #include "settingspage.h" #include "ui_settingspage.h" +#include "../backend/sparkapi.h" +#include "utils/utils.h" + +#include +#include +#include + +#define TMP_PATH "/tmp/spark-store" + bool SettingsPage::isdownload = false; -SettingsPage::SettingsPage(QWidget *parent) : QWidget(parent), - ui(new Ui::SettingsPage) + +SettingsPage::SettingsPage(QWidget *parent) + : QWidget(parent) + , ui(new Ui::SettingsPage) { ui->setupUi(this); + configCanSave = false; initConfig(); } @@ -25,20 +37,22 @@ void SettingsPage::setTheme(bool dark) void SettingsPage::readServerList() { // 读取服务器列表并初始化 - QFile file(QDir::homePath().toUtf8() + "/.config/spark-store/server.list"); + QFile file(QStandardPaths::writableLocation(QStandardPaths::AppConfigLocation) + "/server.list"); // 判断文件是否存在 if (!file.exists()) { ui->comboBox_server->addItem("https://d.store.deepinos.org.cn/"); + return; } if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) { - qDebug() << "无法读取server.list"; + qWarning() << "无法读取 server.list"; + return; } - // 创建QTextStream对象 + // 创建 QTextStream 对象 QTextStream textStream(&file); QString lineData = textStream.readLine(); // 读取文件的第一行 @@ -71,12 +85,12 @@ void SettingsPage::initConfig() readServerList(); // 读取服务器URL并初始化菜单项的链接 - QSettings readConfig(QDir::homePath() + "/.config/spark-store/config.ini", QSettings::IniFormat); - if (!readConfig.value("server/choose").toString().isEmpty() && readConfig.value("server/updated").toString() == "TRUE") + QSettings config(QStandardPaths::writableLocation(QStandardPaths::AppConfigLocation) + "/config.ini", QSettings::IniFormat); + if (!config.value("server/choose").toString().isEmpty() && config.value("server/updated").toBool()) { - qDebug() << readConfig.value("server/choose").toString(); - ui->comboBox_server->setCurrentText(readConfig.value("server/choose").toString()); - SparkAPI::setServerUrl(readConfig.value("server/choose").toString()); + qDebug() << config.value("server/choose").toString(); + ui->comboBox_server->setCurrentText(config.value("server/choose").toString()); + SparkAPI::setServerUrl(config.value("server/choose").toString()); } configCanSave = true; //  防止触发保存配置信号 } @@ -89,30 +103,31 @@ SettingsPage::~SettingsPage() void SettingsPage::on_pushButton_updateServer_clicked() { QtConcurrent::run([=]() - { + { ui->pushButton_updateServer->setEnabled(false); ui->comboBox_server->clear(); - QFile::remove(QDir::homePath().toUtf8() + "/.config/spark-store/server.list"); - system("curl -o " + QDir::homePath().toUtf8() + "/.config/spark-store/server.list https://d.store.deepinos.org.cn/store/server-and-mirror.list"); + QFile::remove(QStandardPaths::writableLocation(QStandardPaths::AppConfigLocation) + "/server.list"); + system("curl -o " + QStandardPaths::writableLocation(QStandardPaths::AppConfigLocation).toUtf8() + "/server.list https://d.store.deepinos.org.cn/store/server-and-mirror.list"); ui->pushButton_updateServer->setEnabled(true); readServerList(); - ui->comboBox_server->setCurrentIndex(0); }); + ui->comboBox_server->setCurrentIndex(0); + }); } void SettingsPage::on_comboBox_server_currentIndexChanged(const QString &arg1) { SparkAPI::setServerUrl(arg1); // 服务器信息更新 qDebug() << arg1; - const QString updatedInfo = "TRUE"; - if (configCanSave) + bool updatedInfo = true; + if(configCanSave) { // ui->label_setting1->show(); - QSettings *setConfig = new QSettings(QDir::homePath() + "/.config/spark-store/config.ini", QSettings::IniFormat); - setConfig->setValue("server/choose", arg1); - setConfig->setValue("server/updated", updatedInfo); - setConfig->deleteLater(); + QSettings config(QStandardPaths::writableLocation(QStandardPaths::AppConfigLocation) + "/config.ini", QSettings::IniFormat); + config.setValue("server/choose", arg1); + config.setValue("server/updated", updatedInfo); + config.sync(); } } @@ -176,20 +191,21 @@ quint64 SettingsPage::dirFileSize(const QString &path) void SettingsPage::on_pushButton_updateApt_clicked() { QtConcurrent::run([=]() - { + { ui->pushButton_updateApt->setEnabled(false); ui->label_aptserver->setText(tr("Updating, please wait...")); emit openUrl(QUrl("spk://store/tools/spark-store")); ui->label_aptserver->setText(tr("")); - ui->pushButton_updateApt->setEnabled(true); }); + ui->pushButton_updateApt->setEnabled(true); + }); } void SettingsPage::on_pushButton_clear_clicked() { QtConcurrent::run([=]() - { + { ui->pushButton_clear->setEnabled(false); QDir tmpdir("/tmp/spark-store"); @@ -201,19 +217,22 @@ void SettingsPage::on_pushButton_clear_clicked() } Utils::sendNotification("spark-store",tr("Spark Store"),tr("Temporary cache was cleaned")); ui->pushButton_clear->setEnabled(true); - updateUI(); }); + updateUI(); + }); } void SettingsPage::on_pushButton_clearWebCache_clicked() { QtConcurrent::run([=]() - { - QString dataLocal = QStandardPaths::writableLocation(QStandardPaths::AppLocalDataLocation); - qDebug() << dataLocal; - QDir dataDir(dataLocal); + { + QString localDataLocation = QStandardPaths::writableLocation(QStandardPaths::AppLocalDataLocation) + "/QtWebEngine"; + qDebug() << localDataLocation; + QDir dataDir(localDataLocation); dataDir.removeRecursively(); - dataLocal = QStandardPaths::writableLocation(QStandardPaths::TempLocation); - qDebug() << dataLocal; - QDir cacheDir(dataLocal); - cacheDir.removeRecursively(); }); + + QString cacheLocation = QStandardPaths::writableLocation(QStandardPaths::CacheLocation) + "/QtWebEngine"; + qDebug() << cacheLocation; + QDir cacheDir(cacheLocation); + cacheDir.removeRecursively(); + }); } diff --git a/src/pages/settingspage.h b/src/pages/settingspage.h index 62942839..f65347f4 100644 --- a/src/pages/settingspage.h +++ b/src/pages/settingspage.h @@ -2,14 +2,7 @@ #define SETTINGSPAGE_H #include -#include -#include -#include -#include -#include -#include "../backend/sparkapi.h" -#include "utils/utils.h" -#define TMP_PATH "/tmp/spark-store" +#include namespace Ui { class SettingsPage; diff --git a/src/spark-store.pro b/src/spark-store.pro index d01287b7..1d10d002 100644 --- a/src/spark-store.pro +++ b/src/spark-store.pro @@ -4,7 +4,7 @@ # #------------------------------------------------- -QT += core gui network concurrent webenginewidgets dbus svg +QT += core gui concurrent dbus network svg webenginewidgets greaterThan(QT_MAJOR_VERSION, 4): QT += widgets @@ -22,78 +22,75 @@ DEFINES += QT_DEPRECATED_WARNINGS # You can also select to disable deprecated APIs only up to a certain version of Qt. #DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0 -DEFINES += QT_APP_DEBUG +# Disable qWarning / qDebug output in Release +# CONFIG(release, debug|release): DEFINES += QT_NO_WARNING_OUTPUT QT_NO_DEBUG_OUTPUT CONFIG += c++11 link_pkgconfig PKGCONFIG += dtkcore dtkgui dtkwidget -# Disable qWarning / qDebug output in Release -CONFIG(release, debug|release): DEFINES += QT_NO_WARNING_OUTPUT QT_NO_DEBUG_OUTPUT - -# Update translation files -CONFIG(release, debug|release): system(bash $${PWD}/translate_generation.sh) - -TRANSLATIONS += \ - ../translations/spark-store_en.ts \ - ../translations/spark-store_fr.ts \ - ../translations/spark-store_zh_CN.ts - SOURCES += \ - dbus/dbussparkstoreservice.cpp \ - main.cpp \ - mainwindow-dtk.cpp \ + backend/downloadworker.cpp \ + backend/image_show.cpp \ backend/sparkapi.cpp \ + dbus/dbussparkstoreservice.cpp \ + pages/appintopage.cpp \ + pages/applistpage.cpp \ pages/settingspage.cpp \ + utils/httprequest.cpp \ utils/utils.cpp \ utils/widgetanimation.cpp \ - widgets/common/progressbutton.cpp \ - widgets/common/webenginepage.cpp \ - widgets/common/webengineview.cpp \ - widgets/downloadlistwidget.cpp \ + widgets/base/basewidgetopacity.cpp \ widgets/common/downloaditem.cpp \ + widgets/common/progressbutton.cpp \ widgets/common/smoothlistwidget.cpp \ widgets/common/smoothscrollbar.cpp \ - utils/httprequest.cpp \ - pages/applistpage.cpp \ - backend/downloadworker.cpp \ - pages/appintopage.cpp \ + widgets/common/webenginepage.cpp \ + widgets/common/webengineview.cpp \ widgets/big_image.cpp \ - backend/image_show.cpp \ - widgets/base/basewidgetopacity.cpp + widgets/downloadlistwidget.cpp \ + application.cpp \ + main.cpp \ + mainwindow-dtk.cpp HEADERS += \ - dbus/dbussparkstoreservice.h \ - mainwindow-dtk.h \ + backend/downloadworker.h \ + backend/image_show.h \ backend/sparkapi.h \ + dbus/dbussparkstoreservice.h \ + pages/appintopage.h \ + pages/applistpage.h \ pages/settingspage.h \ + utils/httprequest.h \ utils/utils.h \ utils/widgetanimation.h \ - widgets/common/progressbutton.h \ - widgets/common/webenginepage.h \ - widgets/common/webengineview.h \ - widgets/downloadlistwidget.h \ + widgets/base/basewidgetopacity.h \ widgets/common/downloaditem.h \ + widgets/common/progressbutton.h \ widgets/common/smoothlistwidget.h \ widgets/common/smoothscrollbar.h \ - utils/httprequest.h \ - pages/applistpage.h \ - backend/downloadworker.h \ - pages/appintopage.h \ + widgets/common/webenginepage.h \ + widgets/common/webengineview.h \ widgets/big_image.h \ - backend/image_show.h \ - widgets/base/basewidgetopacity.h + widgets/downloadlistwidget.h \ + application.h \ + mainwindow-dtk.h FORMS += \ - mainwindow-dtk.ui \ + pages/appintopage.ui \ + pages/applistpage.ui \ pages/settingspage.ui \ - widgets/downloadlistwidget.ui \ widgets/common/downloaditem.ui \ - pages/applistpage.ui \ - pages/appintopage.ui + widgets/downloadlistwidget.ui \ + mainwindow-dtk.ui RESOURCES += \ assets/assets.qrc +TRANSLATIONS += \ + ../translations/spark-store_en.ts \ + ../translations/spark-store_fr.ts \ + ../translations/spark-store_zh_CN.ts + # Default rules for deployment. qnx: target.path = /tmp/$${TARGET}/bin else: unix:!android: target.path = /opt/durapps/$${TARGET}/bin diff --git a/src/widgets/common/downloaditem.cpp b/src/widgets/common/downloaditem.cpp index 538942f8..2c8513b5 100644 --- a/src/widgets/common/downloaditem.cpp +++ b/src/widgets/common/downloaditem.cpp @@ -98,7 +98,7 @@ void DownloadItem::install(int t) ui->label_2->setText(tr("Installing")); QtConcurrent::run([=]() - { + { QProcess installer; switch(t) { diff --git a/src/widgets/downloadlistwidget.cpp b/src/widgets/downloadlistwidget.cpp index 6c611150..450cd5d5 100644 --- a/src/widgets/downloadlistwidget.cpp +++ b/src/widgets/downloadlistwidget.cpp @@ -55,7 +55,6 @@ DownloadListWidget::~DownloadListWidget() if (downloadController) { downloadController->stopDownload(); - downloadController->deleteLater(); } delete ui; diff --git a/translate_generation.sh b/translate_generation.sh index 9304a50a..f64e4ca0 100755 --- a/translate_generation.sh +++ b/translate_generation.sh @@ -1,10 +1,6 @@ #!/bin/bash # this file is used to auto-generate .qm file from .ts file. -ts_list=(`ls ./translations/*.ts`) +cd $(dirname $0) -for ts in "${ts_list[@]}" -do - printf "\nprocess ${ts}\n" - lrelease "${ts}" -done +lrelease ./src/spark-store.pro diff --git a/translate_update.sh b/translate_update.sh new file mode 100755 index 00000000..6c9b030f --- /dev/null +++ b/translate_update.sh @@ -0,0 +1,6 @@ +#!/bin/bash +# this file is used to auto-update .ts file. + +cd $(dirname $0) + +lupdate ./src/spark-store.pro -no-obsolete diff --git a/translations/spark-store_en.ts b/translations/spark-store_en.ts index 25a689ab..29d43305 100644 --- a/translations/spark-store_en.ts +++ b/translations/spark-store_en.ts @@ -10,8 +10,8 @@ - - + + Download @@ -174,47 +174,47 @@ - + Click Open - - - + + + Reinstall - + Upgrade - - - + + + Install - + Installing - - + + Spark Store - + Uninstall succeeded - + The URL has been copied to the clipboard @@ -232,6 +232,19 @@ + + DAboutDialog + + + Version: %1 + + + + + %1 is released under %2 + + + DownloadItem @@ -275,59 +288,59 @@ - + Download Complete. - - - + + + Spark Store - + Installing - + Installation complete. - + Finish - + Retry - + Error happened in dpkg progress , you can try it again. - + Error happened in dpkg progress , you can try it again - + dpkg progress had been aborted,you can retry installation. - + dpkg progress had been aborted,you can retry installation - + Download canceled @@ -358,141 +371,123 @@ - + Home - + Network - + Chat - + Music - + Video - + Picture - + Game - + Office - + Reading - + Development - + Tool - + Theme - + Other - + APP Upgrade - + Submit App - + Submit App with client(Recommanded) - + Settings - + APP Upgrade and Install Settings - + Spark Store - + Search or enter spk:// - - QLabel - - - - Spark Store - - - QObject - - We publish this program under GPL V3 - - - - - <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 Store - - The Spark Project + + <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 Store - - - - - <span style='font-size:10pt;font-weight:60;'>An appstore powered by deepin 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><br/><br/>Published under GPL V3 + + Spark Project @@ -584,30 +579,19 @@ - + Updating, please wait... - + Spark Store - + Temporary cache was cleaned - - Widget - - Share - Spk share link - - - 0B - 0B - - diff --git a/translations/spark-store_fr.ts b/translations/spark-store_fr.ts index ea99fddb..8bfdd7ec 100644 --- a/translations/spark-store_fr.ts +++ b/translations/spark-store_fr.ts @@ -10,8 +10,8 @@ - - + + Download @@ -174,47 +174,47 @@ - + Click Open - - - + + + Reinstall - + Upgrade - - - + + + Install - + Installing - - + + Spark Store - + Uninstall succeeded - + The URL has been copied to the clipboard @@ -232,6 +232,19 @@ + + DAboutDialog + + + Version: %1 + + + + + %1 is released under %2 + + + DownloadItem @@ -275,59 +288,59 @@ - + Download Complete. - - - + + + Spark Store - + Installing - + Installation complete. - + Finish - + Retry - + Error happened in dpkg progress , you can try it again. - + Error happened in dpkg progress , you can try it again - + dpkg progress had been aborted,you can retry installation. - + dpkg progress had been aborted,you can retry installation - + Download canceled @@ -358,152 +371,123 @@ - + Home - + Network - + Chat - + Music - + Video - + Picture - + Game - + Office - + Reading - + Development - + Tool - + Theme - + Other - + APP Upgrade - + Submit App - + Submit App with client(Recommanded) - + Settings - + APP Upgrade and Install Settings - + Spark Store - + Search or enter spk:// - - QLabel - - Spark应用商店 - Spark Store - - - 社区驱动的一款为第三方应用商店,为改变而生 -本程序按GPL第三版开源 - Un app store tier alimenté par la communauté Deepin -Spark Store est publié sous licence GPL V3 -Nous sommes nés pour le changement. - - - - - Spark Store - - - QObject - - We publish this program under GPL V3 - - - - - <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> - - - - - The Spark Project + + + + Spark Store - - - 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 deepin 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><br/><br/>Published under GPL V3 + + Spark Project @@ -595,212 +579,19 @@ Nous sommes nés pour le changement. - + Updating, please wait... - + Spark Store - + Temporary cache was cleaned - - Widget - - 视频播放 - Lecteurs vidéo et créateurs vidéo - Vidéo - - - 下载列表 - Liste de téléchargement - - - 系统工具 - Outils - - - 主题美化 - Thème des icônes et autres - Thèmes - - - 音乐欣赏 - Musique - - - 编程开发 - Développement - - - 办公学习 - Bureau - - - 阅读翻译 - Traduire - - - 其他应用 - Autres - - - 商店首页 - Accueil - - - 图形图像 - Images - - - 游戏娱乐 - Jeux - - - 社交沟通 - Chat - - - 网络应用 - Réseau - - - 当前下载列表为空 - La liste de téléchargement est vide - - - 打开文件夹 - Ouvrir dans le gestionnaire de fichiers - - - 安装 - Installer - - - 卸载 - Supprimer - - - 官网 - Site - - - 软件名 - Nom - - - 图标 - Icon - - - 分享 - Partager - - - 详细介绍 - Détails - - - <html><head/><body><p>由社区爱好者开发的软件商店</p></body></html> - <html><head/><body><p>magasin de logiciels développé par des passionnés de la communauté</p></body></html> - - - 软件截图 - Captures d'écran - - - 线路设置 - Line Settings - - - 线路选择: - Choisissez: - - - 刷新 - Mise à jour - - - 重启商店后生效 - Redémarrez pour prendre effet - - - <html><head/><body><p>源服务器的作用是保证软件更新,并且支持使用apt工具获取软件。通常我们更建议你使用第一个线路作为更新源,一般是最稳定的。</p></body></html> - <html><head/><body><p>Le rôle du serveur source est de s'assurer que le logiciel est mis à jour et prend en charge l'utilisation de l'outil apt pour obtenir le logiciel. Nous préférons généralement que vous utilisiez la première ligne comme source de mise à jour, qui est généralement la plus stable. </p></body></html> - - - 更新源 - Mettre à jour la source APT - - - 更新源服务器: - Source APT: - - - 服务器 - serveur - - - 缓存目录 - Temp - - - 清空 - Nettoyer - - - 因为这个目录位于/tmp下,所以即使你不手动清空的话,其也将在系统重启时自动清空。 - Étant donné que ce répertoire se trouve sous /tmp, même si vous ne l'effacez pas manuellement, il sera effacé automatiquement au redémarrage du système. - - - 目录大小: - Taille: - - - 0B - 0B - - - 目录位置:/tmp/spark-store - Emplacement:/tmp/spark-store - - - 关于我们 - À propos de nous - - - <html><head/><body><p>我们并不是官方团队,和你一样,我们也只是众多Linux/deepin系统爱好者和用户之中的一员,我们开发并且运营这个“Spark应用商店”,是为了让社区的朋友们一起分享好用的软件,或者一起参与开发,让大家都用到最新的,最优秀的软件。</p><p>我们并没有因此盈利,所有开发和维护人员都不会获得报酬,我们的主要支出大部分依赖于社区对我们的捐助,很感谢大家,这部分捐助让我们并不需要耗费太多精力去担心资金问题。</p><p>我们的服务和开发的软件都是免费供给大家使用,交流,学习的,但是在您的使用过程中一定要遵守当地的法律法规,否则出现任何问题和我们无关。</p><p>如果商店中任何一部分有侵犯您权益的行为,请告知我们&lt;jifengshenmo@outlook.com&gt;,我们会第一时间删除侵权内容。</p><p>如果你也想参与我们,不管是参与开发,设计,投递还是投稿作品,我们都欢迎你的加入。</p><p>QQ群:872690351<br/></p></body></html> - <html><head/><body><p>Nous ne sommes pas l'équipe officielle, tout comme vous, nous ne sommes qu'un des nombreux passionnés et utilisateurs de systèmes Linux / deepin, nous développons et gérons le "Spark Store"! ", est de rassembler la communauté pour partager des logiciels utiles, ou pour participer au développement ensemble, afin que nous utilisions tous les derniers et meilleurs logiciels. </p><p> Nous n'en tirons aucun profit, tous les développeurs et mainteneurs ne sont pas payés, et nous comptons sur les dons de la communauté pour la plupart de nos dépenses, dont nous sommes reconnaissants et qui nous permettent de ne pas dépenser trop d'énergie se soucier du financement. </p><p>Notre service et nos logiciels sont gratuits pour tout le monde à utiliser, à communiquer et à apprendre, mais vous devez vous conformer aux lois et réglementations locales dans le processus de votre utilisation, sinon tout problème n'a rien à voir avec nous. </p><p>Si une partie du magasin enfreint vos droits, veuillez nous en informer &lt;jifengshenmo@outlook.com&gt; nous retirerons le contenu en infraction dès que possible. </p><p>Si vous souhaitez également vous impliquer avec nous, que vous soyez impliqué dans le développement, la conception, le pitching ou la soumission de travaux, nous vous invitons à nous rejoindre. </p><p>QQ group:872690351<br/></p></body></html> - - - - downloadlist - - 名称 - Nom - - - 等待开始下载 - Attendez pour téléchargerd - Attendez pour télécharger - - - 安装 - Installer - - - 取消 - Annuler - - - 详情 - Détail - - diff --git a/translations/spark-store_zh_CN.ts b/translations/spark-store_zh_CN.ts index 3e548d04..b9c5590d 100644 --- a/translations/spark-store_zh_CN.ts +++ b/translations/spark-store_zh_CN.ts @@ -10,8 +10,8 @@ - - + + Download 下载 @@ -63,10 +63,6 @@ <html><head/><body><p><img src=":/tags/uos-small.png"/></p></body></html> - - <html><head/><body><p>A deepin-wine2 app.If you are using ubuntu or other non-deepin distro,you should deploy deepin-wine2 by your self.</p></body></html> - <html><head/><body><p>这是一款 deepin-wine2 应用,如果你并没有在使用深度系列发行版(比如您在使用ubuntu),你需要自行配置 deepin-wine2 环境</p></body></html> - @@ -111,10 +107,6 @@ <html><head/><body><p><img src=":/tags/a2d-small.png"/></p></body></html> - - <html><head/><body><p>A deepin-wine5 app.If you are using ubuntu or other non-deepin distro,you should deploy deepin-wine5 by your self.</p></body></html> - <html><head/><body><p>这是一款deepin-wine5应用,如果你并没有在使用深度系列发行版(比如您在使用ubuntu),你需要自行配置deepin-wine5环境</p></body></html> - @@ -182,55 +174,47 @@ 软件官网 - + Click Open 点击跳转 - - - + + + Reinstall 重新安装 - + Upgrade 升级 - Downloading - 下载中 - - - Downloaded - 下载完成 - - - - - + + + Install 安装 - + Installing - 正在安装 + 正在安装 - - + + Spark Store 星火应用商店 - + Uninstall succeeded 卸载成功 - + The URL has been copied to the clipboard 链接已复制到剪贴板 @@ -248,6 +232,19 @@ + + DAboutDialog + + + Version: %1 + 版本:%1 + + + + %1 is released under %2 + %1遵循%2协议发布 + + DownloadItem @@ -291,83 +288,59 @@ 详情 - Spark Store App Installer - 星火内置安装器 - - - deepin deb installer - 深度软件包安装器 - - - gdebi - gdebi - - - Downloaded, waiting to install - 已完成,等待安装 - - - Download Failed,Check Your Connection - 下载失败,请检查网络连接 - - - Downloaded. Open APP Upgrade and Install Settings to enable password-free installation - 打开 APP 升级和安装设置以启用无密码安装 - - - + Download Complete. 下载完成. - - - + + + Spark Store 星火应用商店 - + Installing 正在安装 - + Installation complete. 安装完成. - + Finish 完成 - + Retry 重试 - + Error happened in dpkg progress , you can try it again. 安装被中止,可重新安装。 - + Error happened in dpkg progress , you can try it again dpkg出现错误,可重新安装 - + dpkg progress had been aborted,you can retry installation. dpkg进程被中断,您可重试安装。 - + dpkg progress had been aborted,you can retry installation 安装被中止,可重新安装 - + Download canceled 下载已取消 @@ -389,14 +362,6 @@ Open download directory 打开下载文件夹 - - Spark Store - 星火应用商店 - - - The download is complete. Please click the download button on the title Bar to open the download list for installation - 下载已完成,请点击标题栏上的下载按钮打开下载列表进行安装 - MainWindow @@ -406,155 +371,125 @@ - + Home 主页 - + Network 网络 - + Chat 社交 - + Music 音乐 - + Video 视频 - + Picture 图像 - + Game 游戏 - + Office 办公 - + Reading 阅读 - + Development 开发 - + Tool 工具 - + Theme 主题 - + Other 其他 - + APP Upgrade 更新 - + Submit App 投递应用 - + Submit App with client(Recommanded) 使用本地投稿器投递应用(推荐) - + Settings 设置 - + APP Upgrade and Install Settings 应用更新和安装设置 - + Spark Store 星火应用商店 - + Search or enter spk:// 搜索或打开链接 - - QLabel - - - - Spark Store - Spark 应用商店 - - QObject - - We publish this program under GPL V3 - 本程序按GPL V3开源 - - - - <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> - - - - Version 2.0+2 - 版本: 2.0+2 + + + + Spark Store + 星火应用商店 - <span style=' font-size:10pt;font-weight:60;'>An appstore powered by deepin 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;'>deepin 社区驱动的一款第三方应用商店</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> + <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> - - The Spark Project + + Spark Project 星火计划 - - <span style=' font-size:10pt;font-weight:60;'>An appstore powered by deepin 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><br/>We publish this program under GPL V3 - <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><br/>本程序遵循 GPL V3 协议发布 - - - - <span style='font-size:10pt;font-weight:60;'>An appstore powered by deepin 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><br/><br/>Published under GPL V3 - <span style='font-size:10pt;font-weight:60;'>由 Deepin 社区出品的应用商店</span><br/><a href='https://www.spark-app.store/'>https://www.spark-app.store</a><br/><span style='font-size:12pt;'>星火商店开发组</span><br/><br/>遵循 GPL V3 协议发布 - - - - - Spark Store - 星火应用商店 - SettingsPage @@ -644,539 +579,19 @@ <html><head/><body><p>我们并<span style=" font-weight:600;">不是</span>官方团队,和你一样,我们也只是众多Linux/deepin系统爱好者和用户之中的一员,我们开发并且运营这个“Spark应用商店”,是为了让社区的朋友们一起分享好用的软件,或者一起参与开发,让大家都用到最新的,最优秀的软件。</p><p>我们并没有因此盈利,所有开发和维护人员都不会获得报酬,我们的主要支出大部分依赖于社区对我们的捐助,很感谢大家,这部分捐助让我们并不需要耗费太多精力去担心资金问题。</p><p>我们的服务和开发的软件都是免费供给大家使用,交流,学习的,但是在您的使用过程中一定要遵守当地的法律法规,否则出现任何问题和我们无关。</p><p>如果商店中任何一部分有侵犯您权益的行为,请告知我们 &lt;jifengshenmo@outlook.com&gt; ,我们会第一时间删除侵权内容。</p><p>如果你也想参与我们,不管是参与开发,设计,投递还是投稿作品,我们都欢迎你的加入。</p><p>在 Spark IM 联系我们:<a href="https://chat.shenmo.tech"><span style=" text-decoration: underline; color:#0000ff;">https://chat.shenmo.tech<br/></span></a>QQ 群:872690351</p></body></html> - <html><head/><body><p>We are <span style=" font-weight:600;">NOT</span> the official team, just like you, we are just one of the many Linux/deepin system enthusiasts and users, we develop and run the &quot;Spark Store&quot;! &quot;, is to bring the community together to share useful software, or to participate in development together, so that we all use the latest and greatest software. </p><p>We don't make a profit from this, all developers and maintainers don't get paid, and we rely on the community's donations to us for most of our expenses, which we are grateful for and which allow us not to spend too much energy worrying about funding. </p><p>Our service and software are free for everyone to use, communicate, and learn, but you must comply with local laws and regulations in the process of your use, otherwise any problems have nothing to do with us. </p><p>If any part of the store infringes your rights, please tell us &lt;jifengshenmo@outlook.com&gt; we will remove the infringing content as soon as possible. </p><p>If you'd like to get involved with us too, whether you're involved in development, design, pitching or submitting work, we welcome you to join us. </p><p>Connect us on Spark IM: https://chat.shenmo.tech<br/></p></body></html> - &lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;我们并&lt;span style=&quot; font-weight:600;&quot;&gt;不是&lt;/span&gt;官方团队,和你一样,我们也只是众多Linux/deepin系统爱好者和用户之中的一员,我们开发并且运营这个“Spark应用商店”,是为了让社区的朋友们一起分享好用的软件,或者一起参与开发,让大家都用到最新的,最优秀的软件。&lt;/p&gt;&lt;p&gt;我们并没有因此盈利,所有开发和维护人员都不会获得报酬,我们的主要支出大部分依赖于社区对我们的捐助,很感谢大家,这部分捐助让我们并不需要耗费太多精力去担心资金问题。&lt;/p&gt;&lt;p&gt;我们的服务和开发的软件都是免费供给大家使用,交流,学习的,但是在您的使用过程中一定要遵守当地的法律法规,否则出现任何问题和我们无关。&lt;/p&gt;&lt;p&gt;如果商店中任何一部分有侵犯您权益的行为,请告知我们 &amp;lt;jifengshenmo@outlook.com&amp;gt;,我们会第一时间删除侵权内容。&lt;/p&gt;&lt;p&gt;如果你也想参与我们,不管是参与开发,设计,投递还是投稿作品,我们都欢迎你的加入。&lt;/p&gt;&lt;p&gt;在 Spark IM 联系我们: https://chat.shenmo.tech&lt;br/&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt; - - - + Updating, please wait... 正在更新,请稍候…… - + Spark Store 星火应用商店 - + Temporary cache was cleaned 缓存目录已清空 - - SpkAppInfoLoaderThread - - Failed to download app info. Please check internet connection. - 下载应用程序详细信息失败,请检查网络连接。 - - - PkgName: - 包名: - - - Version: - 版本: - - - Author: - 作者: - - - Official Site: - 官网: - - - Contributor: - 投稿者: - - - Update Time: - 更新时间: - - - Installed Size: - 大小: - - - Failed to load application icon. - 加载应用程序图标失败。 - - - - Widget - - Videos - 视频播放 - - - Download List - 下载列表 - - - Tools - 系统工具 - - - Beautify - 主题美化 - - - Music - 音乐欣赏 - - - Coding - 编程开发 - - - Office - 办公学习 - - - Translate - 阅读翻译 - - - Others - 其他应用 - - - FrontPage - 商店首页 - - - Images - 图形图像 - - - Games - 游戏娱乐 - - - Chatting - 社交沟通 - - - Network - 网络应用 - - - The list is currently empty. Go and download some softwares! - 当前下载列表为空。去下载些软件吧! - - - Open download directory - 打开下载文件夹 - - - Name - 软件名 - - - Install - 安装 - - - Video - 视频播放 - - - Download - 下载列表 - - - Reading - 阅读翻译 - - - Chat - 社交沟通 - - - Uninstall - 卸载 - - - Site - 官网 - - - <html><head/><body><p>This app is developed by community user,we give this tag to honor those who contribute to the Linux Ecology</p></body></html> - <html><head/><body><p>这款应用是社区开发者开发的,我们为社区开发者颁发这款勋章以表彰他们对Linux生态的贡献</p></body></html> - - - <html><head/><body><p>Capable to Ubuntu 20.04</p></body></html> - <html><head/><body><p>支持Ubuntu 20.04</p></body></html> - - - <html><head/><body><p>Capable to deepin 20</p></body></html> - <html><head/><body><p>支持deepin 20</p></body></html> - - - <html><head/><body><p>Capable to UOS home 20</p></body></html> - <html><head/><body><p>支持UOS家庭版 20</p></body></html> - - - <html><head/><body><p>This is a DTK5 app,which means it would have better effect on Deepin Desktop Environment</p></body></html> - <html><head/><body><p>这是一款DTK5应用,请使用深度桌面环境来获得最完美的体验</p></body></html> - - - <html><head/><body><p>A deepin-wine5 app.If you are using ubuntu or other non-deepin distro,you should deploy deepin-wine5 by your self.</p></body></html> - <html><head/><body><p>这是一款deepin-wine5应用,如果你并没有在使用深度系列发行版(比如您在使用ubuntu),你需要自行配置deepin-wine5环境</p></body></html> - - - <html><head/><body><p>An Appimage to deb app.</p></body></html> - <html><head/><body><p>这是一款Appimage转制应用.</p></body></html> - - - Share - Spk分享链接 - - - Development - 编程开发 - - - Home - 商店首页 - - - Graphics - 图形图像 - - - Communication - 社交沟通 - - - <html><head/><body><p>A deepin-wine2 app.If you are using ubuntu or other non-deepin distro,you should deploy deepin-wine2 by your self.</p></body></html> - <html><head/><body><p>这是一款 deepin-wine2 应用,如果你并没有在使用深度系列发行版(比如您在使用ubuntu),你需要自行配置 deepin-wine2 环境</p></body></html> - - - Contribute translation - 贡献翻译/应用反馈 - - - Info - 详细 - - - <html><head/><body><p>An app store developed by community enthusiasts</p></body></html> - <html><head/><body><p>由社区爱好者开发的一款应用商店</p></body></html> - - - Screenshots - 屏幕截图 - - - Line Settings - 线路设置 - - - Choose Line: - 线路选择: - - - Refresh - 刷新 - - - Take effect when restart - 重启商店后生效 - - - <html><head/><body><p>The role of the source server is to ensure that the software is updated, and supports the use of the apt tool to get the software. We usually prefer that you use the first line as the update source, which is generally the most stable. </p></body></html> - <html><head/><body><p>源服务器的作用是保证软件更新,并且支持使用apt工具获取软件。通常我们更建议你使用第一个线路作为更新源,一般是最稳定的。</p></body></html> - - - Update - 更新源 - - - Source Server - 更新源服务器 - - - Temp - 缓存目录 - - - Clean - 清空 - - - Since the dictionary is at /tmp,It would be cleaned automatically when system reboot. - 因为这个目录位于/tmp下,所以即使你不手动清空的话,其也将在系统重启时自动清空。 - - - Size: - 目录大小: - - - Location:/tmp/spark-store - 目录位置:/tmp/spark-store - - - About us - 关于我们 - - - <html><head/><body><p>We are <span style=" font-weight:600;">NOT</span> the official team, just like you, we are just one of the many Linux/deepin system enthusiasts and users, we develop and run the &quot;Spark Store&quot;! &quot;, is to bring the community together to share useful software, or to participate in development together, so that we all use the latest and greatest software. </p><p>We don't make a profit from this, all developers and maintainers don't get paid, and we rely on the community's donations to us for most of our expenses, which we are grateful for and which allow us not to spend too much energy worrying about funding. </p><p>Our service and software are free for everyone to use, communicate, and learn, but you must comply with local laws and regulations in the process of your use, otherwise any problems have nothing to do with us. </p><p>If any part of the store infringes your rights, please tell us &lt;jifengshenmo@outlook.com&gt; we will remove the infringing content as soon as possible. </p><p>If you'd like to get involved with us too, whether you're involved in development, design, pitching or submitting work, we welcome you to join us. </p><p>QQ group:872690351<br/></p></body></html> - <html><head/><body><p>我们并<span style=" font-weight:600;">不是</span>官方团队,和你一样,我们也只是众多Linux/deepin系统爱好者和用户之中的一员,我们开发并且运营这个“Spark应用商店”,是为了让社区的朋友们一起分享好用的软件,或者一起参与开发,让大家都用到最新的,最优秀的软件。</p><p>我们并没有因此盈利,所有开发和维护人员都不会获得报酬,我们的主要支出大部分依赖于社区对我们的捐助,很感谢大家,这部分捐助让我们并不需要耗费太多精力去担心资金问题。</p><p>我们的服务和开发的软件都是免费供给大家使用,交流,学习的,但是在您的使用过程中一定要遵守当地的法律法规,否则出现任何问题和我们无关。</p><p>如果商店中任何一部分有侵犯您权益的行为,请告知我们 &lt;jifengshenmo@outlook.com&gt;,我们会第一时间删除侵权内容。</p><p>如果你也想参与我们,不管是参与开发,设计,投递还是投稿作品,我们都欢迎你的加入。</p><p>QQ 群:872690351<br/></p></body></html> - - - Back to category - 返回分类 - - - Home - 商店首页 - - - Reload - 刷新 - - - Take effect when restart - 重启商店后生效 - - - Spark Store - Spark 应用商店 - - - Search or enter spk:// - 搜索或打开链接 - - - Submit App - 投递应用 - - - Settings - 设置 - - - Not Exist - 不存在 - - - Spark\ Store - 星火应用商店 - - - Failed to download app info. Please check internet connection. - 下载应用程序详细信息失败,请检查网络连接。 - - - PkgName: - 包名: - - - Version: - 版本: - - - Author: - 作者: - - - Official Site: - 官网: - - - Contributor: - 投稿者: - - - Update Time: - 更新时间: - - - Installed Size: - 大小: - - - Reinstall - 重新安装 - - - Failed to load application icon. - 加载应用程序图标失败。 - - - Failed to get the name to the file to be downloaded. - 获取安装包文件名失败。 - - - Relative apps Not Found! - 相关应用未找到! - - - Request Error: %1 - 请求错误:%1 - - - Spark store could only process spk:// links for now. The search feature is coming soon! - 目前仅支持商店专用链接的打开,搜索功能正在开发,请期待以后的版本! - - - Upgrade - 升级 - - - Updating, please wait... - 正在更新,请稍候…… - - - Apt has reported an error. Please use apt update in terminal to locate the problem. - 更新中发生错误,请在终端使用apt update来查看错误原因。 - - - Unknown error! - 未知错误! - - - Yes - - - - No - - - - Information for Contributors - 贡献者须知 - - - Currently the translation contribution is limited to English, -and you will be redirected to our Gitee repository at which you are -supposed to be creating pull requests to contribute app info -translations. -Tips:You can simply click the file to edit to create a flat pull request without create a full pull request -Tips:You can use github account to login to Gitee -Click yes to continue. - 目前商店仅支持应用程序英文详细信息的贡献。 -在你确认后你会被导向到我们的 Gitee 页面, -请在此创建 Pull Request 以进行翻译贡献。 -备注:你可以直接在页面编辑以快速创建轻量级pr -你也可以使用github账户直接登陆Gitee - -单击“是”以继续。 - - - Currently the translation contribution is limited to English, -and you will be redirected to our Gitee repository at which you are -supposed to be creating pull requests to contribute app info -translations. - -Click yes to continue. - 目前商店仅支持应用程序英文详细信息的贡献。 -在你确认后你会被导向到我们的 Gitee 页面, -请在此创建 Pull Request 以进行翻译贡献。 -备注:你可以直接在页面编辑以快速创建轻量级pr -你也可以使用github账户直接登陆Gitee - -单击“是”以继续。. - - - Unknown server error! - 服务器未知错误 - - - Uninstall succeeded - 卸载成功 - - - Temporary cache was cleaned - 缓存目录已清空 - - - The URL has been copied to the clipboard - 链接已复制到剪贴板 - - - - downloadlist - - Name - 软件名 - - - Waiting to download - 正在等待下载 - - - Install - 安装 - - - Cancel - 取消 - - - Info - 详情 - - - dpkg - dpkg - - - Spark Store App Installer - 星火内置安装器 - - - gdebi - gdebi - - - deepin deb installer - 深度软件包安装器 - - - Downloaded, waiting to install - 已完成,等待安装 - - - Failed to download %1 - 下载 %1 失败 - - - Download Failed,Check Your Connection - 下载失败,请检查网络连接 - - - Finished downloading %1, awaiting to install - %1 下载完成,等待安装 - - - Installing - 正在安装 - - - Installing... - 正在安装 - - - Finish - 完成 - - - Retry - 重试 - - - Error happened in dpkg progress , you can try it again - dpkg出现错误,可重新安装 - - - dpkg progress had been aborted,you can retry installation - 安装被中止,可重新安装 - - - Download canceled - 下载已取消 - - -- Gitee