From 77dde49653a2b200109ec207e32fd21adca9c318 Mon Sep 17 00:00:00 2001 From: momen Date: Sat, 2 Aug 2025 17:09:57 +0800 Subject: [PATCH 001/105] =?UTF-8?q?chore:=E6=9B=B4=E6=96=B0=E6=8C=89?= =?UTF-8?q?=E9=92=AE14=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/mainwindow-dtk.cpp | 96 +++++++++++++++++++++++++++++++++++++----- 1 file changed, 86 insertions(+), 10 deletions(-) diff --git a/src/mainwindow-dtk.cpp b/src/mainwindow-dtk.cpp index 45bc6e21..fb85dce7 100755 --- a/src/mainwindow-dtk.cpp +++ b/src/mainwindow-dtk.cpp @@ -531,8 +531,8 @@ void MainWindow::on_pushButton_14_clicked() if (false) { qDebug() << "UOS Developer Mode has not been enabled!"; - QtConcurrent::run([=] - { + (void)QtConcurrent::run([=] + { auto upgradeP = new QProcess(); upgradeP->startDetached("zenity", QStringList() << "--info" << "--text" @@ -544,20 +544,96 @@ void MainWindow::on_pushButton_14_clicked() ); upgradeP->waitForStarted(); upgradeP->waitForFinished(30); - upgradeP->deleteLater(); }); + upgradeP->deleteLater(); + }); + }else +{ + QFile upgradeStatus("/tmp/spark-store/upgradeStatus.txt"); + if (!upgradeStatus.exists()) + { + QString appPath; + // 判断路径:开发环境 vs 安装后 +#ifdef QT_DEBUG + appPath = QCoreApplication::applicationDirPath() + + "/spark-update-tool/spark-update-tool"; +#else + appPath = QStandardPaths::findExecutable("spark-update-tool"); +#endif + + if (appPath.isEmpty()) { + qWarning() << "spark-update-tool not found!"; + return; + } + + QProcess *process = new QProcess(this); + +#ifdef QT_DEBUG + // 开发模式:直接运行本地构建的更新器 + process->start(appPath, {"--silent"}); +#else + // 安装模式:使用 pkexec 提权运行系统路径下的 spark-update-tool + QString program = "pkexec"; + QStringList arguments; + arguments << appPath << "--silent"; + process->start(program, arguments); +#endif + + QObject::connect(process, &QProcess::finished, + [process](int exitCode, QProcess::ExitStatus) { + if (exitCode == 0) { + qDebug() << "Update check successful"; + } else { + qWarning() << "Update check failed with exit code:" << exitCode; + } + process->deleteLater(); + }); } +} +// ...existing code... else { QFile upgradeStatus("/tmp/spark-store/upgradeStatus.txt"); if (!upgradeStatus.exists()) { - QtConcurrent::run([=] - { - auto upgradeP = new QProcess(); - upgradeP->startDetached("/opt/durapps/spark-store/bin/update-upgrade/ss-do-upgrade.sh", QStringList()); - upgradeP->waitForStarted(); - upgradeP->waitForFinished(-1); - upgradeP->deleteLater(); }); + QString appPath; + + // 判断路径:开发环境 vs 安装后 + #ifdef QT_DEBUG + appPath = QCoreApplication::applicationDirPath() + + "/spark-update-tool/spark-update-tool"; + #else + appPath = QStandardPaths::findExecutable("spark-update-tool"); + #endif + + if (appPath.isEmpty()) { + qWarning() << "spark-update-tool not found!"; + return; + } + + QProcess *process = new QProcess(this); + + #ifdef QT_DEBUG + // 开发模式:直接运行本地构建的更新器 + process->start(appPath, {"--silent"}); + #else + // 安装模式:使用 pkexec 提权运行系统路径下的 spark-update-tool + QString program = "pkexec"; + QStringList arguments; + arguments << appPath << "--silent"; + process->start(program, arguments); + #endif + + QObject::connect(process, QOverload::of(&QProcess::finished), + [process](int exitCode) { + if (exitCode == 0) { + qDebug() << "Update check successful"; + } else { + qWarning() << "Update check failed with exit code:" << exitCode; + } + process->deleteLater(); + }); + } + } } } } -- Gitee From 2b62cc76771af8bf6ab50f5823026dc9aa378bbf Mon Sep 17 00:00:00 2001 From: momen Date: Sun, 3 Aug 2025 19:53:30 +0800 Subject: [PATCH 002/105] =?UTF-8?q?chore:=E6=9B=B4=E6=96=B0=E6=8C=89?= =?UTF-8?q?=E9=92=AE=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/mainwindow-dtk.cpp | 113 ----------------------------------------- 1 file changed, 113 deletions(-) diff --git a/src/mainwindow-dtk.cpp b/src/mainwindow-dtk.cpp index fb85dce7..98e33d67 100755 --- a/src/mainwindow-dtk.cpp +++ b/src/mainwindow-dtk.cpp @@ -522,118 +522,5 @@ void MainWindow::notify(QObject *receiver, QEvent *event) void MainWindow::on_pushButton_14_clicked() { - /** - * NOTE: No need to judget developmode status - */ - // Check UOS - // QSettings config(QStandardPaths::writableLocation(QStandardPaths::AppConfigLocation) + "/config.ini", QSettings::IniFormat); - // if (config.contains("UOS/EnableDeveloperMode") && !config.value("UOS/EnableDeveloperMode").toBool()) - if (false) - { - qDebug() << "UOS Developer Mode has not been enabled!"; - (void)QtConcurrent::run([=] - { - auto upgradeP = new QProcess(); - upgradeP->startDetached("zenity", QStringList() << "--info" - << "--text" - << "UOS开发者模式未开启,相关功能被禁用" - << "--title" - << "功能禁用提示" - << "--width" - << "360" - ); - upgradeP->waitForStarted(); - upgradeP->waitForFinished(30); - upgradeP->deleteLater(); - }); - }else -{ - QFile upgradeStatus("/tmp/spark-store/upgradeStatus.txt"); - if (!upgradeStatus.exists()) - { - QString appPath; - // 判断路径:开发环境 vs 安装后 -#ifdef QT_DEBUG - appPath = QCoreApplication::applicationDirPath() + - "/spark-update-tool/spark-update-tool"; -#else - appPath = QStandardPaths::findExecutable("spark-update-tool"); -#endif - - if (appPath.isEmpty()) { - qWarning() << "spark-update-tool not found!"; - return; - } - QProcess *process = new QProcess(this); - -#ifdef QT_DEBUG - // 开发模式:直接运行本地构建的更新器 - process->start(appPath, {"--silent"}); -#else - // 安装模式:使用 pkexec 提权运行系统路径下的 spark-update-tool - QString program = "pkexec"; - QStringList arguments; - arguments << appPath << "--silent"; - process->start(program, arguments); -#endif - - QObject::connect(process, &QProcess::finished, - [process](int exitCode, QProcess::ExitStatus) { - if (exitCode == 0) { - qDebug() << "Update check successful"; - } else { - qWarning() << "Update check failed with exit code:" << exitCode; - } - process->deleteLater(); - }); - } -} -// ...existing code... - else - { - QFile upgradeStatus("/tmp/spark-store/upgradeStatus.txt"); - if (!upgradeStatus.exists()) - { - QString appPath; - - // 判断路径:开发环境 vs 安装后 - #ifdef QT_DEBUG - appPath = QCoreApplication::applicationDirPath() + - "/spark-update-tool/spark-update-tool"; - #else - appPath = QStandardPaths::findExecutable("spark-update-tool"); - #endif - - if (appPath.isEmpty()) { - qWarning() << "spark-update-tool not found!"; - return; - } - - QProcess *process = new QProcess(this); - - #ifdef QT_DEBUG - // 开发模式:直接运行本地构建的更新器 - process->start(appPath, {"--silent"}); - #else - // 安装模式:使用 pkexec 提权运行系统路径下的 spark-update-tool - QString program = "pkexec"; - QStringList arguments; - arguments << appPath << "--silent"; - process->start(program, arguments); - #endif - - QObject::connect(process, QOverload::of(&QProcess::finished), - [process](int exitCode) { - if (exitCode == 0) { - qDebug() << "Update check successful"; - } else { - qWarning() << "Update check failed with exit code:" << exitCode; - } - process->deleteLater(); - }); - } - } - } - } } -- Gitee From 2367137dc5678aef1f4f476aee1777edb8498ca9 Mon Sep 17 00:00:00 2001 From: momen Date: Mon, 4 Aug 2025 11:38:42 +0800 Subject: [PATCH 003/105] =?UTF-8?q?chore:=E8=B0=83=E7=94=A8=E6=9B=B4?= =?UTF-8?q?=E6=96=B0=E5=99=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/mainwindow-dtk.cpp | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/src/mainwindow-dtk.cpp b/src/mainwindow-dtk.cpp index 98e33d67..f98348c3 100755 --- a/src/mainwindow-dtk.cpp +++ b/src/mainwindow-dtk.cpp @@ -14,6 +14,8 @@ #include #include #include +#include +#include #include #include @@ -522,5 +524,16 @@ void MainWindow::notify(QObject *receiver, QEvent *event) void MainWindow::on_pushButton_14_clicked() { - -} + QString appPath; + appPath = QCoreApplication::applicationDirPath() + "/spark-update-tool/spark-update-tool"; + if(appPath.isEmpty()) + { + qWarning() << "Spark Update Tool not found!"; + return; + } + QProcess *process = new QProcess(this); + QString program = "pkexec"; + QStringList arguments; + arguments << appPath << "--silent"; + process->start(program, arguments); +} \ No newline at end of file -- Gitee From f06d17c57a9d9be37dd0208df19c3bf1b4e193f8 Mon Sep 17 00:00:00 2001 From: momen Date: Tue, 5 Aug 2025 13:04:08 +0800 Subject: [PATCH 004/105] =?UTF-8?q?chore:=E6=9E=84=E5=BB=BA=E6=97=B6?= =?UTF-8?q?=E6=9E=84=E5=BB=BA=E6=9B=B4=E6=96=B0=E5=99=A8=E4=BB=A3=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index 6f049df8..69cbd7a5 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -41,3 +41,4 @@ include(GNUInstallDirs) add_subdirectory(src) add_subdirectory(translations) +add_subdirectory(spark-update-tool) \ No newline at end of file -- Gitee From 655d562bac462c919ce78332f5c20f0e86c7a417 Mon Sep 17 00:00:00 2001 From: momen Date: Tue, 5 Aug 2025 13:04:46 +0800 Subject: [PATCH 005/105] =?UTF-8?q?chore:=E6=9B=B4=E6=96=B0=E8=B0=83?= =?UTF-8?q?=E7=94=A8=E6=9B=B4=E6=96=B0=E5=99=A8=E7=9A=84=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/mainwindow-dtk.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/mainwindow-dtk.cpp b/src/mainwindow-dtk.cpp index f98348c3..0579f0bb 100755 --- a/src/mainwindow-dtk.cpp +++ b/src/mainwindow-dtk.cpp @@ -16,6 +16,7 @@ #include #include #include +#include #include #include @@ -525,7 +526,11 @@ void MainWindow::notify(QObject *receiver, QEvent *event) void MainWindow::on_pushButton_14_clicked() { QString appPath; - appPath = QCoreApplication::applicationDirPath() + "/spark-update-tool/spark-update-tool"; + appPath = QCoreApplication::applicationDirPath() ; + QDir dir(appPath); + dir.cdUp(); + appPath = dir.absolutePath(); + qDebug() << "Spark Update Tool Path: " << appPath; if(appPath.isEmpty()) { qWarning() << "Spark Update Tool not found!"; -- Gitee From 1dc50be61c78847d375a1dcb244e93a492834b1f Mon Sep 17 00:00:00 2001 From: momen Date: Tue, 5 Aug 2025 13:19:23 +0800 Subject: [PATCH 006/105] =?UTF-8?q?chore:=E6=9B=B4=E6=96=B0=E8=B0=83?= =?UTF-8?q?=E7=94=A8=E4=BB=A3=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/mainwindow-dtk.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/mainwindow-dtk.cpp b/src/mainwindow-dtk.cpp index 0579f0bb..7c0ae982 100755 --- a/src/mainwindow-dtk.cpp +++ b/src/mainwindow-dtk.cpp @@ -529,7 +529,7 @@ void MainWindow::on_pushButton_14_clicked() appPath = QCoreApplication::applicationDirPath() ; QDir dir(appPath); dir.cdUp(); - appPath = dir.absolutePath(); + appPath = dir.absolutePath()+"/spark-update-tool/spark-update-tool"; qDebug() << "Spark Update Tool Path: " << appPath; if(appPath.isEmpty()) { @@ -539,6 +539,6 @@ void MainWindow::on_pushButton_14_clicked() QProcess *process = new QProcess(this); QString program = "pkexec"; QStringList arguments; - arguments << appPath << "--silent"; + arguments << appPath <<"--silent"; process->start(program, arguments); } \ No newline at end of file -- Gitee From e60d2740d881a7c13dd33274d4e159d168f2464e Mon Sep 17 00:00:00 2001 From: momen Date: Tue, 5 Aug 2025 13:19:50 +0800 Subject: [PATCH 007/105] =?UTF-8?q?update:=E5=BC=80=E5=8F=91=E6=A8=A1?= =?UTF-8?q?=E5=BC=8F=E4=B8=8B=E7=9B=B4=E6=8E=A5=E8=B0=83=E7=94=A8=E6=9B=B4?= =?UTF-8?q?=E6=96=B0=E5=99=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/mainwindow-dtk.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/mainwindow-dtk.cpp b/src/mainwindow-dtk.cpp index 7c0ae982..77c9c191 100755 --- a/src/mainwindow-dtk.cpp +++ b/src/mainwindow-dtk.cpp @@ -537,8 +537,7 @@ void MainWindow::on_pushButton_14_clicked() return; } QProcess *process = new QProcess(this); - QString program = "pkexec"; QStringList arguments; arguments << appPath <<"--silent"; - process->start(program, arguments); + process->start(appPath, {"--silent"}); } \ No newline at end of file -- Gitee From a2018df6fabe108c59e8805778decf18c5ed6263 Mon Sep 17 00:00:00 2001 From: momen Date: Tue, 5 Aug 2025 13:20:48 +0800 Subject: [PATCH 008/105] =?UTF-8?q?update:=E5=85=B3=E9=97=AD.cache?= =?UTF-8?q?=E7=9B=AE=E5=BD=95=E5=90=8C=E6=AD=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 8437de6f..709ed4d9 100644 --- a/.gitignore +++ b/.gitignore @@ -63,3 +63,4 @@ debian/spark-store build obj-* .vscode +.cache \ No newline at end of file -- Gitee From 9a14b38d14895dd929c40d5a5d7deb3e187c9cc5 Mon Sep 17 00:00:00 2001 From: momen Date: Tue, 5 Aug 2025 13:59:00 +0800 Subject: [PATCH 009/105] =?UTF-8?q?chore:=E8=B0=83=E7=94=A8=E6=9B=B4?= =?UTF-8?q?=E6=96=B0=E6=97=B6=E5=88=86=E5=BC=80=E5=BC=80=E5=8F=91=E8=80=85?= =?UTF-8?q?=E5=92=8C=E6=99=AE=E9=80=9A=E7=94=A8=E6=88=B7=E7=9A=84=E8=B0=83?= =?UTF-8?q?=E7=94=A8=E6=96=B9=E5=BC=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/mainwindow-dtk.cpp | 38 ++++++++++++++++++++++++-------------- 1 file changed, 24 insertions(+), 14 deletions(-) diff --git a/src/mainwindow-dtk.cpp b/src/mainwindow-dtk.cpp index 77c9c191..9ad85ca4 100755 --- a/src/mainwindow-dtk.cpp +++ b/src/mainwindow-dtk.cpp @@ -526,18 +526,28 @@ void MainWindow::notify(QObject *receiver, QEvent *event) void MainWindow::on_pushButton_14_clicked() { QString appPath; - appPath = QCoreApplication::applicationDirPath() ; - QDir dir(appPath); - dir.cdUp(); - appPath = dir.absolutePath()+"/spark-update-tool/spark-update-tool"; - qDebug() << "Spark Update Tool Path: " << appPath; - if(appPath.isEmpty()) - { - qWarning() << "Spark Update Tool not found!"; - return; - } - QProcess *process = new QProcess(this); - QStringList arguments; - arguments << appPath <<"--silent"; - process->start(appPath, {"--silent"}); + #ifdef QT_DEBUG + appPath = QCoreApplication::applicationDirPath() ; + QDir dir(appPath); + dir.cdUp(); + appPath = dir.absolutePath()+"/spark-update-tool/spark-update-tool"; + qDebug() << "Spark Update Tool Path: " << appPath; + if(appPath.isEmpty()) + { + qWarning() << "Spark Update Tool not found!"; + return; + } + QProcess *process = new QProcess(this); + QStringList arguments; + arguments << appPath <<"--silent"; + process->start(appPath, {"--silent"}); + #else + appPath = QStandardPaths::findExecutable("spark-update-tool"); + QString program = "pkexec"; + QStringList arguments; + arguments << appPath << "--silent"; + process->start(program, arguments); + #endif + + } \ No newline at end of file -- Gitee From 411efd79bb47f10d32653f5ae58d7d6e8b572ac1 Mon Sep 17 00:00:00 2001 From: momen Date: Wed, 6 Aug 2025 22:50:48 +0800 Subject: [PATCH 010/105] =?UTF-8?q?update:=E5=88=A0=E9=99=A4pro=E6=96=87?= =?UTF-8?q?=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- spark-store-project.pro | 75 ----------------------------------------- 1 file changed, 75 deletions(-) delete mode 100644 spark-store-project.pro diff --git a/spark-store-project.pro b/spark-store-project.pro deleted file mode 100644 index c5022584..00000000 --- a/spark-store-project.pro +++ /dev/null @@ -1,75 +0,0 @@ -#------------------------------------------------- -# -# Project created by QtCreator 2022-01-12T04:00:00 -# -#------------------------------------------------- - -TARGET = spark-store -TEMPLATE = subdirs - -CONFIG += ordered - -SUBDIRS += \ - src/$${TARGET}.pro - -# https://wiki.debian.org/Hardening -QMAKE_CFLAGS *= $(shell dpkg-buildflags --get CFLAGS) -QMAKE_CPPFLAGS *= $(shell dpkg-buildflags --get CPPFLAGS) -QMAKE_CXXFLAGS *= $(shell dpkg-buildflags --get CXXFLAGS) -QMAKE_LFLAGS *= $(shell dpkg-buildflags --get LDFLAGS) - -# Update translation files -CONFIG(release, debug | release) { - system(bash $${PWD}/translate_update.sh) - system(bash $${PWD}/translate_generation.sh) -} - -# Rules for deployment -tool.files += tool/* -tool.path = /opt/durapps/$${TARGET}/bin/ - -qm.files += translations/*.qm -qm.path = /usr/share/$${TARGET}/translations/ - -#preferences.files += pkg/etc/apt/preferences.d/sparkstore -#preferences.path = /etc/apt/preferences.d/ - -#sourceslist.files += pkg/etc/apt/sources.list.d/sparkstore.list -#sourceslist.path = /etc/apt/sources.list.d/ - -bash_completion.files += pkg/usr/share/bash-completion/completions/aptss -bash_completion.path = /usr/share/bash-completion/completions/ - -desktop.files += pkg/usr/share/applications/*.desktop -desktop.path = /usr/share/applications/ - -service.files += pkg/usr/lib/systemd/system/spark-update-notifier.service -service.path = /lib/systemd/system/ - -polkit-1.files += pkg/usr/share/polkit-1/actions/* -polkit-1.path = /usr/share/polkit-1/actions/ - -icon.files += pkg/usr/share/icons -icon.path = /usr/share/ - -ssinstall-transhell.files += pkg/usr/share/ssinstall/transhell -ssinstall-transhell.path = /usr/share/ssinstall/ - -aptss-transhell.files += pkg/usr/share/aptss/transhell -aptss-transhell.path = /usr/share/aptss/ - -tmp.files += pkg/tmp/spark-store-install/feedback.sh -tmp.path = /tmp/spark-store-install/ - -INSTALLS += \ - tool \ - qm \ - desktop \ - icon \ - ssinstall-transhell \ - aptss-transhell \ -# sourceslist \ - tmp \ - service \ - bash_completion \ - polkit-1 -- Gitee From 00f296e971e9f736437a6dfb3e4e7e5b534240e0 Mon Sep 17 00:00:00 2001 From: momen Date: Wed, 6 Aug 2025 23:17:33 +0800 Subject: [PATCH 011/105] =?UTF-8?q?update:=E6=9E=84=E5=BB=BAdeb=E5=8C=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/CMakeLists.txt | 2 +- src/mainwindow-dtk.cpp | 1 + translations/spark-store_en.ts | 242 ++++++++++++++--------------- translations/spark-store_es.ts | 250 ++++++++++++++---------------- translations/spark-store_fr.ts | 250 ++++++++++++++---------------- translations/spark-store_zh_CN.ts | 250 ++++++++++++++---------------- translations/spark-store_zh_TW.ts | 250 ++++++++++++++---------------- 7 files changed, 588 insertions(+), 657 deletions(-) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index b5bc88e3..fcdce80d 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1,4 +1,4 @@ -find_package(Qt6 REQUIRED COMPONENTS Core Gui Widgets Concurrent Network Svg WebEngineWidgets) +find_package(Qt6 REQUIRED COMPONENTS Core Gui Widgets Concurrent Network Svg WebEngineWidgets Concurrent) find_package(Dtk6 REQUIRED COMPONENTS Core Gui Widget) include(src.cmake) diff --git a/src/mainwindow-dtk.cpp b/src/mainwindow-dtk.cpp index 9ad85ca4..0527eccf 100755 --- a/src/mainwindow-dtk.cpp +++ b/src/mainwindow-dtk.cpp @@ -546,6 +546,7 @@ void MainWindow::on_pushButton_14_clicked() QString program = "pkexec"; QStringList arguments; arguments << appPath << "--silent"; + QProcess *process = new QProcess(this); process->start(program, arguments); #endif diff --git a/translations/spark-store_en.ts b/translations/spark-store_en.ts index 9932a133..b093bf8e 100644 --- a/translations/spark-store_en.ts +++ b/translations/spark-store_en.ts @@ -24,164 +24,150 @@ - - - <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>Capable to UOS home 20</p></body></html> + + + <html><head/><body><p>Capable to deepin 23</p></body></html> - - - <html><head/><body><p>A deepin-wine2 app. Spark Store will automatically configure the wine kit for you.</p></body></html> + + + <html><head/><body><p>This app can only be installed natively</p></body></html> - - <html><head/><body><p><img src=":/tags/dwine2-small.png"/></p></body></html> + + + <html><head/><body><p>This app will be installed to debian12 ACE</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>This app will be installed to debian13 ACE</p></body></html> - - - <html><head/><body><p>Capable to deepin 20</p></body></html> + + + <html><head/><body><p>This app will be installed to debian SID ACE</p></body></html> - - - <html><head/><body><p>An Appimage to deb app.</p></body></html> + + + <html><head/><body><p>This app will be installed to deepin23 ACE</p></body></html> - - Share - Spk share link - - - - APP Feedback + + + <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> - - Introduction + + + <html><head/><body><p>Capable to UOS home 20</p></body></html> - - Description + + + <html><head/><body><p>A deepin-wine2 app. Spark Store will automatically configure the wine kit for you.</p></body></html> - - Screen capture + + + <html><head/><body><p>This is a DTK5 app,which means it would have better effect on Deepin Desktop Environment</p></body></html> - - - - - - Download and Install + + + <html><head/><body><p>An Appimage to deb app.</p></body></html> - - <html><head/><body><p><img src=":/tags/community.svg" height=30 width=30 /></p></body></html> - + + Share + Spk share link - - - <html><head/><body><p>Capable to Ubuntu 22.04</p></body></html> + + APP Feedback - - <html><head/><body><p><img src=":/tags/ubuntu.png" width=30 height=30 /></p></body></html> + + Introduction - - <html><head/><body><p><img src=":/tags/uos-authorize.svg" height=30 width=30 /></p></body></html> + + Description - - <html><head/><body><p><img src=":/tags/logo_icon.svg" height=30 width=30 /></p></body></html> + + Screen capture - - <html><head/><body><p><img src=":/tags/deepin.svg" height=30 width=30 /></p></body></html> + + + + + + Download and Install - - <html><head/><body><p><img src=":/tags/a2d.png"height=30 width=30 /></p></body></html> + + + <html><head/><body><p>Capable to Ubuntu 22.04</p></body></html> - - + + <html><head/><body><p>A Wine app.Spark Store will automatically configure the wine kit for you</p></body></html> - - <html><head/><body><p><img src=":/tags/dwine5.svg" height=30 width=30 /></p></body></html> - - - - + + <html><head/><body><p>Capable to Debian Stable</p></body></html> - - <html><head/><body><p><img src=":/tags/debian.svg" height="30" width="30"/></p></body></html> - - - - + Update - + Contributor - + Pkgname - + Author - + Size - + Website @@ -191,21 +177,21 @@ - + Developer Mode Disabled - - + + Reinstall - - + + Launch @@ -215,63 +201,63 @@ - - + + Install - + Installing - - - - - + + + + + Warning - + The current application does not support or tested on deepin, there may be problems - + The current application does not support or tested on UOS, there may be problems - + The current application does not support or tested on Ubuntu, there may be problems - + The current application does not support or tested on Debian, there may be problems - + The current application does not support or tested on current platform, there may be problems - - + + Spark Store - + Uninstall succeeded - + The URL has been copied to the clipboard @@ -292,12 +278,12 @@ DAboutDialog - + Version: %1 - + %1 is released under %2 @@ -359,9 +345,9 @@ - - + + Spark Store @@ -372,32 +358,32 @@ - + Installation complete. - - + + Finish - + Retry - - - + + + Error happened in dpkg progress , please check the install info or try to reinstall. - - - + + + dpkg progress had been aborted, please check the install info or try to reinstall. @@ -504,33 +490,33 @@ - + Submit App - + Submit App with client(Recommanded) - + Settings - + APP Upgrade and Install Settings - - + + Spark Store - + Search or enter spk:// @@ -538,19 +524,19 @@ QObject + - - + Spark Store - - <span style=' font-size:10pt;font-weight:60;'>An appstore powered by community</span><br/><a href='https://www.spark-app.store/'>https://www.spark-app.store</a><br/><span style=' font-size:12pt;'>Spark developers</span> + + <span style=' font-size:10pt;font-weight:60;'>An appstore powered by community</span><br/><span style=' font-size:10pt;font-weight:60;'>Sparky is our mascot, designed by <a href='https://tai3.cn/'>Tyson Tan</a></span><br/> - + Spark Project @@ -560,7 +546,7 @@ - + Show MainWindow @@ -681,12 +667,12 @@ TitleBarMenu - + About - + Exit diff --git a/translations/spark-store_es.ts b/translations/spark-store_es.ts index bc778822..f38a6f04 100644 --- a/translations/spark-store_es.ts +++ b/translations/spark-store_es.ts @@ -24,164 +24,150 @@ Número de descargas - - + + + <html><head/><body><p>Capable to deepin 23</p></body></html> + + + + + + <html><head/><body><p>This app can only be installed natively</p></body></html> + + + + + + <html><head/><body><p>This app will be installed to debian12 ACE</p></body></html> + + + + + + <html><head/><body><p>This app will be installed to debian13 ACE</p></body></html> + + + + + + <html><head/><body><p>This app will be installed to debian SID ACE</p></body></html> + + + + + + <html><head/><body><p>This app will be installed to deepin23 ACE</p></body></html> + + + + + <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>Esta aplicación fue desarrollada por usuarios de la comunidad y la Etiquetamos en honor a aquellos que contribuyeron a la ecología de linux.</p></body></html> - - + + <html><head/><body><p>Capable to UOS home 20</p></body></html> <html><head/><body><p>Capaz de UOS home 20</p></body></html> - - + + <html><head/><body><p>A deepin-wine2 app. Spark Store will automatically configure the wine kit for you.</p></body></html> <html><head/><body><p>A deepin-wine2 app. La tienda Spark le configurará automáticamente un traje de vino.</p></body></html> - - <html><head/><body><p><img src=":/tags/dwine2-small.png"/></p></body></html> - <html><head/><body><p><img src=":/tags/dwine2-small.png"/></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>Esta es una aplicación dtk5, lo que significa que funcionará mejor en un entorno de escritorio profundo.</p></body></html> - - - <html><head/><body><p>Capable to deepin 20</p></body></html> - <html><head/><body><p>Capaz de deepin 20</p></body></html> - - - - + + <html><head/><body><p>An Appimage to deb app.</p></body></html> <html><head/><body><p>Appimage de la aplicación deb.</p></body></html> - + Share Comunión - + APP Feedback Comentarios de la app - + Introduction Introducción - + Description Descripción - + Screen capture Captura de pantalla - - - + + + Download and Install Descargar e instalar - - <html><head/><body><p><img src=":/tags/community.svg" height=30 width=30 /></p></body></html> - - - - - + + <html><head/><body><p>Capable to Ubuntu 22.04</p></body></html> <html><head/><body><p>Capaz de Ubuntu 22.04</p></body></html> - - <html><head/><body><p><img src=":/tags/ubuntu.png" width=30 height=30 /></p></body></html> - - - - - <html><head/><body><p><img src=":/tags/uos-authorize.svg" height=30 width=30 /></p></body></html> - - - - - <html><head/><body><p><img src=":/tags/logo_icon.svg" height=30 width=30 /></p></body></html> - - - - - <html><head/><body><p><img src=":/tags/deepin.svg" height=30 width=30 /></p></body></html> - - - - - <html><head/><body><p><img src=":/tags/a2d.png"height=30 width=30 /></p></body></html> - - - - - + + <html><head/><body><p>A Wine app.Spark Store will automatically configure the wine kit for you</p></body></html> <html><head/><body><p>La aplicación wine. Spark Store configurará automáticamente el kit Wine para usted</p></body></html> - - <html><head/><body><p><img src=":/tags/dwine5.svg" height=30 width=30 /></p></body></html> - - - - + + <html><head/><body><p>Capable to Debian Stable</p></body></html> - - <html><head/><body><p><img src=":/tags/debian.svg" height="30" width="30"/></p></body></html> - - - - + Update Modernizar - + Contributor Contribuyentes - + Pkgname Nombre del embalaje - + Author Autor - + Size Tamaño - + Website Sitio web @@ -191,21 +177,21 @@ Haga clic en "abrir" - + Developer Mode Disabled Se ha desactivado el modo desarrollador - - + + Reinstall Reinstalación - - + + Launch @@ -215,63 +201,63 @@ Actualización - - + + Install Instalación - + Installing Se está instalando - - - - - + + + + + Warning Aviso - + The current application does not support or tested on deepin, there may be problems - + The current application does not support or tested on UOS, there may be problems - + The current application does not support or tested on Ubuntu, there may be problems - + The current application does not support or tested on Debian, there may be problems - + The current application does not support or tested on current platform, there may be problems - - + + Spark Store SPARK Store - + Uninstall succeeded Desinstalación exitosa - + The URL has been copied to the clipboard La URL ha sido copiada al portapapeles @@ -292,12 +278,12 @@ DAboutDialog - + Version: %1 Versión %1 - + %1 is released under %2 %1 publicado bajo %2 @@ -359,9 +345,9 @@ Descarga completada. - - + + Spark Store SPARK Store @@ -372,32 +358,32 @@ Se está instalando - + Installation complete. La instalación está completa. - - + + Finish Completado - + Retry Reinterpretar - - - + + + Error happened in dpkg progress , please check the install info or try to reinstall. Se produjo un error durante el proceso dpkg, verifique la información de instalación o intente reinstalar. - - - + + + dpkg progress had been aborted, please check the install info or try to reinstall. El proceso de DPKG ha sido interrumpido, compruebe la información de instalación o intente reinstalar. @@ -504,33 +490,33 @@ Actualización de app - + Submit App Presentación de la aplicación - + Submit App with client(Recommanded) Enviar la aplicación al cliente (recomendación) - + Settings Configuración - + APP Upgrade and Install Settings Actualización e instalación de app - - + + Spark Store SPARK Store - + Search or enter spk:// Buscar o introducir spk: /% @@ -538,19 +524,19 @@ QObject + - - + 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 community</span><br/><a href='https://www.spark-app.store/'>https://www.spark-app.store</a><br/><span style=' font-size:12pt;'>Spark developers</span> + + <span style=' font-size:10pt;font-weight:60;'>An appstore powered by community</span><br/><span style=' font-size:10pt;font-weight:60;'>Sparky is our mascot, designed by <a href='https://tai3.cn/'>Tyson Tan</a></span><br/> + - + Spark Project Proyecto spark @@ -560,7 +546,7 @@ Descargar lista - + Show MainWindow Mostrar la ventana principal @@ -681,12 +667,12 @@ TitleBarMenu - + About Sobre - + Exit Exportaciones diff --git a/translations/spark-store_fr.ts b/translations/spark-store_fr.ts index 1e624517..0a6823d6 100644 --- a/translations/spark-store_fr.ts +++ b/translations/spark-store_fr.ts @@ -24,164 +24,150 @@ Nombre de téléchargements - - + + + <html><head/><body><p>Capable to deepin 23</p></body></html> + + + + + + <html><head/><body><p>This app can only be installed natively</p></body></html> + + + + + + <html><head/><body><p>This app will be installed to debian12 ACE</p></body></html> + + + + + + <html><head/><body><p>This app will be installed to debian13 ACE</p></body></html> + + + + + + <html><head/><body><p>This app will be installed to debian SID ACE</p></body></html> + + + + + + <html><head/><body><p>This app will be installed to deepin23 ACE</p></body></html> + + + + + <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>Cette application a été développée par des utilisateurs de la communauté et nous avons donné ce label à ceux qui ont contribué à l'écologie de Linux</p></body></html> - - + + <html><head/><body><p>Capable to UOS home 20</p></body></html> <html><head/><body><p>Capable de la home UOS 20</p></body></html> - - + + <html><head/><body><p>A deepin-wine2 app. Spark Store will automatically configure the wine kit for you.</p></body></html> <html><head/><body><p>Une application deepin-wine2. Le Spark Store configure automatiquement votre pack de vins.</p></body></html> - - <html><head/><body><p><img src=":/tags/dwine2-small.png"/></p></body></html> - <html><head/><body><p><img src=":/tags/dwine2-small.png"/></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>C'est une application dtk5, ce qui signifie qu'elle fonctionnera mieux dans un environnement de bureau profond.</p></body></html> - - - <html><head/><body><p>Capable to deepin 20</p></body></html> - <html><head/><body><p>Capable de la deepin 20</p></body></html> - - - - + + <html><head/><body><p>An Appimage to deb app.</p></body></html> <html><head/><body><p>Appimage pour l'application DEB</p></body></html> - + Share Au total - + APP Feedback App feedback - + Introduction Présentation - + Description Description - + Screen capture Captures d'écran - - - + + + Download and Install Télécharger et installer - - <html><head/><body><p><img src=":/tags/community.svg" height=30 width=30 /></p></body></html> - - - - - + + <html><head/><body><p>Capable to Ubuntu 22.04</p></body></html> <html><head/><body><p>Capable de la Ubuntu 22.04</p></body></html> - - <html><head/><body><p><img src=":/tags/ubuntu.png" width=30 height=30 /></p></body></html> - - - - - <html><head/><body><p><img src=":/tags/uos-authorize.svg" height=30 width=30 /></p></body></html> - - - - - <html><head/><body><p><img src=":/tags/logo_icon.svg" height=30 width=30 /></p></body></html> - - - - - <html><head/><body><p><img src=":/tags/deepin.svg" height=30 width=30 /></p></body></html> - - - - - <html><head/><body><p><img src=":/tags/a2d.png"height=30 width=30 /></p></body></html> - - - - - + + <html><head/><body><p>A Wine app.Spark Store will automatically configure the wine kit for you</p></body></html> <html><head/><body><p>L'application wine. Spark Store configure automatiquement le kit Wine pour vous</p></body></html> - - <html><head/><body><p><img src=":/tags/dwine5.svg" height=30 width=30 /></p></body></html> - - - - + + <html><head/><body><p>Capable to Debian Stable</p></body></html> - - <html><head/><body><p><img src=":/tags/debian.svg" height="30" width="30"/></p></body></html> - - - - + Update Moderniser - + Contributor Contributeurs - + Pkgname Nom de l'emballage - + Author Auteur - + Size Taille - + Website Site Web @@ -191,21 +177,21 @@ Cliquez sur Ouvrir - + Developer Mode Disabled Mode développeur désactivé - - + + Reinstall Réinstaller - - + + Launch @@ -215,63 +201,63 @@ Mise à niveau - - + + Install Installation - + Installing Installation en cours - - - - - + + + + + Warning Avertissement - + The current application does not support or tested on deepin, there may be problems - + The current application does not support or tested on UOS, there may be problems - + The current application does not support or tested on Ubuntu, there may be problems - + The current application does not support or tested on Debian, there may be problems - + The current application does not support or tested on current platform, there may be problems - - + + Spark Store Le Spark store - + Uninstall succeeded Désinstallation réussie - + The URL has been copied to the clipboard L'URL a été copiée dans le presse - papiers @@ -292,12 +278,12 @@ DAboutDialog - + Version: %1 Version: %1 - + %1 is released under %2 %1 publié sous %2 @@ -359,9 +345,9 @@ Le téléchargement est terminé. - - + + Spark Store Le Spark store @@ -372,32 +358,32 @@ Installation en cours - + Installation complete. L'installation est terminée. - - + + Finish Terminé - + Retry Essayez à nouveau - - - + + + Error happened in dpkg progress , please check the install info or try to reinstall. Une erreur s'est produite dans le processus dpkg, vérifiez les informations d'installation ou essayez de réinstaller. - - - + + + dpkg progress had been aborted, please check the install info or try to reinstall. La progression de DPKG a été interrompue, veuillez vérifier les informations d’installation ou essayer de réinstaller. @@ -504,33 +490,33 @@ Mise à niveau app - + Submit App Soumettre une application - + Submit App with client(Recommanded) Soumettre une demande au client (recommandé) - + Settings Paramètres - + APP Upgrade and Install Settings Paramètres de mise à niveau et d'installation de l'app - - + + Spark Store Le Spark store - + Search or enter spk:// Rechercher ou entrer SPK / @@ -538,19 +524,19 @@ QObject + - - + Spark Store Le Spark store - - <span style=' font-size:10pt;font-weight:60;'>An appstore powered by community</span><br/><a href='https://www.spark-app.store/'>https://www.spark-app.store</a><br/><span style=' font-size:12pt;'>Spark developers</span> - <span style=' font-size:10pt;font-weight:60;'>An appstore powered by community</span><br/><a href='https://www.spark-app.store/'>https://www.spark-app.store</a><br/><span style=' font-size:12pt;'>Spark developers</span> + + <span style=' font-size:10pt;font-weight:60;'>An appstore powered by community</span><br/><span style=' font-size:10pt;font-weight:60;'>Sparky is our mascot, designed by <a href='https://tai3.cn/'>Tyson Tan</a></span><br/> + - + Spark Project Le projet Spark @@ -560,7 +546,7 @@ Télécharger la Liste - + Show MainWindow Afficher la fenêtre principale @@ -681,12 +667,12 @@ TitleBarMenu - + About À propos - + Exit Exportations diff --git a/translations/spark-store_zh_CN.ts b/translations/spark-store_zh_CN.ts index 3765f74e..6df066c1 100644 --- a/translations/spark-store_zh_CN.ts +++ b/translations/spark-store_zh_CN.ts @@ -24,164 +24,150 @@ 下载量 - - + + + <html><head/><body><p>Capable to deepin 23</p></body></html> + + + + + + <html><head/><body><p>This app can only be installed natively</p></body></html> + + + + + + <html><head/><body><p>This app will be installed to debian12 ACE</p></body></html> + + + + + + <html><head/><body><p>This app will be installed to debian13 ACE</p></body></html> + + + + + + <html><head/><body><p>This app will be installed to debian SID ACE</p></body></html> + + + + + + <html><head/><body><p>This app will be installed to deepin23 ACE</p></body></html> + + + + + <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 UOS home 20</p></body></html> <html><head/><body><p>支持UOS家庭版 20</p></body></html> - - + + <html><head/><body><p>A deepin-wine2 app. Spark Store will automatically configure the wine kit for you.</p></body></html> 这是一款 deepin-wine2 应用。星火商店会为你自动配置wine环境 - - <html><head/><body><p><img src=":/tags/dwine2-small.png"/></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>Capable to deepin 20</p></body></html> - <html><head/><body><p>支持deepin 20</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分享链接 - + APP Feedback 应用反馈 - + Description 描述 - + Screen capture 屏幕截图 - - - + + + Download and Install 下载并安装 - - <html><head/><body><p><img src=":/tags/community.svg" height=30 width=30 /></p></body></html> - - - - - + + <html><head/><body><p>Capable to Ubuntu 22.04</p></body></html> <html><head/><body><p>支持Ubuntu 22.04</p></body></html> - - <html><head/><body><p><img src=":/tags/ubuntu.png" width=30 height=30 /></p></body></html> - - - - - <html><head/><body><p><img src=":/tags/uos-authorize.svg" height=30 width=30 /></p></body></html> - - - - - <html><head/><body><p><img src=":/tags/logo_icon.svg" height=30 width=30 /></p></body></html> - - - - - <html><head/><body><p><img src=":/tags/deepin.svg" height=30 width=30 /></p></body></html> - - - - - <html><head/><body><p><img src=":/tags/a2d.png"height=30 width=30 /></p></body></html> - - - - - + + <html><head/><body><p>A Wine app.Spark Store will automatically configure the wine kit for you</p></body></html> 这是一款 Wine 应用。星火商店会为你自动配置wine环境 - - <html><head/><body><p><img src=":/tags/dwine5.svg" height=30 width=30 /></p></body></html> - - - - + + <html><head/><body><p>Capable to Debian Stable</p></body></html> <html><head/><body><p>支持Debian Stable</p></body></html> - - <html><head/><body><p><img src=":/tags/debian.svg" height="30" width="30"/></p></body></html> - - - - + Introduction 介绍 - + Update 更新时间 - + Contributor 投稿用户 - + Pkgname 软件包名 - + Author 软件作者 - + Size 软件大小 - + Website 软件官网 @@ -191,21 +177,21 @@ 点击跳转 - + Developer Mode Disabled 开发者模式未开启 - - + + Reinstall 重新安装 - - + + Launch 启动应用 @@ -215,63 +201,63 @@ 升级 - - + + Install 安装 - + Installing 正在安装 - - - - - + + + + + Warning 警告 - + The current application does not support or tested on deepin, there may be problems 当前应用不支持或未在deepin上测试过,安装后可能会出现问题 - + The current application does not support or tested on UOS, there may be problems 当前应用不支持或未在UOS上测试过,安装后可能会出现问题 - + The current application does not support or tested on Ubuntu, there may be problems 当前应用不支持或未在Ubuntu上测试过,安装后可能会出现问题 - + The current application does not support or tested on Debian, there may be problems 当前应用不支持或未在Debian上测试过,安装后可能会出现问题 - + The current application does not support or tested on current platform, there may be problems 当前应用不支持或未在您的平台上测试过,安装后可能会出现问题 - - + + Spark Store 星火应用商店 - + Uninstall succeeded 卸载成功 - + The URL has been copied to the clipboard 链接已复制到剪贴板 @@ -292,12 +278,12 @@ DAboutDialog - + Version: %1 版本:%1 - + %1 is released under %2 %1遵循%2协议发布 @@ -359,9 +345,9 @@ 下载完成. - - + + Spark Store 星火应用商店 @@ -372,32 +358,32 @@ 正在安装 - + Installation complete. 安装完成. - - + + Finish 完成 - + Retry 重试 - - - + + + Error happened in dpkg progress , please check the install info or try to reinstall. 安装出现错误,请检查安装详情或尝试重新安装。 - - - + + + dpkg progress had been aborted, please check the install info or try to reinstall. 安装被中止,请检查安装详情或尝试重新安装。 @@ -504,33 +490,33 @@ 更新 - + Submit App 投递应用 - + Submit App with client(Recommanded) 使用本地投稿器投递应用(推荐) - + Settings 设置 - + APP Upgrade and Install Settings 应用更新和安装设置 - - + + Spark Store 星火应用商店 - + Search or enter spk:// 搜索或打开链接 @@ -538,19 +524,19 @@ QObject + - - + Spark Store 星火应用商店 - - <span style=' font-size:10pt;font-weight:60;'>An appstore powered by community</span><br/><a href='https://www.spark-app.store/'>https://www.spark-app.store</a><br/><span style=' font-size:12pt;'>Spark developers</span> - <span style=' font-size:10pt;font-weight:60;'>一款由社区提供的应用商店</span><br/><a href='https://www.spark-app.store/'>https://www.spark-app.store</a><br/><span style=' font-size:12pt;'>星火计划开发者</span> + + <span style=' font-size:10pt;font-weight:60;'>An appstore powered by community</span><br/><span style=' font-size:10pt;font-weight:60;'>Sparky is our mascot, designed by <a href='https://tai3.cn/'>Tyson Tan</a></span><br/> + - + Spark Project 星火计划 @@ -560,7 +546,7 @@ 下载列表 - + Show MainWindow 显示主窗口 @@ -681,12 +667,12 @@ TitleBarMenu - + About 关于 - + Exit 退出 diff --git a/translations/spark-store_zh_TW.ts b/translations/spark-store_zh_TW.ts index ddc60482..f6cf9ade 100644 --- a/translations/spark-store_zh_TW.ts +++ b/translations/spark-store_zh_TW.ts @@ -24,164 +24,150 @@ 下載次數 - - + + + <html><head/><body><p>Capable to deepin 23</p></body></html> + + + + + + <html><head/><body><p>This app can only be installed natively</p></body></html> + + + + + + <html><head/><body><p>This app will be installed to debian12 ACE</p></body></html> + + + + + + <html><head/><body><p>This app will be installed to debian13 ACE</p></body></html> + + + + + + <html><head/><body><p>This app will be installed to debian SID ACE</p></body></html> + + + + + + <html><head/><body><p>This app will be installed to deepin23 ACE</p></body></html> + + + + + <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 UOS home 20</p></body></html> <html><head/><body><p>支持UOS家庭版 20</p></body></html> - - + + <html><head/><body><p>A deepin-wine2 app. Spark Store will automatically configure the wine kit for you.</p></body></html> 这是一款 deepin-wine2 应用。星火商店会为你自动配置wine环境 - - <html><head/><body><p><img src=":/tags/dwine2-small.png"/></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>Capable to deepin 20</p></body></html> - <html><head/><body><p>支持deepin 20</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共享链接 - + APP Feedback 軟件錯誤回報 - + Description 軟體詳細資料 - + Screen capture 軟體演示 - - - + + + Download and Install 下載並安裝 - - <html><head/><body><p><img src=":/tags/community.svg" height=30 width=30 /></p></body></html> - - - - - + + <html><head/><body><p>Capable to Ubuntu 22.04</p></body></html> <html><head/><body><p>支持Ubuntu 22.04</p></body></html> - - <html><head/><body><p><img src=":/tags/ubuntu.png" width=30 height=30 /></p></body></html> - - - - - <html><head/><body><p><img src=":/tags/uos-authorize.svg" height=30 width=30 /></p></body></html> - - - - - <html><head/><body><p><img src=":/tags/logo_icon.svg" height=30 width=30 /></p></body></html> - - - - - <html><head/><body><p><img src=":/tags/deepin.svg" height=30 width=30 /></p></body></html> - - - - - <html><head/><body><p><img src=":/tags/a2d.png"height=30 width=30 /></p></body></html> - - - - - + + <html><head/><body><p>A Wine app.Spark Store will automatically configure the wine kit for you</p></body></html> 这是一款 Wine 应用。星火商店会为你自动配置wine环境 - - <html><head/><body><p><img src=":/tags/dwine5.svg" height=30 width=30 /></p></body></html> - - - - + + <html><head/><body><p>Capable to Debian Stable</p></body></html> - - <html><head/><body><p><img src=":/tags/debian.svg" height="30" width="30"/></p></body></html> - - - - + Introduction 軟體介紹 - + Update 更新时间 - + Contributor 投稿用户 - + Pkgname 软件包名 - + Author 软件作者 - + Size 软件大小 - + Website 软件官网 @@ -191,21 +177,21 @@ 点击跳转 - + Developer Mode Disabled 开发者模式未开启 - - + + Reinstall 重新安裝 - - + + Launch @@ -215,63 +201,63 @@ 升级 - - + + Install 安装 - + Installing 正在安装 - - - - - + + + + + Warning - + The current application does not support or tested on deepin, there may be problems - + The current application does not support or tested on UOS, there may be problems - + The current application does not support or tested on Ubuntu, there may be problems - + The current application does not support or tested on Debian, there may be problems - + The current application does not support or tested on current platform, there may be problems - - + + Spark Store 星火应用商店 - + Uninstall succeeded 卸载成功 - + The URL has been copied to the clipboard 链接已复制到剪贴板 @@ -292,12 +278,12 @@ DAboutDialog - + Version: %1 版本:%1 - + %1 is released under %2 %1遵循%2协议发布 @@ -359,9 +345,9 @@ 下載完成. - - + + Spark Store 星火应用商店 @@ -372,32 +358,32 @@ 正在安裝 - + Installation complete. 安裝完成. - - + + Finish 完成 - + Retry 重试 - - - + + + Error happened in dpkg progress , please check the install info or try to reinstall. 安裝出現錯誤,請檢查安裝詳情或嘗試重新安裝。 - - - + + + dpkg progress had been aborted, please check the install info or try to reinstall. 安裝被中止,請檢查安裝詳情或嘗試重新安裝。 @@ -504,33 +490,33 @@ 軟體更新 - + Submit App 上傳軟體 - + Submit App with client(Recommanded) 從客戶端上傳軟體(推薦的) - + Settings 設定 - + APP Upgrade and Install Settings 軟體升級 和 安裝設定 - - + + Spark Store 星火应用商店 - + Search or enter spk:// 搜索或打开链接 @@ -538,19 +524,19 @@ QObject + - - + Spark Store 星火应用商店 - - <span style=' font-size:10pt;font-weight:60;'>An appstore powered by community</span><br/><a href='https://www.spark-app.store/'>https://www.spark-app.store</a><br/><span style=' font-size:12pt;'>Spark developers</span> - <span style=' font-size:10pt;font-weight:60;'>一款由社区提供的应用商店</span><br/><a href='https://www.spark-app.store/'>https://www.spark-app.store</a><br/><span style=' font-size:12pt;'>星火计划开发者</span> + + <span style=' font-size:10pt;font-weight:60;'>An appstore powered by community</span><br/><span style=' font-size:10pt;font-weight:60;'>Sparky is our mascot, designed by <a href='https://tai3.cn/'>Tyson Tan</a></span><br/> + - + Spark Project 星火计划 @@ -560,7 +546,7 @@ 下载列表 - + Show MainWindow 显示主窗口 @@ -681,12 +667,12 @@ TitleBarMenu - + About 关于 - + Exit 退出 -- Gitee From c54c83834fdb569e62a4ccaaa7beb981f8a7e7fd Mon Sep 17 00:00:00 2001 From: momen Date: Thu, 7 Aug 2025 15:27:52 +0800 Subject: [PATCH 012/105] =?UTF-8?q?update:=E6=9B=B4=E6=96=B0=E7=89=88?= =?UTF-8?q?=E6=9C=AC=E5=8F=B7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- debian/changelog | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/debian/changelog b/debian/changelog index 84b1509d..53324041 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,9 @@ +spark-store (4.8.1~test1) UNRELEASED; urgency=medium + + * 添加全新的更新器 + * 替换了新版更新器的polkit policy + -- momen Tue, 15 Jul 2025 01:03:08 +0800 + spark-store (4.8.0) UNRELEASED; urgency=medium * ssinstall重写,支持安装到ACE和自动安装到ACE,支持只允许安装到本地 -- Gitee From 8ea38112d2a9e1c612465fe08fcf73927ca0e41e Mon Sep 17 00:00:00 2001 From: momen Date: Fri, 8 Aug 2025 11:31:31 +0800 Subject: [PATCH 013/105] =?UTF-8?q?chore:=E8=A7=A3=E5=86=B3=E8=AF=A5?= =?UTF-8?q?=E6=96=87=E4=BB=B6=E6=9E=84=E5=BB=BAdeb=E6=8A=A5=E9=94=99?= =?UTF-8?q?=E7=9A=84=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/application.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/application.cpp b/src/application.cpp index 6b810e9f..9555bc49 100644 --- a/src/application.cpp +++ b/src/application.cpp @@ -163,7 +163,10 @@ void Application::loadTranslator() if (QLocale::system().language() == QLocale::Chinese) { QTranslator *webengineTranslator = new QTranslator(this); - webengineTranslator->load(QLocale(QLocale::Chinese), "qtwebengine", "_", ":/translations"); + bool loaded = webengineTranslator->load(QLocale(QLocale::Chinese), "qtwebengine", "_", ":/translations"); + if (!loaded) { + qWarning() << "Failed to load webengine translator"; + } installTranslator(webengineTranslator); } } -- Gitee From edfe2512b03c36c44b6c9351741c2223a1a1d393 Mon Sep 17 00:00:00 2001 From: momen Date: Fri, 8 Aug 2025 11:31:36 +0800 Subject: [PATCH 014/105] =?UTF-8?q?chore:=E8=A7=A3=E5=86=B3=E8=AF=A5?= =?UTF-8?q?=E6=96=87=E4=BB=B6=E6=9E=84=E5=BB=BAdeb=E6=8A=A5=E9=94=99?= =?UTF-8?q?=E7=9A=84=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/mainwindow-dtk.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mainwindow-dtk.cpp b/src/mainwindow-dtk.cpp index 0527eccf..a08c4490 100755 --- a/src/mainwindow-dtk.cpp +++ b/src/mainwindow-dtk.cpp @@ -437,7 +437,7 @@ void MainWindow::initTmpDir() if (info.isWritable() == false) { - QtConcurrent::run([=] + auto future = QtConcurrent::run([=] { sleep(3); auto upgradeP = new QProcess(); -- Gitee From 949f3f402d232b532a247a3ae5b6320290915711 Mon Sep 17 00:00:00 2001 From: momen Date: Fri, 8 Aug 2025 11:31:39 +0800 Subject: [PATCH 015/105] =?UTF-8?q?chore:=E8=A7=A3=E5=86=B3=E8=AF=A5?= =?UTF-8?q?=E6=96=87=E4=BB=B6=E6=9E=84=E5=BB=BAdeb=E6=8A=A5=E9=94=99?= =?UTF-8?q?=E7=9A=84=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/backend/downloadworker.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/backend/downloadworker.cpp b/src/backend/downloadworker.cpp index d7e5f5af..720f35b7 100644 --- a/src/backend/downloadworker.cpp +++ b/src/backend/downloadworker.cpp @@ -41,7 +41,7 @@ bool checkMeatlink(QString metaUrl) metaStatus.remove(); } QString cmd = QString("curl -I -s --connect-timeout 5 %1 -w %{http_code} |tail -n1 > /tmp/spark-store/metaStatus.txt").arg(metaUrl); - system(cmd.toUtf8().data()); + [[maybe_unused]] int ret = system(cmd.toUtf8().data());//不这样写就会-Wunused-variable 警告导致无法打包 if (metaStatus.open(QFile::ReadOnly) && QString(metaStatus.readAll()).toUtf8() == "200") { metaStatus.remove(); @@ -94,7 +94,7 @@ void DownloadController::startDownload(const QString &url) return; } - QtConcurrent::run([=]() + auto future = QtConcurrent::run([=]() { QString metaUrl = url + ".metalink"; qDebug() << "metalink" << metaUrl; @@ -272,7 +272,7 @@ void DownloadController::stopDownload() // 实现下载进程退出 QString killCmd = QString("kill -9 %1").arg(pidNumber); - system(killCmd.toUtf8()); + [[maybe_unused]] int ret = system(killCmd.toUtf8()); qDebug() << "kill aria2!"; pidNumber = -1; } -- Gitee From 02d63a349e83b0fb27131b6d1c1db9c59255ab8c Mon Sep 17 00:00:00 2001 From: momen Date: Fri, 8 Aug 2025 11:31:43 +0800 Subject: [PATCH 016/105] =?UTF-8?q?chore:=E8=A7=A3=E5=86=B3=E8=AF=A5?= =?UTF-8?q?=E6=96=87=E4=BB=B6=E6=9E=84=E5=BB=BAdeb=E6=8A=A5=E9=94=99?= =?UTF-8?q?=E7=9A=84=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/pages/appintopage.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pages/appintopage.cpp b/src/pages/appintopage.cpp index 95f2dcb9..37a5a3ae 100644 --- a/src/pages/appintopage.cpp +++ b/src/pages/appintopage.cpp @@ -616,7 +616,7 @@ void AppIntoPage::on_downloadButton_clicked() void AppIntoPage::on_pushButton_3_clicked() { - QtConcurrent::run([=]() + auto future = QtConcurrent::run([=]() { ui->downloadButton->setEnabled(false); ui->pushButton_3->setEnabled(false); -- Gitee From d60390e83cb23240d656e4294f22870c49a9bbee Mon Sep 17 00:00:00 2001 From: momen Date: Fri, 8 Aug 2025 11:31:46 +0800 Subject: [PATCH 017/105] =?UTF-8?q?chore:=E8=A7=A3=E5=86=B3=E8=AF=A5?= =?UTF-8?q?=E6=96=87=E4=BB=B6=E6=9E=84=E5=BB=BAdeb=E6=8A=A5=E9=94=99?= =?UTF-8?q?=E7=9A=84=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/pages/settingspage.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/pages/settingspage.cpp b/src/pages/settingspage.cpp index 8d1f42c5..c380ea6c 100644 --- a/src/pages/settingspage.cpp +++ b/src/pages/settingspage.cpp @@ -109,7 +109,7 @@ SettingsPage::~SettingsPage() void SettingsPage::on_pushButton_updateServer_clicked() { - QtConcurrent::run([=]() + auto future = QtConcurrent::run([=]() { ui->pushButton_updateServer->setEnabled(false); @@ -208,7 +208,7 @@ quint64 SettingsPage::dirFileSize(const QString &path) void SettingsPage::on_pushButton_updateApt_clicked() { - QtConcurrent::run([=]() + auto future = QtConcurrent::run([=]() { ui->pushButton_updateApt->setEnabled(false); ui->label_aptserver->setText(tr("Updating, please wait...")); @@ -222,7 +222,7 @@ void SettingsPage::on_pushButton_updateApt_clicked() void SettingsPage::on_pushButton_clear_clicked() { - QtConcurrent::run([=]() + auto future = QtConcurrent::run([=]() { ui->pushButton_clear->setEnabled(false); @@ -240,7 +240,7 @@ void SettingsPage::on_pushButton_clear_clicked() void SettingsPage::on_pushButton_clearWebCache_clicked() { - QtConcurrent::run([=]() + auto future = QtConcurrent::run([=]() { QString localDataLocation = QStandardPaths::writableLocation(QStandardPaths::AppLocalDataLocation) + "/QtWebEngine"; qDebug() << localDataLocation; -- Gitee From 1797fccc2c0ebfa28fd4a39c774afc648c05cdfb Mon Sep 17 00:00:00 2001 From: momen Date: Fri, 8 Aug 2025 11:31:48 +0800 Subject: [PATCH 018/105] =?UTF-8?q?chore:=E8=A7=A3=E5=86=B3=E8=AF=A5?= =?UTF-8?q?=E6=96=87=E4=BB=B6=E6=9E=84=E5=BB=BAdeb=E6=8A=A5=E9=94=99?= =?UTF-8?q?=E7=9A=84=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/widgets/downloadlistwidget.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/widgets/downloadlistwidget.cpp b/src/widgets/downloadlistwidget.cpp index 413477a6..b4b19fc3 100644 --- a/src/widgets/downloadlistwidget.cpp +++ b/src/widgets/downloadlistwidget.cpp @@ -168,7 +168,7 @@ void DownloadListWidget::httpFinished() // 完成下载 isdownload = false; isBusy = false; - QtConcurrent::run([=]() + auto future = QtConcurrent::run([=]() { while (downloaditemlist[nowDownload - 1]->readyInstall() == -1) // 安装当前应用,堵塞安装,后面的下载suspend { -- Gitee From 76a5d7313b1426f034410d3c7229b376688e954f Mon Sep 17 00:00:00 2001 From: momen Date: Fri, 8 Aug 2025 11:31:51 +0800 Subject: [PATCH 019/105] =?UTF-8?q?chore:=E8=A7=A3=E5=86=B3=E8=AF=A5?= =?UTF-8?q?=E6=96=87=E4=BB=B6=E6=9E=84=E5=BB=BAdeb=E6=8A=A5=E9=94=99?= =?UTF-8?q?=E7=9A=84=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/widgets/common/downloaditem.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/widgets/common/downloaditem.cpp b/src/widgets/common/downloaditem.cpp index e4aad7ab..3a25ab8f 100644 --- a/src/widgets/common/downloaditem.cpp +++ b/src/widgets/common/downloaditem.cpp @@ -125,7 +125,7 @@ void DownloadItem::install(int t) ui->label_2->setText(tr("Installing")); ui->label_2->setToolTip(tr("Installing")); - QtConcurrent::run([=]() + auto future = QtConcurrent::run([=]() { slotAsyncInstall(t); }); -- Gitee From ebe9187ca851d4ea014a7ea2572fb991880ca761 Mon Sep 17 00:00:00 2001 From: momen Date: Fri, 8 Aug 2025 11:41:13 +0800 Subject: [PATCH 020/105] =?UTF-8?q?chore:=E5=BC=95=E5=85=A5=E5=A4=B4?= =?UTF-8?q?=E6=96=87=E4=BB=B6QScreen?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- spark-update-tool/src/mainwindow.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spark-update-tool/src/mainwindow.h b/spark-update-tool/src/mainwindow.h index bc7f9d72..d754b5f7 100644 --- a/spark-update-tool/src/mainwindow.h +++ b/spark-update-tool/src/mainwindow.h @@ -7,7 +7,7 @@ #include "appdelegate.h" #include #include // 添加头文件 - +#include QT_BEGIN_NAMESPACE namespace Ui { class MainWindow; -- Gitee From 85ca5dfb86253d0f7db5869d7c922b54b4b310c2 Mon Sep 17 00:00:00 2001 From: momen Date: Fri, 8 Aug 2025 12:46:00 +0800 Subject: [PATCH 021/105] =?UTF-8?q?update:=E9=87=8D=E5=86=99=E8=8E=B7?= =?UTF-8?q?=E5=8F=96=E6=9E=84=E5=BB=BA=E6=97=B6=E9=97=B4=E6=96=B9=E6=B3=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/CMakeLists.txt | 6 ++++++ src/main.cpp | 12 +++++++----- 2 files changed, 13 insertions(+), 5 deletions(-) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index fcdce80d..203b654d 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1,6 +1,12 @@ find_package(Qt6 REQUIRED COMPONENTS Core Gui Widgets Concurrent Network Svg WebEngineWidgets Concurrent) find_package(Dtk6 REQUIRED COMPONENTS Core Gui Widget) +# 添加构建时间宏 +string(TIMESTAMP BUILD_DATE "%Y.%m.%d" UTC) +string(TIMESTAMP BUILD_TIME "%H:%M:%S" UTC) +add_definitions(-DBUILD_DATE="${BUILD_DATE}") +add_definitions(-DBUILD_TIME="${BUILD_TIME}") + include(src.cmake) add_executable(${PROJECT_NAME} ${HEADERS} ${SOURCES} ${QRC_FILE}) diff --git a/src/main.cpp b/src/main.cpp index 84bce65d..2e155e8a 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -110,11 +110,13 @@ int main(int argc, char *argv[]) signal(SIGSEGV, crashHandler); // 注册SIGSEGV处理函数 - // Get build time - static const QDate buildDate = QLocale(QLocale::English).toDate(QString(__DATE__).replace(" ", " 0"), "MMM dd yyyy"); - static const QTime buildTime = QTime::fromString(__TIME__, "hh:mm:ss"); - buildDateTime = buildDate.toString("yyyy.MM.dd") + "-" + buildTime.toString("hh:mm:ss"); - + // // Get build time + // static const QDate buildDate = QLocale(QLocale::English).toDate(QString(__DATE__).replace(" ", " 0"), "MMM dd yyyy"); + // static const QTime buildTime = QTime::fromString(__TIME__, "hh:mm:ss"); + // buildDateTime = buildDate.toString("yyyy.MM.dd") + "-" + buildTime.toString("hh:mm:ss"); + + //在cmakelist.txt中设置 buildDateTime + QString buildDateTime = QString("%1-%2").arg(QString(BUILD_DATE)).arg(QString(BUILD_TIME)); // NOTE: 提前设置组织名称和应用名称,避免配置文件位置错误 DApplication::setOrganizationName("spark-union"); -- Gitee From 52e6888b9d7b8ede77e2f655329d35bee8d86d95 Mon Sep 17 00:00:00 2001 From: momen Date: Sat, 9 Aug 2025 16:45:26 +0800 Subject: [PATCH 022/105] =?UTF-8?q?chore:=E5=AE=89=E8=A3=85=E9=98=B6?= =?UTF-8?q?=E6=AE=B5=E5=85=8D=E5=AF=86=E8=BF=90=E8=A1=8C=E6=9B=B4=E6=96=B0?= =?UTF-8?q?=E7=A8=8B=E5=BA=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/mainwindow-dtk.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mainwindow-dtk.cpp b/src/mainwindow-dtk.cpp index a08c4490..e0a22267 100755 --- a/src/mainwindow-dtk.cpp +++ b/src/mainwindow-dtk.cpp @@ -545,7 +545,7 @@ void MainWindow::on_pushButton_14_clicked() appPath = QStandardPaths::findExecutable("spark-update-tool"); QString program = "pkexec"; QStringList arguments; - arguments << appPath << "--silent"; + arguments << appPath; QProcess *process = new QProcess(this); process->start(program, arguments); #endif -- Gitee From 3e6cb43b2a6c7b40c69774c86571bc084a4f16d2 Mon Sep 17 00:00:00 2001 From: momen Date: Sun, 10 Aug 2025 16:55:32 +0800 Subject: [PATCH 023/105] =?UTF-8?q?chore:=E7=9B=B4=E6=8E=A5=E8=B0=83?= =?UTF-8?q?=E7=94=A8=E6=9B=B4=E6=96=B0=E5=99=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/mainwindow-dtk.cpp | 41 +++++++++++++++++++++++------------------ 1 file changed, 23 insertions(+), 18 deletions(-) diff --git a/src/mainwindow-dtk.cpp b/src/mainwindow-dtk.cpp index e0a22267..c2a90636 100755 --- a/src/mainwindow-dtk.cpp +++ b/src/mainwindow-dtk.cpp @@ -526,29 +526,34 @@ void MainWindow::notify(QObject *receiver, QEvent *event) void MainWindow::on_pushButton_14_clicked() { QString appPath; - #ifdef QT_DEBUG - appPath = QCoreApplication::applicationDirPath() ; - QDir dir(appPath); - dir.cdUp(); - appPath = dir.absolutePath()+"/spark-update-tool/spark-update-tool"; - qDebug() << "Spark Update Tool Path: " << appPath; - if(appPath.isEmpty()) - { - qWarning() << "Spark Update Tool not found!"; - return; - } - QProcess *process = new QProcess(this); - QStringList arguments; - arguments << appPath <<"--silent"; - process->start(appPath, {"--silent"}); - #else + // #ifdef QT_DEBUG + // appPath = QCoreApplication::applicationDirPath() ; + // QDir dir(appPath); + // dir.cdUp(); + // appPath = dir.absolutePath()+"/spark-update-tool/spark-update-tool"; + // qDebug() << "Spark Update Tool Path: " << appPath; + // if(appPath.isEmpty()) + // { + // qWarning() << "Spark Update Tool not found!"; + // return; + // } + // QProcess *process = new QProcess(this); + // QStringList arguments; + // arguments << appPath <<"--silent"; + // process->start(appPath, {"--silent"}); + // #else + // appPath = QStandardPaths::findExecutable("spark-update-tool"); + // QString program = "pkexec"; + // QStringList arguments; + // arguments << appPath; + // QProcess *process = new QProcess(this); + // process->start(program, arguments); + // #endif appPath = QStandardPaths::findExecutable("spark-update-tool"); QString program = "pkexec"; QStringList arguments; arguments << appPath; QProcess *process = new QProcess(this); process->start(program, arguments); - #endif - } \ No newline at end of file -- Gitee From ae459373dc586550fe49a52091759ca0e3542f61 Mon Sep 17 00:00:00 2001 From: momen Date: Mon, 11 Aug 2025 20:32:58 +0800 Subject: [PATCH 024/105] =?UTF-8?q?chore:=E6=B5=8B=E8=AF=95=E4=BD=BF?= =?UTF-8?q?=E7=94=A8sudo=E8=B0=83=E7=94=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/mainwindow-dtk.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/mainwindow-dtk.cpp b/src/mainwindow-dtk.cpp index c2a90636..cedf7cae 100755 --- a/src/mainwindow-dtk.cpp +++ b/src/mainwindow-dtk.cpp @@ -550,7 +550,8 @@ void MainWindow::on_pushButton_14_clicked() // process->start(program, arguments); // #endif appPath = QStandardPaths::findExecutable("spark-update-tool"); - QString program = "pkexec"; + qDebug() << "Spark Update Tool Path: " << appPath; + QString program = "sudo"; QStringList arguments; arguments << appPath; QProcess *process = new QProcess(this); -- Gitee From c5a6125fd61c2a9b1a71b74d2f4c526449558ab0 Mon Sep 17 00:00:00 2001 From: momen Date: Tue, 12 Aug 2025 21:09:25 +0800 Subject: [PATCH 025/105] =?UTF-8?q?update:=E6=B7=BB=E5=8A=A0pkexec?= =?UTF-8?q?=E6=8F=90=E6=9D=83=E7=99=BD=E5=90=8D=E5=8D=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../store.spark-app.ss-do-upgrade.policy | 18 ------------------ .../actions/store.spark-update-tool.policy | 16 ++++++++++++++++ 2 files changed, 16 insertions(+), 18 deletions(-) delete mode 100644 pkg/usr/share/polkit-1/actions/store.spark-app.ss-do-upgrade.policy create mode 100644 pkg/usr/share/polkit-1/actions/store.spark-update-tool.policy diff --git a/pkg/usr/share/polkit-1/actions/store.spark-app.ss-do-upgrade.policy b/pkg/usr/share/polkit-1/actions/store.spark-app.ss-do-upgrade.policy deleted file mode 100644 index d82d670c..00000000 --- a/pkg/usr/share/polkit-1/actions/store.spark-app.ss-do-upgrade.policy +++ /dev/null @@ -1,18 +0,0 @@ - - - - Spark Store - x-package-repository - - 运行ss-do-upgrade需要权限 - 要使用ss-do-upgrade需要权限 - - yes - yes - yes - - /opt/durapps/spark-store/bin/update-upgrade/ss-do-upgrade.sh - true - - diff --git a/pkg/usr/share/polkit-1/actions/store.spark-update-tool.policy b/pkg/usr/share/polkit-1/actions/store.spark-update-tool.policy new file mode 100644 index 00000000..012a66ab --- /dev/null +++ b/pkg/usr/share/polkit-1/actions/store.spark-update-tool.policy @@ -0,0 +1,16 @@ + + + + + Run the Spark Update Tool + Authentication is required to update the system + /usr/bin/spark-update-tool + true + + yes + no + + + -- Gitee From 42f7b44945f3b7cd0eae9ba0e7e0490f743c74ef Mon Sep 17 00:00:00 2001 From: momen Date: Tue, 12 Aug 2025 21:17:21 +0800 Subject: [PATCH 026/105] =?UTF-8?q?update:=E5=B7=B2=E8=B0=83=E7=94=A8?= =?UTF-8?q?=E6=9B=B4=E6=96=B0=E5=99=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/mainwindow-dtk.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mainwindow-dtk.cpp b/src/mainwindow-dtk.cpp index cedf7cae..2a4c037f 100755 --- a/src/mainwindow-dtk.cpp +++ b/src/mainwindow-dtk.cpp @@ -551,7 +551,7 @@ void MainWindow::on_pushButton_14_clicked() // #endif appPath = QStandardPaths::findExecutable("spark-update-tool"); qDebug() << "Spark Update Tool Path: " << appPath; - QString program = "sudo"; + QString program = "pkexec"; QStringList arguments; arguments << appPath; QProcess *process = new QProcess(this); -- Gitee From ef38755e748a06dcb71b469584ad521f9b794577 Mon Sep 17 00:00:00 2001 From: momen Date: Wed, 13 Aug 2025 19:19:05 +0800 Subject: [PATCH 027/105] =?UTF-8?q?chore:=E5=AE=89=E8=A3=85=E8=BD=AF?= =?UTF-8?q?=E4=BB=B6=E5=90=8E=E6=A0=87=E8=AE=B0=E4=B8=BA=E4=BB=A5=E5=AE=89?= =?UTF-8?q?=E8=A3=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/appdelegate.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/appdelegate.cpp b/src/appdelegate.cpp index 1a1c3e98..de5c9edb 100644 --- a/src/appdelegate.cpp +++ b/src/appdelegate.cpp @@ -14,6 +14,7 @@ AppDelegate::AppDelegate(QObject *parent) [this](const QString &packageName, bool success) { if (m_downloads.contains(packageName)) { m_downloads[packageName].isDownloading = false; + m_downloads[packageName].isInstalled = true; emit updateDisplay(packageName); qDebug() << (success ? "下载完成:" : "下载失败:") << packageName; if (success) { -- Gitee From dd11831dfa8c9e79d792659849603799058e8b11 Mon Sep 17 00:00:00 2001 From: momen Date: Thu, 14 Aug 2025 20:03:31 +0800 Subject: [PATCH 028/105] =?UTF-8?q?fix:=E4=BF=AE=E5=A4=8D=E5=AE=89?= =?UTF-8?q?=E8=A3=85=E6=88=90=E5=8A=9F=E5=90=8E=E6=98=BE=E7=A4=BA=E4=B8=BA?= =?UTF-8?q?=E4=B8=8B=E8=BD=BD=E5=AE=8C=E6=88=90=E7=9A=84bug?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/appdelegate.cpp | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/src/appdelegate.cpp b/src/appdelegate.cpp index de5c9edb..973fa825 100644 --- a/src/appdelegate.cpp +++ b/src/appdelegate.cpp @@ -14,15 +14,16 @@ AppDelegate::AppDelegate(QObject *parent) [this](const QString &packageName, bool success) { if (m_downloads.contains(packageName)) { m_downloads[packageName].isDownloading = false; - m_downloads[packageName].isInstalled = true; + // 不要提前设置 isInstalled emit updateDisplay(packageName); qDebug() << (success ? "下载完成:" : "下载失败:") << packageName; if (success) { - enqueueInstall(packageName); + enqueueInstall(packageName); // 安装完成后再设置 isInstalled } } }); + connect(m_downloadManager, &DownloadManager::downloadProgress, this, [this](const QString &packageName, int progress) { if (m_downloads.contains(packageName)) { @@ -277,11 +278,11 @@ void AppDelegate::startNextInstall() { qDebug().noquote() << QString::fromLocal8Bit(err); }); connect(m_installProcess, QOverload::of(&QProcess::finished), - this, [this, packageName, logFile](int /*exitCode*/, QProcess::ExitStatus /*status*/) { + this, [this, packageName, logFile](int exitCode, QProcess::ExitStatus status) { if (logFile) logFile->close(); - // 若未检测到“软件包已安装”,此处兜底 - if (!m_downloads[packageName].isInstalled) { - m_downloads[packageName].isInstalling = false; + m_downloads[packageName].isInstalling = false; + if (exitCode == 0) { + m_downloads[packageName].isInstalled = true; // 安装成功 } emit updateDisplay(packageName); m_installProcess->deleteLater(); @@ -289,6 +290,7 @@ void AppDelegate::startNextInstall() { m_installingPackage.clear(); startNextInstall(); }); + } else { // 日志文件无法打开时,仍然要连接原有信号 connect(m_installProcess, &QProcess::readyReadStandardOutput, this, [this, packageName]() { -- Gitee From e5217b3829f4732887140066e6c3d33a120dc9da Mon Sep 17 00:00:00 2001 From: momen Date: Fri, 29 Aug 2025 21:28:22 +0800 Subject: [PATCH 029/105] =?UTF-8?q?update:=E5=BC=95=E5=85=A5QScreen?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/appdelegate.cpp | 2 -- src/mainwindow.h | 2 +- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/src/appdelegate.cpp b/src/appdelegate.cpp index 973fa825..0c930657 100644 --- a/src/appdelegate.cpp +++ b/src/appdelegate.cpp @@ -23,7 +23,6 @@ AppDelegate::AppDelegate(QObject *parent) } }); - connect(m_downloadManager, &DownloadManager::downloadProgress, this, [this](const QString &packageName, int progress) { if (m_downloads.contains(packageName)) { @@ -290,7 +289,6 @@ void AppDelegate::startNextInstall() { m_installingPackage.clear(); startNextInstall(); }); - } else { // 日志文件无法打开时,仍然要连接原有信号 connect(m_installProcess, &QProcess::readyReadStandardOutput, this, [this, packageName]() { diff --git a/src/mainwindow.h b/src/mainwindow.h index bc7f9d72..d754b5f7 100644 --- a/src/mainwindow.h +++ b/src/mainwindow.h @@ -7,7 +7,7 @@ #include "appdelegate.h" #include #include // 添加头文件 - +#include QT_BEGIN_NAMESPACE namespace Ui { class MainWindow; -- Gitee From 286f34f3f865d9cf885979033b4db3270399d78c Mon Sep 17 00:00:00 2001 From: momen Date: Fri, 29 Aug 2025 23:08:43 +0800 Subject: [PATCH 030/105] =?UTF-8?q?chore:=E5=88=A0=E9=99=A4=E6=97=A7?= =?UTF-8?q?=E6=9B=B4=E6=96=B0=E5=99=A8=E4=BB=A3=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- spark-update-tool/.gitignore | 62 -- spark-update-tool/CMakeLists.txt | 75 -- spark-update-tool/LICENSE | 674 ------------------ spark-update-tool/README.md | 15 - spark-update-tool/README.zh.md | 25 - spark-update-tool/debian/changelog | 5 - spark-update-tool/debian/compat | 1 - spark-update-tool/debian/control | 13 - spark-update-tool/debian/copyright | 7 - spark-update-tool/debian/install | 3 - spark-update-tool/debian/postrm | 11 - spark-update-tool/debian/rules | 7 - spark-update-tool/debian/source/format | 1 - .../debian/spark-update-tool.desktop | 9 - .../resources/128*128/spark-update-tool.png | Bin 9142 -> 0 bytes spark-update-tool/resources/default_icon.svg | 1 - spark-update-tool/resources/down_arrow.svg | 1 - .../resources/spark-update-tool.svg | 1 - spark-update-tool/src/appdelegate.cpp | 322 --------- spark-update-tool/src/appdelegate.h | 46 -- spark-update-tool/src/applistmodel.cpp | 62 -- spark-update-tool/src/applistmodel.h | 26 - spark-update-tool/src/aptssupdater.cpp | 398 ----------- spark-update-tool/src/aptssupdater.h | 28 - spark-update-tool/src/downloadmanager.cpp | 117 --- spark-update-tool/src/downloadmanager.h | 28 - spark-update-tool/src/icons.qrc | 8 - spark-update-tool/src/main.cpp | 86 --- spark-update-tool/src/mainwindow.cpp | 268 ------- spark-update-tool/src/mainwindow.h | 36 - spark-update-tool/src/mainwindow.ui | 256 ------- update-tool/.gitignore | 62 -- update-tool/CMakeLists.txt | 75 -- update-tool/LICENSE | 674 ------------------ update-tool/README.md | 15 - update-tool/README.zh.md | 25 - update-tool/debian/changelog | 5 - update-tool/debian/compat | 1 - update-tool/debian/control | 13 - update-tool/debian/copyright | 7 - update-tool/debian/install | 3 - update-tool/debian/postrm | 11 - update-tool/debian/rules | 7 - update-tool/debian/source/format | 1 - update-tool/debian/spark-update-tool.desktop | 9 - .../resources/128*128/spark-update-tool.png | Bin 9142 -> 0 bytes update-tool/resources/default_icon.svg | 1 - update-tool/resources/down_arrow.svg | 1 - update-tool/resources/spark-update-tool.svg | 1 - update-tool/src/appdelegate.cpp | 321 --------- update-tool/src/appdelegate.h | 46 -- update-tool/src/applistmodel.cpp | 62 -- update-tool/src/applistmodel.h | 26 - update-tool/src/aptssupdater.cpp | 398 ----------- update-tool/src/aptssupdater.h | 28 - update-tool/src/downloadmanager.cpp | 117 --- update-tool/src/downloadmanager.h | 28 - update-tool/src/icons.qrc | 8 - update-tool/src/main.cpp | 86 --- update-tool/src/mainwindow.cpp | 268 ------- update-tool/src/mainwindow.h | 36 - update-tool/src/mainwindow.ui | 256 ------- 62 files changed, 5183 deletions(-) delete mode 100644 spark-update-tool/.gitignore delete mode 100644 spark-update-tool/CMakeLists.txt delete mode 100644 spark-update-tool/LICENSE delete mode 100644 spark-update-tool/README.md delete mode 100644 spark-update-tool/README.zh.md delete mode 100644 spark-update-tool/debian/changelog delete mode 100644 spark-update-tool/debian/compat delete mode 100644 spark-update-tool/debian/control delete mode 100644 spark-update-tool/debian/copyright delete mode 100644 spark-update-tool/debian/install delete mode 100644 spark-update-tool/debian/postrm delete mode 100755 spark-update-tool/debian/rules delete mode 100644 spark-update-tool/debian/source/format delete mode 100644 spark-update-tool/debian/spark-update-tool.desktop delete mode 100644 spark-update-tool/resources/128*128/spark-update-tool.png delete mode 100644 spark-update-tool/resources/default_icon.svg delete mode 100644 spark-update-tool/resources/down_arrow.svg delete mode 100644 spark-update-tool/resources/spark-update-tool.svg delete mode 100644 spark-update-tool/src/appdelegate.cpp delete mode 100644 spark-update-tool/src/appdelegate.h delete mode 100644 spark-update-tool/src/applistmodel.cpp delete mode 100644 spark-update-tool/src/applistmodel.h delete mode 100644 spark-update-tool/src/aptssupdater.cpp delete mode 100644 spark-update-tool/src/aptssupdater.h delete mode 100644 spark-update-tool/src/downloadmanager.cpp delete mode 100644 spark-update-tool/src/downloadmanager.h delete mode 100644 spark-update-tool/src/icons.qrc delete mode 100644 spark-update-tool/src/main.cpp delete mode 100644 spark-update-tool/src/mainwindow.cpp delete mode 100644 spark-update-tool/src/mainwindow.h delete mode 100644 spark-update-tool/src/mainwindow.ui delete mode 100644 update-tool/.gitignore delete mode 100644 update-tool/CMakeLists.txt delete mode 100644 update-tool/LICENSE delete mode 100644 update-tool/README.md delete mode 100644 update-tool/README.zh.md delete mode 100644 update-tool/debian/changelog delete mode 100644 update-tool/debian/compat delete mode 100644 update-tool/debian/control delete mode 100644 update-tool/debian/copyright delete mode 100644 update-tool/debian/install delete mode 100644 update-tool/debian/postrm delete mode 100755 update-tool/debian/rules delete mode 100644 update-tool/debian/source/format delete mode 100644 update-tool/debian/spark-update-tool.desktop delete mode 100644 update-tool/resources/128*128/spark-update-tool.png delete mode 100644 update-tool/resources/default_icon.svg delete mode 100644 update-tool/resources/down_arrow.svg delete mode 100644 update-tool/resources/spark-update-tool.svg delete mode 100644 update-tool/src/appdelegate.cpp delete mode 100644 update-tool/src/appdelegate.h delete mode 100644 update-tool/src/applistmodel.cpp delete mode 100644 update-tool/src/applistmodel.h delete mode 100644 update-tool/src/aptssupdater.cpp delete mode 100644 update-tool/src/aptssupdater.h delete mode 100644 update-tool/src/downloadmanager.cpp delete mode 100644 update-tool/src/downloadmanager.h delete mode 100644 update-tool/src/icons.qrc delete mode 100644 update-tool/src/main.cpp delete mode 100644 update-tool/src/mainwindow.cpp delete mode 100644 update-tool/src/mainwindow.h delete mode 100644 update-tool/src/mainwindow.ui diff --git a/spark-update-tool/.gitignore b/spark-update-tool/.gitignore deleted file mode 100644 index 79c9ac74..00000000 --- a/spark-update-tool/.gitignore +++ /dev/null @@ -1,62 +0,0 @@ -build -.vscode -.cache -CMakeLists.txt.user -CMakeLists.txt.user.* -obj-x86_64-linux-gnu -# C++ objects and libs -*.slo -*.lo -*.o -*.a -*.la -*.lai -*.so -*.dll -*.dylib - -# Qt-es -object_script.*.Release -object_script.*.Debug -*_plugin_import.cpp -/.qmake.cache -/.qmake.stash -*.pro.user -*.pro.user.* -*.qbs.user -*.qbs.user.* -*.moc -moc_*.cpp -moc_*.h -qrc_*.cpp -ui_*.h -*.qmlc -*.jsc -Makefile* -*build-* - -# Qt unit tests -target_wrapper.* - -# Qt qm files -translations/*.qm - -# QtCreator -*.autosave - -# QtCreator Qml -*.qmlproject.user -*.qmlproject.user.* - -# QtCreator CMake -CMakeLists.txt.user* -build - -# Debian dpkg-buildpackage -debian/*.debhelper* -debian/files -debian/*.substvars -debian/spark-update-tool - -.vscode/* -src/spark-update-tool diff --git a/spark-update-tool/CMakeLists.txt b/spark-update-tool/CMakeLists.txt deleted file mode 100644 index 6c624b41..00000000 --- a/spark-update-tool/CMakeLists.txt +++ /dev/null @@ -1,75 +0,0 @@ -cmake_minimum_required(VERSION 3.16) - -project(spark-update-tool VERSION 0.1 LANGUAGES CXX) - -set(CMAKE_AUTOUIC ON) -set(CMAKE_AUTOMOC ON) -set(CMAKE_AUTORCC ON) - -set(CMAKE_CXX_STANDARD 17) -set(CMAKE_CXX_STANDARD_REQUIRED ON) - -find_package(QT NAMES Qt6 Qt5 REQUIRED COMPONENTS Widgets Network Concurrent) -find_package(Qt${QT_VERSION_MAJOR} REQUIRED COMPONENTS Widgets Network Concurrent) - -set(PROJECT_SOURCES - src/main.cpp - src/mainwindow.cpp - src/mainwindow.h - src/mainwindow.ui -) - -if(${QT_VERSION_MAJOR} GREATER_EQUAL 6) - qt_add_executable(spark-update-tool - MANUAL_FINALIZATION - ${PROJECT_SOURCES} - src/aptssupdater.h src/aptssupdater.cpp - src/icons.qrc - src/appdelegate.h src/appdelegate.cpp - src/applistmodel.h src/applistmodel.cpp - src/downloadmanager.h src/downloadmanager.cpp - ) -# Define target properties for Android with Qt 6 as: -# set_property(TARGET spark-update-tool APPEND PROPERTY QT_ANDROID_PACKAGE_SOURCE_DIR -# ${CMAKE_CURRENT_SOURCE_DIR}/android) -# For more information, see https://doc.qt.io/qt-6/qt-add-executable.html#target-creation -else() - if(ANDROID) - add_library(spark-update-tool SHARED - ${PROJECT_SOURCES} - ) -# Define properties for Android with Qt 5 after find_package() calls as: -# set(ANDROID_PACKAGE_SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/android") - else() - add_executable(spark-update-tool - ${PROJECT_SOURCES} - ) - endif() -endif() - -target_link_libraries(spark-update-tool PRIVATE Qt${QT_VERSION_MAJOR}::Widgets Qt${QT_VERSION_MAJOR}::Network Qt${QT_VERSION_MAJOR}::Concurrent) - -# Qt for iOS sets MACOSX_BUNDLE_GUI_IDENTIFIER automatically since Qt 6.1. -# If you are developing for iOS or macOS you should consider setting an -# explicit, fixed bundle identifier manually though. -if(${QT_VERSION} VERSION_LESS 6.1.0) - set(BUNDLE_ID_OPTION MACOSX_BUNDLE_GUI_IDENTIFIER com.example.spark-update-tool) -endif() -set_target_properties(spark-update-tool PROPERTIES - ${BUNDLE_ID_OPTION} - MACOSX_BUNDLE_BUNDLE_VERSION ${PROJECT_VERSION} - MACOSX_BUNDLE_SHORT_VERSION_STRING ${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR} - MACOSX_BUNDLE TRUE - WIN32_EXECUTABLE TRUE -) - -include(GNUInstallDirs) -install(TARGETS spark-update-tool - BUNDLE DESTINATION . - LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} - RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} -) - -if(QT_VERSION_MAJOR EQUAL 6) - qt_finalize_executable(spark-update-tool) -endif() diff --git a/spark-update-tool/LICENSE b/spark-update-tool/LICENSE deleted file mode 100644 index 3877ae0a..00000000 --- a/spark-update-tool/LICENSE +++ /dev/null @@ -1,674 +0,0 @@ - GNU GENERAL PUBLIC LICENSE - Version 3, 29 June 2007 - - Copyright (C) 2007 Free Software Foundation, Inc. - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - - Preamble - - The GNU General Public License is a free, copyleft license for -software and other kinds of works. - - The licenses for most software and other practical works are designed -to take away your freedom to share and change the works. By contrast, -the GNU General Public License is intended to guarantee your freedom to -share and change all versions of a program--to make sure it remains free -software for all its users. We, the Free Software Foundation, use the -GNU General Public License for most of our software; it applies also to -any other work released this way by its authors. You can apply it to -your programs, too. - - When we speak of free software, we are referring to freedom, not -price. Our General Public Licenses are designed to make sure that you -have the freedom to distribute copies of free software (and charge for -them if you wish), that you receive source code or can get it if you -want it, that you can change the software or use pieces of it in new -free programs, and that you know you can do these things. - - To protect your rights, we need to prevent others from denying you -these rights or asking you to surrender the rights. Therefore, you have -certain responsibilities if you distribute copies of the software, or if -you modify it: responsibilities to respect the freedom of others. - - For example, if you distribute copies of such a program, whether -gratis or for a fee, you must pass on to the recipients the same -freedoms that you received. You must make sure that they, too, receive -or can get the source code. And you must show them these terms so they -know their rights. - - Developers that use the GNU GPL protect your rights with two steps: -(1) assert copyright on the software, and (2) offer you this License -giving you legal permission to copy, distribute and/or modify it. - - For the developers' and authors' protection, the GPL clearly explains -that there is no warranty for this free software. For both users' and -authors' sake, the GPL requires that modified versions be marked as -changed, so that their problems will not be attributed erroneously to -authors of previous versions. - - Some devices are designed to deny users access to install or run -modified versions of the software inside them, although the manufacturer -can do so. This is fundamentally incompatible with the aim of -protecting users' freedom to change the software. The systematic -pattern of such abuse occurs in the area of products for individuals to -use, which is precisely where it is most unacceptable. Therefore, we -have designed this version of the GPL to prohibit the practice for those -products. If such problems arise substantially in other domains, we -stand ready to extend this provision to those domains in future versions -of the GPL, as needed to protect the freedom of users. - - Finally, every program is threatened constantly by software patents. -States should not allow patents to restrict development and use of -software on general-purpose computers, but in those that do, we wish to -avoid the special danger that patents applied to a free program could -make it effectively proprietary. To prevent this, the GPL assures that -patents cannot be used to render the program non-free. - - The precise terms and conditions for copying, distribution and -modification follow. - - TERMS AND CONDITIONS - - 0. Definitions. - - "This License" refers to version 3 of the GNU General Public License. - - "Copyright" also means copyright-like laws that apply to other kinds of -works, such as semiconductor masks. - - "The Program" refers to any copyrightable work licensed under this -License. Each licensee is addressed as "you". "Licensees" and -"recipients" may be individuals or organizations. - - To "modify" a work means to copy from or adapt all or part of the work -in a fashion requiring copyright permission, other than the making of an -exact copy. The resulting work is called a "modified version" of the -earlier work or a work "based on" the earlier work. - - A "covered work" means either the unmodified Program or a work based -on the Program. - - To "propagate" a work means to do anything with it that, without -permission, would make you directly or secondarily liable for -infringement under applicable copyright law, except executing it on a -computer or modifying a private copy. Propagation includes copying, -distribution (with or without modification), making available to the -public, and in some countries other activities as well. - - To "convey" a work means any kind of propagation that enables other -parties to make or receive copies. Mere interaction with a user through -a computer network, with no transfer of a copy, is not conveying. - - An interactive user interface displays "Appropriate Legal Notices" -to the extent that it includes a convenient and prominently visible -feature that (1) displays an appropriate copyright notice, and (2) -tells the user that there is no warranty for the work (except to the -extent that warranties are provided), that licensees may convey the -work under this License, and how to view a copy of this License. If -the interface presents a list of user commands or options, such as a -menu, a prominent item in the list meets this criterion. - - 1. Source Code. - - The "source code" for a work means the preferred form of the work -for making modifications to it. "Object code" means any non-source -form of a work. - - A "Standard Interface" means an interface that either is an official -standard defined by a recognized standards body, or, in the case of -interfaces specified for a particular programming language, one that -is widely used among developers working in that language. - - The "System Libraries" of an executable work include anything, other -than the work as a whole, that (a) is included in the normal form of -packaging a Major Component, but which is not part of that Major -Component, and (b) serves only to enable use of the work with that -Major Component, or to implement a Standard Interface for which an -implementation is available to the public in source code form. A -"Major Component", in this context, means a major essential component -(kernel, window system, and so on) of the specific operating system -(if any) on which the executable work runs, or a compiler used to -produce the work, or an object code interpreter used to run it. - - The "Corresponding Source" for a work in object code form means all -the source code needed to generate, install, and (for an executable -work) run the object code and to modify the work, including scripts to -control those activities. However, it does not include the work's -System Libraries, or general-purpose tools or generally available free -programs which are used unmodified in performing those activities but -which are not part of the work. For example, Corresponding Source -includes interface definition files associated with source files for -the work, and the source code for shared libraries and dynamically -linked subprograms that the work is specifically designed to require, -such as by intimate data communication or control flow between those -subprograms and other parts of the work. - - The Corresponding Source need not include anything that users -can regenerate automatically from other parts of the Corresponding -Source. - - The Corresponding Source for a work in source code form is that -same work. - - 2. Basic Permissions. - - All rights granted under this License are granted for the term of -copyright on the Program, and are irrevocable provided the stated -conditions are met. This License explicitly affirms your unlimited -permission to run the unmodified Program. The output from running a -covered work is covered by this License only if the output, given its -content, constitutes a covered work. This License acknowledges your -rights of fair use or other equivalent, as provided by copyright law. - - You may make, run and propagate covered works that you do not -convey, without conditions so long as your license otherwise remains -in force. You may convey covered works to others for the sole purpose -of having them make modifications exclusively for you, or provide you -with facilities for running those works, provided that you comply with -the terms of this License in conveying all material for which you do -not control copyright. Those thus making or running the covered works -for you must do so exclusively on your behalf, under your direction -and control, on terms that prohibit them from making any copies of -your copyrighted material outside their relationship with you. - - Conveying under any other circumstances is permitted solely under -the conditions stated below. Sublicensing is not allowed; section 10 -makes it unnecessary. - - 3. Protecting Users' Legal Rights From Anti-Circumvention Law. - - No covered work shall be deemed part of an effective technological -measure under any applicable law fulfilling obligations under article -11 of the WIPO copyright treaty adopted on 20 December 1996, or -similar laws prohibiting or restricting circumvention of such -measures. - - When you convey a covered work, you waive any legal power to forbid -circumvention of technological measures to the extent such circumvention -is effected by exercising rights under this License with respect to -the covered work, and you disclaim any intention to limit operation or -modification of the work as a means of enforcing, against the work's -users, your or third parties' legal rights to forbid circumvention of -technological measures. - - 4. Conveying Verbatim Copies. - - You may convey verbatim copies of the Program's source code as you -receive it, in any medium, provided that you conspicuously and -appropriately publish on each copy an appropriate copyright notice; -keep intact all notices stating that this License and any -non-permissive terms added in accord with section 7 apply to the code; -keep intact all notices of the absence of any warranty; and give all -recipients a copy of this License along with the Program. - - You may charge any price or no price for each copy that you convey, -and you may offer support or warranty protection for a fee. - - 5. Conveying Modified Source Versions. - - You may convey a work based on the Program, or the modifications to -produce it from the Program, in the form of source code under the -terms of section 4, provided that you also meet all of these conditions: - - a) The work must carry prominent notices stating that you modified - it, and giving a relevant date. - - b) The work must carry prominent notices stating that it is - released under this License and any conditions added under section - 7. This requirement modifies the requirement in section 4 to - "keep intact all notices". - - c) You must license the entire work, as a whole, under this - License to anyone who comes into possession of a copy. This - License will therefore apply, along with any applicable section 7 - additional terms, to the whole of the work, and all its parts, - regardless of how they are packaged. This License gives no - permission to license the work in any other way, but it does not - invalidate such permission if you have separately received it. - - d) If the work has interactive user interfaces, each must display - Appropriate Legal Notices; however, if the Program has interactive - interfaces that do not display Appropriate Legal Notices, your - work need not make them do so. - - A compilation of a covered work with other separate and independent -works, which are not by their nature extensions of the covered work, -and which are not combined with it such as to form a larger program, -in or on a volume of a storage or distribution medium, is called an -"aggregate" if the compilation and its resulting copyright are not -used to limit the access or legal rights of the compilation's users -beyond what the individual works permit. Inclusion of a covered work -in an aggregate does not cause this License to apply to the other -parts of the aggregate. - - 6. Conveying Non-Source Forms. - - You may convey a covered work in object code form under the terms -of sections 4 and 5, provided that you also convey the -machine-readable Corresponding Source under the terms of this License, -in one of these ways: - - a) Convey the object code in, or embodied in, a physical product - (including a physical distribution medium), accompanied by the - Corresponding Source fixed on a durable physical medium - customarily used for software interchange. - - b) Convey the object code in, or embodied in, a physical product - (including a physical distribution medium), accompanied by a - written offer, valid for at least three years and valid for as - long as you offer spare parts or customer support for that product - model, to give anyone who possesses the object code either (1) a - copy of the Corresponding Source for all the software in the - product that is covered by this License, on a durable physical - medium customarily used for software interchange, for a price no - more than your reasonable cost of physically performing this - conveying of source, or (2) access to copy the - Corresponding Source from a network server at no charge. - - c) Convey individual copies of the object code with a copy of the - written offer to provide the Corresponding Source. This - alternative is allowed only occasionally and noncommercially, and - only if you received the object code with such an offer, in accord - with subsection 6b. - - d) Convey the object code by offering access from a designated - place (gratis or for a charge), and offer equivalent access to the - Corresponding Source in the same way through the same place at no - further charge. You need not require recipients to copy the - Corresponding Source along with the object code. If the place to - copy the object code is a network server, the Corresponding Source - may be on a different server (operated by you or a third party) - that supports equivalent copying facilities, provided you maintain - clear directions next to the object code saying where to find the - Corresponding Source. Regardless of what server hosts the - Corresponding Source, you remain obligated to ensure that it is - available for as long as needed to satisfy these requirements. - - e) Convey the object code using peer-to-peer transmission, provided - you inform other peers where the object code and Corresponding - Source of the work are being offered to the general public at no - charge under subsection 6d. - - A separable portion of the object code, whose source code is excluded -from the Corresponding Source as a System Library, need not be -included in conveying the object code work. - - A "User Product" is either (1) a "consumer product", which means any -tangible personal property which is normally used for personal, family, -or household purposes, or (2) anything designed or sold for incorporation -into a dwelling. In determining whether a product is a consumer product, -doubtful cases shall be resolved in favor of coverage. For a particular -product received by a particular user, "normally used" refers to a -typical or common use of that class of product, regardless of the status -of the particular user or of the way in which the particular user -actually uses, or expects or is expected to use, the product. A product -is a consumer product regardless of whether the product has substantial -commercial, industrial or non-consumer uses, unless such uses represent -the only significant mode of use of the product. - - "Installation Information" for a User Product means any methods, -procedures, authorization keys, or other information required to install -and execute modified versions of a covered work in that User Product from -a modified version of its Corresponding Source. The information must -suffice to ensure that the continued functioning of the modified object -code is in no case prevented or interfered with solely because -modification has been made. - - If you convey an object code work under this section in, or with, or -specifically for use in, a User Product, and the conveying occurs as -part of a transaction in which the right of possession and use of the -User Product is transferred to the recipient in perpetuity or for a -fixed term (regardless of how the transaction is characterized), the -Corresponding Source conveyed under this section must be accompanied -by the Installation Information. But this requirement does not apply -if neither you nor any third party retains the ability to install -modified object code on the User Product (for example, the work has -been installed in ROM). - - The requirement to provide Installation Information does not include a -requirement to continue to provide support service, warranty, or updates -for a work that has been modified or installed by the recipient, or for -the User Product in which it has been modified or installed. Access to a -network may be denied when the modification itself materially and -adversely affects the operation of the network or violates the rules and -protocols for communication across the network. - - Corresponding Source conveyed, and Installation Information provided, -in accord with this section must be in a format that is publicly -documented (and with an implementation available to the public in -source code form), and must require no special password or key for -unpacking, reading or copying. - - 7. Additional Terms. - - "Additional permissions" are terms that supplement the terms of this -License by making exceptions from one or more of its conditions. -Additional permissions that are applicable to the entire Program shall -be treated as though they were included in this License, to the extent -that they are valid under applicable law. If additional permissions -apply only to part of the Program, that part may be used separately -under those permissions, but the entire Program remains governed by -this License without regard to the additional permissions. - - When you convey a copy of a covered work, you may at your option -remove any additional permissions from that copy, or from any part of -it. (Additional permissions may be written to require their own -removal in certain cases when you modify the work.) You may place -additional permissions on material, added by you to a covered work, -for which you have or can give appropriate copyright permission. - - Notwithstanding any other provision of this License, for material you -add to a covered work, you may (if authorized by the copyright holders of -that material) supplement the terms of this License with terms: - - a) Disclaiming warranty or limiting liability differently from the - terms of sections 15 and 16 of this License; or - - b) Requiring preservation of specified reasonable legal notices or - author attributions in that material or in the Appropriate Legal - Notices displayed by works containing it; or - - c) Prohibiting misrepresentation of the origin of that material, or - requiring that modified versions of such material be marked in - reasonable ways as different from the original version; or - - d) Limiting the use for publicity purposes of names of licensors or - authors of the material; or - - e) Declining to grant rights under trademark law for use of some - trade names, trademarks, or service marks; or - - f) Requiring indemnification of licensors and authors of that - material by anyone who conveys the material (or modified versions of - it) with contractual assumptions of liability to the recipient, for - any liability that these contractual assumptions directly impose on - those licensors and authors. - - All other non-permissive additional terms are considered "further -restrictions" within the meaning of section 10. If the Program as you -received it, or any part of it, contains a notice stating that it is -governed by this License along with a term that is a further -restriction, you may remove that term. If a license document contains -a further restriction but permits relicensing or conveying under this -License, you may add to a covered work material governed by the terms -of that license document, provided that the further restriction does -not survive such relicensing or conveying. - - If you add terms to a covered work in accord with this section, you -must place, in the relevant source files, a statement of the -additional terms that apply to those files, or a notice indicating -where to find the applicable terms. - - Additional terms, permissive or non-permissive, may be stated in the -form of a separately written license, or stated as exceptions; -the above requirements apply either way. - - 8. Termination. - - You may not propagate or modify a covered work except as expressly -provided under this License. Any attempt otherwise to propagate or -modify it is void, and will automatically terminate your rights under -this License (including any patent licenses granted under the third -paragraph of section 11). - - However, if you cease all violation of this License, then your -license from a particular copyright holder is reinstated (a) -provisionally, unless and until the copyright holder explicitly and -finally terminates your license, and (b) permanently, if the copyright -holder fails to notify you of the violation by some reasonable means -prior to 60 days after the cessation. - - Moreover, your license from a particular copyright holder is -reinstated permanently if the copyright holder notifies you of the -violation by some reasonable means, this is the first time you have -received notice of violation of this License (for any work) from that -copyright holder, and you cure the violation prior to 30 days after -your receipt of the notice. - - Termination of your rights under this section does not terminate the -licenses of parties who have received copies or rights from you under -this License. If your rights have been terminated and not permanently -reinstated, you do not qualify to receive new licenses for the same -material under section 10. - - 9. Acceptance Not Required for Having Copies. - - You are not required to accept this License in order to receive or -run a copy of the Program. Ancillary propagation of a covered work -occurring solely as a consequence of using peer-to-peer transmission -to receive a copy likewise does not require acceptance. However, -nothing other than this License grants you permission to propagate or -modify any covered work. These actions infringe copyright if you do -not accept this License. Therefore, by modifying or propagating a -covered work, you indicate your acceptance of this License to do so. - - 10. Automatic Licensing of Downstream Recipients. - - Each time you convey a covered work, the recipient automatically -receives a license from the original licensors, to run, modify and -propagate that work, subject to this License. You are not responsible -for enforcing compliance by third parties with this License. - - An "entity transaction" is a transaction transferring control of an -organization, or substantially all assets of one, or subdividing an -organization, or merging organizations. If propagation of a covered -work results from an entity transaction, each party to that -transaction who receives a copy of the work also receives whatever -licenses to the work the party's predecessor in interest had or could -give under the previous paragraph, plus a right to possession of the -Corresponding Source of the work from the predecessor in interest, if -the predecessor has it or can get it with reasonable efforts. - - You may not impose any further restrictions on the exercise of the -rights granted or affirmed under this License. For example, you may -not impose a license fee, royalty, or other charge for exercise of -rights granted under this License, and you may not initiate litigation -(including a cross-claim or counterclaim in a lawsuit) alleging that -any patent claim is infringed by making, using, selling, offering for -sale, or importing the Program or any portion of it. - - 11. Patents. - - A "contributor" is a copyright holder who authorizes use under this -License of the Program or a work on which the Program is based. The -work thus licensed is called the contributor's "contributor version". - - A contributor's "essential patent claims" are all patent claims -owned or controlled by the contributor, whether already acquired or -hereafter acquired, that would be infringed by some manner, permitted -by this License, of making, using, or selling its contributor version, -but do not include claims that would be infringed only as a -consequence of further modification of the contributor version. For -purposes of this definition, "control" includes the right to grant -patent sublicenses in a manner consistent with the requirements of -this License. - - Each contributor grants you a non-exclusive, worldwide, royalty-free -patent license under the contributor's essential patent claims, to -make, use, sell, offer for sale, import and otherwise run, modify and -propagate the contents of its contributor version. - - In the following three paragraphs, a "patent license" is any express -agreement or commitment, however denominated, not to enforce a patent -(such as an express permission to practice a patent or covenant not to -sue for patent infringement). To "grant" such a patent license to a -party means to make such an agreement or commitment not to enforce a -patent against the party. - - If you convey a covered work, knowingly relying on a patent license, -and the Corresponding Source of the work is not available for anyone -to copy, free of charge and under the terms of this License, through a -publicly available network server or other readily accessible means, -then you must either (1) cause the Corresponding Source to be so -available, or (2) arrange to deprive yourself of the benefit of the -patent license for this particular work, or (3) arrange, in a manner -consistent with the requirements of this License, to extend the patent -license to downstream recipients. "Knowingly relying" means you have -actual knowledge that, but for the patent license, your conveying the -covered work in a country, or your recipient's use of the covered work -in a country, would infringe one or more identifiable patents in that -country that you have reason to believe are valid. - - If, pursuant to or in connection with a single transaction or -arrangement, you convey, or propagate by procuring conveyance of, a -covered work, and grant a patent license to some of the parties -receiving the covered work authorizing them to use, propagate, modify -or convey a specific copy of the covered work, then the patent license -you grant is automatically extended to all recipients of the covered -work and works based on it. - - A patent license is "discriminatory" if it does not include within -the scope of its coverage, prohibits the exercise of, or is -conditioned on the non-exercise of one or more of the rights that are -specifically granted under this License. You may not convey a covered -work if you are a party to an arrangement with a third party that is -in the business of distributing software, under which you make payment -to the third party based on the extent of your activity of conveying -the work, and under which the third party grants, to any of the -parties who would receive the covered work from you, a discriminatory -patent license (a) in connection with copies of the covered work -conveyed by you (or copies made from those copies), or (b) primarily -for and in connection with specific products or compilations that -contain the covered work, unless you entered into that arrangement, -or that patent license was granted, prior to 28 March 2007. - - Nothing in this License shall be construed as excluding or limiting -any implied license or other defenses to infringement that may -otherwise be available to you under applicable patent law. - - 12. No Surrender of Others' Freedom. - - If conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot convey a -covered work so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you may -not convey it at all. For example, if you agree to terms that obligate you -to collect a royalty for further conveying from those to whom you convey -the Program, the only way you could satisfy both those terms and this -License would be to refrain entirely from conveying the Program. - - 13. Use with the GNU Affero General Public License. - - Notwithstanding any other provision of this License, you have -permission to link or combine any covered work with a work licensed -under version 3 of the GNU Affero General Public License into a single -combined work, and to convey the resulting work. The terms of this -License will continue to apply to the part which is the covered work, -but the special requirements of the GNU Affero General Public License, -section 13, concerning interaction through a network will apply to the -combination as such. - - 14. Revised Versions of this License. - - The Free Software Foundation may publish revised and/or new versions of -the GNU General Public License from time to time. Such new versions will -be similar in spirit to the present version, but may differ in detail to -address new problems or concerns. - - Each version is given a distinguishing version number. If the -Program specifies that a certain numbered version of the GNU General -Public License "or any later version" applies to it, you have the -option of following the terms and conditions either of that numbered -version or of any later version published by the Free Software -Foundation. If the Program does not specify a version number of the -GNU General Public License, you may choose any version ever published -by the Free Software Foundation. - - If the Program specifies that a proxy can decide which future -versions of the GNU General Public License can be used, that proxy's -public statement of acceptance of a version permanently authorizes you -to choose that version for the Program. - - Later license versions may give you additional or different -permissions. However, no additional obligations are imposed on any -author or copyright holder as a result of your choosing to follow a -later version. - - 15. Disclaimer of Warranty. - - THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY -APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT -HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY -OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, -THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM -IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF -ALL NECESSARY SERVICING, REPAIR OR CORRECTION. - - 16. Limitation of Liability. - - IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING -WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS -THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY -GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE -USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF -DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD -PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), -EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF -SUCH DAMAGES. - - 17. Interpretation of Sections 15 and 16. - - If the disclaimer of warranty and limitation of liability provided -above cannot be given local legal effect according to their terms, -reviewing courts shall apply local law that most closely approximates -an absolute waiver of all civil liability in connection with the -Program, unless a warranty or assumption of liability accompanies a -copy of the Program in return for a fee. - - END OF TERMS AND CONDITIONS - - How to Apply These Terms to Your New Programs - - If you develop a new program, and you want it to be of the greatest -possible use to the public, the best way to achieve this is to make it -free software which everyone can redistribute and change under these terms. - - To do so, attach the following notices to the program. It is safest -to attach them to the start of each source file to most effectively -state the exclusion of warranty; and each file should have at least -the "copyright" line and a pointer to where the full notice is found. - - - Copyright (C) - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . - -Also add information on how to contact you by electronic and paper mail. - - If the program does terminal interaction, make it output a short -notice like this when it starts in an interactive mode: - - Copyright (C) - This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. - This is free software, and you are welcome to redistribute it - under certain conditions; type `show c' for details. - -The hypothetical commands `show w' and `show c' should show the appropriate -parts of the General Public License. Of course, your program's commands -might be different; for a GUI interface, you would use an "about box". - - You should also get your employer (if you work as a programmer) or school, -if any, to sign a "copyright disclaimer" for the program, if necessary. -For more information on this, and how to apply and follow the GNU GPL, see -. - - The GNU General Public License does not permit incorporating your program -into proprietary programs. If your program is a subroutine library, you -may consider it more useful to permit linking proprietary applications with -the library. If this is what you want to do, use the GNU Lesser General -Public License instead of this License. But first, please read -. diff --git a/spark-update-tool/README.md b/spark-update-tool/README.md deleted file mode 100644 index 778029c2..00000000 --- a/spark-update-tool/README.md +++ /dev/null @@ -1,15 +0,0 @@ -### Spark Update Tool -#### Introduction - -Welcome to Spark Software Updater. Use this tool to update applications on your Linux system. -This version is specifically designed for Linux distributions with Qt6 support. -Please run under root privileges (recommended: use `sudo`). -#### Currently Supported Linux Distributions -- [x] GXDE OS -- [x] Ubuntu -- [x] deepin -- [ ] Kylin - - -#### Contact & Feedback -momen@momen.world diff --git a/spark-update-tool/README.zh.md b/spark-update-tool/README.zh.md deleted file mode 100644 index c597ce44..00000000 --- a/spark-update-tool/README.zh.md +++ /dev/null @@ -1,25 +0,0 @@ -### 星火软件更新器 -#### 简介 - -欢迎使用星火软件更新器,您可以使用此更新器更新位于您 Linux 计算机的程序。 -此版本专为有qt6的Linux发行版所使用。 -请在root环境下运行。 -#### 当前支持的 Linux 发行版 -- [x] GXDE OS -- [x] Ubuntu -- [x] deepin -- [ ] Kylin - -#### 功能清单 - -| 功能模块 | 描述 | -|------------------|--------------------------------------| -| 应用名识别 | 基于 `ss-do-upgrade.sh` 部分代码实现 | -| 应用包大小识别 | 通过 dpkg 获取包大小信息 | -| 获取应用图标 | 利用 QDesktopServices 实现 | -| 支持 ACE 兼容环境| | -| 多线程下载 | 基于 aptss 方案 | - -如您已安装星火应用商店,则会附带本程序。 -#### 联系与反馈 -momen@momen.world \ No newline at end of file diff --git a/spark-update-tool/debian/changelog b/spark-update-tool/debian/changelog deleted file mode 100644 index b414feaa..00000000 --- a/spark-update-tool/debian/changelog +++ /dev/null @@ -1,5 +0,0 @@ -spark-update-tool (1.0.0) unstable; urgency=low - - * Initial release. - - -- momen Wed, 18 Jun 2025 00:00:00 +0000 \ No newline at end of file diff --git a/spark-update-tool/debian/compat b/spark-update-tool/debian/compat deleted file mode 100644 index f11c82a4..00000000 --- a/spark-update-tool/debian/compat +++ /dev/null @@ -1 +0,0 @@ -9 \ No newline at end of file diff --git a/spark-update-tool/debian/control b/spark-update-tool/debian/control deleted file mode 100644 index 19c9d624..00000000 --- a/spark-update-tool/debian/control +++ /dev/null @@ -1,13 +0,0 @@ -Source: spark-update-tool -Section: utils -Priority: optional -Maintainer: momen -Build-Depends: debhelper (>= 9) -Standards-Version: 3.9.6 -Homepage: https://gitee.com/spark-store-project/Spark-Update-Tool - -Package: spark-update-tool -Architecture: any -Depends: ${shlibs:Depends}, ${misc:Depends} -Description: Spark Update Tool - 星火应用商店更新组件。This package provides the Spark Update Tool. It includes features for checking for updates, downloading, and applying them seamlessly. \ No newline at end of file diff --git a/spark-update-tool/debian/copyright b/spark-update-tool/debian/copyright deleted file mode 100644 index 163489ed..00000000 --- a/spark-update-tool/debian/copyright +++ /dev/null @@ -1,7 +0,0 @@ -Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/ -Upstream-Name: spark-update-tool -Source: https://gitee.com/spark-store-project/Spark-Update-Tool - -Files: * -Copyright: 2025, momen -License: GPL-3.0+ \ No newline at end of file diff --git a/spark-update-tool/debian/install b/spark-update-tool/debian/install deleted file mode 100644 index ed44f2cf..00000000 --- a/spark-update-tool/debian/install +++ /dev/null @@ -1,3 +0,0 @@ -build/spark-update-tool /usr/bin/ -debian/spark-update-tool.desktop /usr/share/applications -resources/128*128/spark-update-tool.png /usr/share/icons/hicolor/128x128/apps diff --git a/spark-update-tool/debian/postrm b/spark-update-tool/debian/postrm deleted file mode 100644 index 263e9c42..00000000 --- a/spark-update-tool/debian/postrm +++ /dev/null @@ -1,11 +0,0 @@ -#!/bin/sh -set -e - -case "$1" in - purge) - - rm -rf /usr/share/spark-update-tool - ;; -esac - -exit 0 \ No newline at end of file diff --git a/spark-update-tool/debian/rules b/spark-update-tool/debian/rules deleted file mode 100755 index 1159ac4f..00000000 --- a/spark-update-tool/debian/rules +++ /dev/null @@ -1,7 +0,0 @@ -#!/usr/bin/make -f - -%: - dh $@ - -override_dh_auto_configure: - dh_auto_configure -- -DCMAKE_INSTALL_PREFIX=/usr diff --git a/spark-update-tool/debian/source/format b/spark-update-tool/debian/source/format deleted file mode 100644 index 9f674278..00000000 --- a/spark-update-tool/debian/source/format +++ /dev/null @@ -1 +0,0 @@ -3.0 (native) \ No newline at end of file diff --git a/spark-update-tool/debian/spark-update-tool.desktop b/spark-update-tool/debian/spark-update-tool.desktop deleted file mode 100644 index 688ba0cd..00000000 --- a/spark-update-tool/debian/spark-update-tool.desktop +++ /dev/null @@ -1,9 +0,0 @@ -[Desktop Entry] -Version=1.0 -Name=Spark Update Tool -Comment=A Qt-based application for managing and updating software -Exec=spark-update-tool -Icon=spark-update-tool -Terminal=false -Type=Application -Categories=Utility; diff --git a/spark-update-tool/resources/128*128/spark-update-tool.png b/spark-update-tool/resources/128*128/spark-update-tool.png deleted file mode 100644 index 138ed83770cf4cce8fdead9c11908a0446e8a135..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 9142 zcmV;nBT3weP)Px#8FWQhbW?9;ba!ELWdL_~cP?peYja~^aAhuUa%Y?FJQ@H1AOJ~3 zK~#90?VWji9mSRJztw#gNtP_zk{4`)H}HyWzyyq0%o?z<4FMAqAcQ0^A<9HEXur0hx-X%+S>#p}l-KD#4Z};j- zmci$vtJ}A`>eT7}ovJ#g>QuFmQgVVmxuhLy0Z!1drASW}CWH_@S>EwVvIm>xZdCvm zz=M8&QppCm^RacOLR4G<9H5JUZ)dts8aaWLZr|2NT4`mdr~+icw}Nc_;Pd@SCs*LJ z-_{R8h>9vfMHIkN>vLdhI22&hEw@Yx@8J33cPeCmlNiWR_wLW@udMG#%# z;RCz|h;3iGb^4I%J~zdLHctpKNC7L{0S+riSAfcxmFHMQ zKK1A-3JPHTR$RIOV%Z8{Y3{AyYxBm9i#~Me%msCk=r=VX#v=jY0eX&l0(@{+fL;i` z^Smi#Q(GqW(_8ubacSJ1CUC&Br8^yjA<@=t+n+V zm%O-i2L(kaO9?_NfTh3B)p{M!_TGN`tbsMv|07@kLK51rk47O9fkXmKkG>fy13sv- z48xsQO%0rRCQO(BC!M6ubsR<3)RZQZABB0&2M)rvX2ix1;e!p3OnR0pCHq>Fop%gg z^vH`S@C_`6Vpv58r2r1_^PjebcYe1v68#Y%N^3s4R zoeN0krU04-=bj4}TmV&7c4i$N?h4Rd;5#XqgthAtD_)1aEnely_Eh>G>mGmbZpu`G zQWPLx^M``IdEvslsw4WsLZaY%QX+el7m2`xi79F~Ozz5JHU|JL)7K7`q zgVRoPXXd5=Jq5nBS9R7lA(s6S4jyuqr_)H^d+MVPerK0b0D}^`gFppv^!YlVbu3(X zcOLvwYkm+#qj1s1(5DY9e+3R%Zn|9XB}&0^3J{ILZMVUYA>PcK3UDmIw^BNd_~V~o zXx!{mT2&e7y+|p z!>U#A{(D^m9|{T}gsS-yC;Bt9D!{P@-%1-cAs&AUIy-R;9MF+5e%R;n2dv#eU{?@E z0djr5zW2*tzG_gPnx|BcAJX9KKLEyzQMGMAgX(K_4NM6~jzDV*Y~2D|w?f9zN7vTE z{2O4)hp>FP{aPvDgX#jL0h1;v1qfo6Q-IzCevVpN5%)g~hq7KuA**anBo_=?{P43_ zT7t3^z}fV#y6O5;&S@OFN?H3Mgd95-W}FXw>tWkg*tru99Dw#VNTpSctf^5}_t>#Y zIo^E--h5Me207AoSa2h3-VAT7a^7%({J_t30Ybu^cS1vhM?wpAbRereyZ}GyZt!z- z=rH0}_Z5^N&r0rJwXb#hj2D+~Cxkr^G#8L>0j3QY@{3U5*Vn^Uvmq9R6)RNj^>g#u z+u-mK)jXehCM;YCFT4or*Qp1S$-tr~;0w3Go;|Q_TQQFy@N;zPso}scmwF0(fckpm zmp+g9^?hnA0YHL)hEFv#+yh*XWu(xHjcY`ZbEL2J_S>(GXxf#^&-bCJXTTS~3{C6d zq2I#hP5$5m>_4E=YZ^2+!^HlW??WXordS0g*kH|9=GS8Hchn>Ir0J@R7>M| zv5VA`;ODXp8i-tQy?RcT5ylAGtd{vV&B219S1^uWNSFY`ym8}V4b@fu=G*5B0iV7S zF1s9_ehOBwdbG0gt@q#51Y5SksL}AuGjQGvm@~Ja1iSaZrcE$o zhUGy>7&#KoImiBBoX6I*t{1yV#{&EujXMp_pI*3-RfL8}{6FS3j*DTRjxVC3F2FI# zqdj!#%mqR)%6Dk@vddx0RCw%B*s;BEe&k5_)H!hSDavY1rKRgF>=fUAau>4hZefe_LhrjU#96hSewY9-nXTj@#@qS3Thh10aa{H zQ33qAzA$$#Xga+2u4)xB8Ffw9;k2Ax;mu{Uf@Tg%KLB*vUpKdweM{Q=C5QP@YmaD6nWJZ zh~GVt!ylxiHWvLh@Hh%fS6jf=1vsa8w|(i>>6#`ccs3wIhN#-Q{1s*FfdX{aY-IpG z@(`?BTL2%FtJl;7zk5X43C+zgd9oT3&e2o<9uB~3JT)77%}f z5BCNiAe}}EVgG2F`UtmAfVJCOz|YZ?NicYD9(({@Fk#E=>pq1AQ>QK9WdjI646g2T zlj7*|Fob~FbD()!!95!@Mtv49g6$s#-^lju@W{jP)4O5M?!tM~R5g9-RHXzXMnGeu zy0Nx4HBMevr}&K+q4ErJ%=C42rqMS~F9RPy2;_w`idwkA)qQTp#}05)00D@hpv5(P zu4mtW`su1aU-rBzbl^Z3It*TZ$=&kzx)CYuet$0Q+O=x5Zp#*>Y}PURojX<80Ez63 zS;GK3Pq%Wy%H&7A5&RrYnWW}8EM->ddd?egRRX615G zYR+5;)nvc6qO=?F10|7wg9nx22!)ysYTO_-|Xw+S%Fm#-N4$P4=7tG8nN(_=!l#F6=(zGN!PT|E~Tl5ABiaI z-%~2b??Hprgic*w*tZXc4OcGY`X=~jyGwqlMh{1gQU+f`1GKajc-PiKd%OBwSEs&h zkwgvwB*jC>Vd!`RACx`Tn49lVt$;2V>BYm@ZWinSwP?dyn)>cjtD1kW8+D!*0hEpvdg*QC#x0!KxW;;?c4pqA2kXt zy;L>(^X94Z9UW?DITlqmK_&y$)k+xvcI@y59~`rQ0dyRL4?sL>0Urdi)+?#24RGtdK>s)Y2;;~c;3^&KEa8$=-MDZzrzA{E-c#`j45Sdo<5a=9Xpls^{ZE9 zEq)R%$-1%i_0ZCy6lB;iIOP;|-fJc>cU%>Rlbivd9`cq#y%GF8e=GRjc}w3SX3G|3 z%=z)P3cGht;rPfA^*wpAGRku4Hf>VJu^0>=rdo<4N8pj)!T9m2|29qaS(Tl4xah)c z-p#OeTd_RW<544(SK&n;C-C!mECu>x_X!D;xQ-oIh8bN+*Okwo3*FkfRfTr<>!*Ot zxsvne!=gpXeOtK_Hh&0XPg7IKd-tkAqUqUh9_LhCVX7<~1saP`&7_>0A0 zTeAXq_;C2j9dPkX#k2V%rC2Y&tc=2WbJY38PpNSQAMlApVA2F{c}u?cUJiafkJSzI z=2Q9x5kbv#v7L9#Jme=FO^>pMSnmkUe{pcTiQO{QYUu+>GOB(RK{K;qLd&Pu<_?VtH>WvMqpc; z8s*E)_T|Vl)g;i~y=u&%r3HR-pBnqWW}Y(q?tc*0uMY+vkTcHpmp3dOH{eqYz7Mz~{76RT+NrhPwCT2z=)`=`TpQE+8!UxwNmpt}J~aRE@p)W_aNR zRjXI7gf(kn`gAprQ&*Q=k6#PzN0sutzgiiEIh$hMTzKz&wP-}jaNrApyyT)_c?0kL zcm&`2UA7nCU{*@Ot*t7gD;KUkVg!8UE6N*KvQ&8pFTSW2fYj8eA>BkmwE#}O)m3WX zCpY>S27G`ilMCYnUh)Rf@d&<6hOT-6<$#}~KmXajvKN#qcU zrGyW+ln#DX9C_sx{_+OV@eF=W5bIcg2YI&u9>V~kBW#jMc=lN}u5VqrbMkQb+i$>z zjj(Z}0@xW7=vGcx@Buk{7WA$2mN$sH5q!CO59Yd!(6SG?rv-WN5VEQoqqYy2CbBbu zkOEO(i#BX9`UU5pH997;N(H}5T|iL5Zp?G(wr+)c?}dg&xa1NTn%#b-x*E=ysy>FH zX7aZ0P{!Sko%XqXXBh$DGi5TIb%wXRK~!Pz&3D(ppOzz9_aRIJP1g{~G-i8ezJ5s{ zeKh6X5PAP!Ou}L1!tWJFTMaHMykOb>#(e@D;vQY^tt?1 zc==DoWdwmgcrfzXx!&>yQH8*l8#W^sFGV|a5M9sSt3WMG0f^XpUIE175t0dqOAKHb zr0#nh{mj!5RUv~~oc({72ZG84U!wZ>r=EsSUjawj;P;E+`s>_d_;NJ;T;(PnI#k#> zD-u;>1}j#&msQsndF##D(63_yzI<{CV$B+~&a@qH2MJ9tI;Tf8G+o0qibLvUXD8eC1L ze-(v#4eCAoSrnQKe26~9S5p&An06QL!(Akl4&0=h64psn{7BXNMAV2{s0lxKk z=T3O^aRu<`(Q4-Jq#?>isPC&3!!Xo%!Oq=k=5fO&$NqVavikKy-u8JF2iL>k%MBY5 zix;C+=@84-_O!=VbPf_i6g^6z3G|4L;oK<&Fq?M<%47c>3_g_V1#|^`YuaQ|Mfo%} zb;;Ui$PnZgZq6tXPJ`Tx*54?>lrIS;7-Uadqdrqk)70CM+UUwQ1p;Q+s@Hh>q8 zu7KCo{8OhWgD>i_AS8&&1Yhpii}=lbs@7``6qA|o;{eXQSrVFXwFS)m2bIju?$ZfA zF5q|B4eU+e*Hj~~o()qcd-D#WGQl@re-r)Hmy2tCj*=m3Kj3F5M4}ogr!kmHBagHr z>gx*UT)?*BSJE#M0QQzs*5U0Il6?8%zHcq#gp^+hgRo(u`8fbDQXQbgBDlPP)> z=KcfdIRz*M{IcD^-T=N3Fkw9Ml9~3nzMcgCp~uknHhVVPK(_fWg}+Z)q1?iZb9?*! z2VwMxih&PZ9SQ7C@Z)iqayoMQIpweY?`j@EKDr2P???Wws{}eT-q+p8xplpRG+i%x zzkzw+FnS>P*2}^7T>eO4cYt5t7eGg;Pj?KdDb0%E}AAH?Fi^VCWvbJ+OYWwk)QVsP+V}-3@tiotQ#rDVJP*;a+Y*Y&x zhn^I?dZ#B1zE@sD-?lM0WX7cQ+7E#(fDoW*0@I>cGL;)DE)o2)yZ{sOOSu3BH$aPr zFIrWlR_x^V+wao{X=J>Id&|M3Cu{!BJ?L+&@EppuQG2TNa*W)IKKw~&ntcsMDn%gp zP6}`Y{9Aw^(si|u&n1@>cI*g}te1n2VIm&9AL1Uao|RIDGXAW^8WJ-ehsFj(B!WD2 z812Ym^`@^}gX;D2DhFx0z_7CS>vr8J4}Q5`fFIS=zzsLpqi%vE>+Rr6kaztIEe!ak zgf{ySwJ~A@;*KvMB8B|9Ra)k|s}YYsg{BLn%SfLa6>aVri{#}Dq!8dkxe8EU54YZ` zB7B^s`Uq4q^)UG6{STq*AqR7gr1FNJG)&B!Z$wP>-c&`LH5JaBg846Z!Qu8$ML4}q z5sg+9dS)sG9#V17H6B8T13Y!o36GXu2@wFTtEU%NKkb{pi~mjUirM1;wss zZU?XcQqw@;o<*<%IQd+5S>eS>o{7R;^3K!4HUGaKKx_UWc$yj@kx_16mW=8e#D(XT zB%l7>{}sFuCB~N1@KdVGQfvYjlhq=e*5ybkD~3`hKTC^OUA9# znTGb_cs=P7+7(tlar%VdCuqqps;dxn9y`612|kpf0QLP;7m(v#N$LUc<<8xR2Od!K z_|Xt<9;n-FPeQ`OGw|y*g5=XQWC<*^@nhV(DUWi(KArGEp}FnYjz{pHdl7BzyWaEo zZj_PGmh^t(I3Ntu{b_`dPaZfF>~L5O#|dM7ulw`yz7#$vw6USU$?r8Vxobhqqm_3l zR4Vwt_%&MMu=hNEQ3h0#-;oZ~bs<0|QxLbfXCdV?|ME`oG=qheKGC57C4ujqHoyz8 zWZb?Z?_K8i*>~G-UymU5NU&Ai6X4(Va|M1F-yW22e<-2+{4hmn0{Q6T(&dxD^4Efs zWh;{y&=2io%PQvzfe&4s3kc@lHQrswBk%gZXu>_jx`@)Is`05(Lb?=bO&=hW$ z-j2S0wOXBHpyu5TslHQY(Mp_3k|quK&!1z|)FP*zj+izTbRBa`GrYeBv3?^W6FzVx zSNo$^Us@vg*+biT?<{2mg@%*Go~MUK`2OpDvhCloAx%S1bRb{*3+D4LsZ(XL%47_* zA%loa_t-$oNo9Z!zB`46JQqYg1ity$Q)tH${4B|gf!XG=mvSjQq{K8#V)L&KH(FUH z_)v*WqI~o8P|eR6Xz#pNdcF#i0>7inV`Z6)i9U7=`q^iMD71X=q5Kvqn0hjR^OyG_ z!o=@&Bgu3I^GHX@(ZOzH2#wespYvab0HMM6TOeM77f`~D_3(VYW_?}lF(8>pWov!~ zz|WXOZkUHQI3Q@m6MVZ2GGJCHq!-Y8!3USvIR|f33gqCyaQ?Z_eiZTYE6Qr`DoHRq z639fz0jCgToIITPWfumNTN&^nlo!yu!OtDqR6t5hErL05JogoA!3Pji zCn2UzD!z~}%DpUc(G1K%1JUk(I9Lg!L?+Uhoym&y^+oJ2n~64Us&D!ELyz<2Q04au z4#lf-;0G7wpGk~A4f9*yKzdp4rituGVjOJ8>_~JA_~w{VXxGp2PS8!@Ls#Yk$`zm& zfuAEWs1f;tZxzBEq(ml_TW1_R+HJKSz^ti3|GPWA6I1|vzoeyyg_j{fm-6_@;9FFQ znflhjKmP-1EvjmJdj~R|DX;L5BmwQ~cX*HXl>@%hJ}P@C*o9eWu9eE;CxdTMWy%+i zq5t^%n3KkLC+>wJCyqyq815}k?$G0WaUM?=o>bagKv=Go$m1u2Z&4vLNr~LK8}q}h zaJ0jAN&ouo$g3{*$XFRN(a^s5IZxU0haTsP^Vok#>3PvcUEeFXJMuucfiK(IFz&ez zt$8~FnP0pqV=?5JQ_yd{0U{B!>tf`s2mRDh_KTGS-!X_+0WY9LRC*!!a>s7O`hcZaSrW-4#siPp3 zL;KmkVvZSAhMbaAGEFL}Ru}1$$JvK_D-M1*77)q{kk%i;)C<7}Fdlq7baXfX@2#*8(&AAmLo-X@2!W1A<>7QirNvn~1l{q6$xa`4TqA0dKTFAvhr zn&K;`7&QW;u8wrdpz~-d3%qxHfIf91+VFx)*)8BpiEQ0xOJiVc^J4940{|FOZnPDU z&VX~_LoWv(DKS>Br}JovL}!{z+EDB5La;JMjYRaV3rr_xo=-ZJ36@XOiG6l%A)iA| z?*cr2cw~{S`yscXWY&n!NV&-?m)A(3Od7_zxO0W?wq~`fXOPf-)PvvyWLCWkfN7Zd zE!c$sP1n$bKxo+y*?s&3aMBPW-&z=|7}4LkS(ZCRFTVh7nA%&ZyTAu9H*B`0kw6N$ z&MQ~G1(1cOECF`3wJmoh7Mnf{7TS+`7<_Zz0nCqzU$r8o>aWvjgH$p@vNKJhGeshi z!JK^s`agaBr#Vv0fj(t2|Ley^UoVCxdV+r3CLYwCJp0RTb5K3)`owmp#=BJQh|x5%=_y@ zWz)}_M)kja4}JWpC6^-)9P&vB@!J-lk3OaQ!3WH@S3@dkOPWv^O3TMaUhSL& zj~2411F_=u(z<|S1U`UtY5uLG4Q{0BI}54$+HL;9m_FqgTbezSM(18ZAQ-unyXWWQQd$@wE+fBrdC?Kf~~{=q{5 zz}^Y~diwLXFOCQ?+m@)R8hPiJVDP|T!M*P1I0oM>T~C59ckLy8_r1tmOk?(XM#|^v zmp}7aviqdqQTrh{ASBm+m~Zae_YEo8XS>qbiMan^IC$s;_(er_Gx+-tlD_A^i@=wX z*0(zL{ViGC0=W822irXY^ZaGc>}*LTZwD;fV@f!D81Y~K1ABblZR^gzr1aTLA=7#M z_?Uoi?#|ZygNN7bj@F^Sozpf+m;1fkPAK<8w`N5zS&;E=;zpplo zD^~%)W)SA=0j=Yv+wQ8?BVQ{LPzdE6eEL$)jT29R@AwfG{A7~Ml4TfwdacOd14x+W zJq@oe`5pz}O#*5^girvm8H57Rhl0NO=G*S777_cDnauv{SC5>1B}|!QTYrB7e8-P4 z;7f`5_WNX>e74Z!JMwlK<}aqKSn|DHkf8+dp)>^mr3Cp;+k!8AyEYpAC&-1_TQyU{ zph3u)=fmVl$au)DRIT($20xL+e0w#6oiwxKlN~8QRIa2h_R!QqenwS|H^G9{c!|h{0 z<@I7IF^_ga`%z>|Yf&VR7x)<|pIh19^1o-l^ZHI4;D-f1MRR=)T)cEGL2q5FF`>XHKFnRqKg{H_*Ebe2yxj0C{GGZUGz$U^(aZ{YfY3 z^KAp2E;RRUR8a*0TWbK}f&Zi`g7e|~DS|qvFklr|02}k-JzP%!?@nHdpnh~CNZqOc zMTPlp>U)B6)SZAksYeyy1ob{Twwvsqpkq$|AM*Vy)j-fNXaE2J07*qoM6N<$f(zKx AL;wH) diff --git a/spark-update-tool/resources/default_icon.svg b/spark-update-tool/resources/default_icon.svg deleted file mode 100644 index 7c9cb42d..00000000 --- a/spark-update-tool/resources/default_icon.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/spark-update-tool/resources/down_arrow.svg b/spark-update-tool/resources/down_arrow.svg deleted file mode 100644 index 4989662c..00000000 --- a/spark-update-tool/resources/down_arrow.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/spark-update-tool/resources/spark-update-tool.svg b/spark-update-tool/resources/spark-update-tool.svg deleted file mode 100644 index 3d21d816..00000000 --- a/spark-update-tool/resources/spark-update-tool.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/spark-update-tool/src/appdelegate.cpp b/spark-update-tool/src/appdelegate.cpp deleted file mode 100644 index 0c930657..00000000 --- a/spark-update-tool/src/appdelegate.cpp +++ /dev/null @@ -1,322 +0,0 @@ -#include "appdelegate.h" -#include -#include -#include -#include -#include -#include -#include -#include - -AppDelegate::AppDelegate(QObject *parent) - : QStyledItemDelegate(parent), m_downloadManager(new DownloadManager(this)), m_installProcess(nullptr) { - connect(m_downloadManager, &DownloadManager::downloadFinished, this, - [this](const QString &packageName, bool success) { - if (m_downloads.contains(packageName)) { - m_downloads[packageName].isDownloading = false; - // 不要提前设置 isInstalled - emit updateDisplay(packageName); - qDebug() << (success ? "下载完成:" : "下载失败:") << packageName; - if (success) { - enqueueInstall(packageName); // 安装完成后再设置 isInstalled - } - } - }); - - connect(m_downloadManager, &DownloadManager::downloadProgress, this, - [this](const QString &packageName, int progress) { - if (m_downloads.contains(packageName)) { - m_downloads[packageName].progress = progress; - qDebug()<save(); - - if (option.state & QStyle::State_Selected) - painter->fillRect(option.rect, option.palette.highlight()); - else - painter->fillRect(option.rect, QColor("#F3F4F6")); - - QFont boldFont = option.font; - boldFont.setBold(true); - QFont normalFont = option.font; - - QString name = index.data(Qt::DisplayRole).toString(); - QString currentVersion = index.data(Qt::UserRole + 2).toString(); - QString newVersion = index.data(Qt::UserRole + 3).toString(); - QString iconPath = index.data(Qt::UserRole + 4).toString(); - QString size = index.data(Qt::UserRole + 5).toString(); - QString description = index.data(Qt::UserRole + 6).toString(); - - QRect rect = option.rect; - int margin = 10, spacing = 6, iconSize = 40; - - QRect iconRect(rect.left() + margin, rect.top() + (rect.height() - iconSize) / 2, iconSize, iconSize); - QIcon(iconPath).paint(painter, iconRect); - - int textX = iconRect.right() + margin; - int textWidth = rect.width() - textX - 100; - - QRect nameRect(textX, rect.top() + margin, textWidth, 20); - painter->setFont(boldFont); - painter->setPen(QColor("#333333")); - painter->drawText(nameRect, Qt::AlignLeft | Qt::AlignVCenter, name); - - QRect versionRect(textX, nameRect.bottom() + spacing, textWidth, 20); - painter->setFont(normalFont); - painter->setPen(QColor("#888888")); - painter->drawText(versionRect, Qt::AlignLeft | Qt::AlignVCenter, - QString("当前版本: %1 → 新版本: %2").arg(currentVersion, newVersion)); - - QRect descRect(textX, versionRect.bottom() + spacing, textWidth, 40); - painter->setFont(normalFont); - painter->setPen(QColor("#AAAAAA")); - painter->drawText(descRect, Qt::TextWordWrap, - QString("包大小:%1 MB").arg(QString::number(size.toDouble() / (1024 * 1024), 'f', 2))); - - QString packageName = index.data(Qt::UserRole + 1).toString(); - bool isDownloading = m_downloads.contains(packageName) && m_downloads[packageName].isDownloading; - int progress = m_downloads.value(packageName, DownloadInfo{0, false}).progress; - bool isInstalled = m_downloads.value(packageName).isInstalled; - bool isInstalling = m_downloads.value(packageName).isInstalling; - - if (isDownloading) { - QRect progressRect(rect.right() - 270, rect.top() + (rect.height() - 20) / 2, 150, 20); - QStyleOptionProgressBar progressBarOption; - progressBarOption.rect = progressRect; - progressBarOption.minimum = 0; - progressBarOption.maximum = 100; - progressBarOption.progress = progress; - progressBarOption.text = QString("%1%").arg(progress); - progressBarOption.textVisible = true; - QApplication::style()->drawControl(QStyle::CE_ProgressBar, &progressBarOption, painter); - - // 修改后的取消按钮绘制代码 - QRect buttonRect(rect.right() - 80, rect.top() + (rect.height() - 30) / 2, 70, 30); - painter->setPen(Qt::NoPen); - painter->setBrush(QColor("#ff4444")); // 红色背景 - painter->drawRoundedRect(buttonRect, 4, 4); // 圆角矩形 - - painter->setPen(Qt::white); // 白色文字 - painter->setFont(option.font); - painter->drawText(buttonRect, Qt::AlignCenter, "取消"); - } else if (isInstalling) { - // 安装中:显示转圈和文字 - QRect spinnerRect(option.rect.right() - 80, option.rect.top() + (option.rect.height() - 30) / 2, 30, 30); - int angle = (m_spinnerTimer.elapsed() / 10) % 360; - QPen pen(QColor("#2563EB"), 3); - painter->setPen(pen); - painter->setRenderHint(QPainter::Antialiasing, true); - QRectF arcRect = spinnerRect.adjusted(3, 3, -3, -3); - painter->drawArc(arcRect, angle * 16, 120 * 16); // 120度弧 - - QRect textRect(option.rect.right() - 120, option.rect.top() + (option.rect.height() - 30) / 2, 110, 30); - painter->setPen(QColor("#2563EB")); - painter->setFont(option.font); - painter->drawText(textRect, Qt::AlignLeft | Qt::AlignVCenter, "正在安装中"); - } else { - QRect buttonRect(option.rect.right() - 80, option.rect.top() + (option.rect.height() - 30) / 2, 70, 30); - painter->setPen(Qt::NoPen); - if (isInstalled) { - painter->setBrush(QColor("#10B981")); - painter->drawRoundedRect(buttonRect, 4, 4); - painter->setPen(Qt::white); - painter->drawText(buttonRect, Qt::AlignCenter, "已安装"); - } else if (m_downloads.contains(packageName) && !m_downloads[packageName].isDownloading) { - // 下载完成,按钮绿色,样式不变 - painter->setBrush(QColor("#10B981")); - painter->drawRoundedRect(buttonRect, 4, 4); - painter->setPen(Qt::white); - painter->drawText(buttonRect, Qt::AlignCenter, "下载完成"); - // 不需要特殊处理样式,交互在 editorEvent 控制 - } else { - painter->setBrush(QColor("#e9effd")); - painter->drawRoundedRect(buttonRect, 4, 4); - painter->setPen(QColor("#2563EB")); - painter->drawText(buttonRect, Qt::AlignCenter, "更新"); - } - } - - painter->restore(); -} - -QSize AppDelegate::sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const { - return QSize(option.rect.width(), 110); -} - -bool AppDelegate::editorEvent(QEvent *event, QAbstractItemModel *model, - const QStyleOptionViewItem &option, const QModelIndex &index) { - if (event->type() == QEvent::MouseButtonRelease) { - QMouseEvent *mouseEvent = static_cast(event); - QRect rect = option.rect; - QString packageName = index.data(Qt::UserRole + 1).toString(); - - if (m_downloads.contains(packageName) && m_downloads[packageName].isDownloading) { - QRect cancelButtonRect(rect.right() - 70, rect.top() + (rect.height() - 20) / 2, 60, 20); - if (cancelButtonRect.contains(mouseEvent->pos())) { - m_downloadManager->cancelDownload(packageName); - m_downloads.remove(packageName); - emit updateDisplay(packageName); - return true; - } - } else { - QRect buttonRect(rect.right() - 80, rect.top() + (rect.height() - 30) / 2, 70, 30); - if (buttonRect.contains(mouseEvent->pos())) { - // 判断是否为“下载完成”状态,如果是则不响应点击 - if (m_downloads.contains(packageName) && !m_downloads[packageName].isDownloading) { - // “下载完成”状态,按钮失效,点击无效 - return false; - } - QString downloadUrl = index.data(Qt::UserRole + 7).toString(); - QString outputPath = QString("%1/%2.metalink").arg(QDir::tempPath(), packageName); - - m_downloads[packageName] = {0, true}; - m_downloadManager->startDownload(packageName, downloadUrl, outputPath); - emit updateDisplay(packageName); - return true; - } - } - } - - return QStyledItemDelegate::editorEvent(event, model, option, index); -} - -void AppDelegate::startDownloadForAll() { - if (!m_model) return; - for (int row = 0; row < m_model->rowCount(); ++row) { - QModelIndex index = m_model->index(row, 0); - QString packageName = index.data(Qt::UserRole + 1).toString(); - if (m_downloads.contains(packageName) && (m_downloads[packageName].isDownloading || m_downloads[packageName].isInstalled)) - continue; // 跳过正在下载或已安装的 - QString downloadUrl = index.data(Qt::UserRole + 7).toString(); - QString outputPath = QString("%1/%2.metalink").arg(QDir::tempPath(), packageName); - m_downloads[packageName] = {0, true, false}; - m_downloadManager->startDownload(packageName, downloadUrl, outputPath); - emit updateDisplay(packageName); - } -} - -// 新增:安装队列相关实现 -void AppDelegate::enqueueInstall(const QString &packageName) { - m_installQueue.enqueue(packageName); - if (!m_isInstalling) { - startNextInstall(); - } -} - -void AppDelegate::startNextInstall() { - if (m_installQueue.isEmpty()) { - m_isInstalling = false; - m_installingPackage.clear(); - return; - } - m_isInstalling = true; - QString packageName = m_installQueue.dequeue(); - m_installingPackage = packageName; - m_downloads[packageName].isInstalling = true; - emit updateDisplay(packageName); - - // 查找 /tmp 下以包名开头的 .deb 文件 - QDir tempDir(QDir::tempPath()); - QStringList debs = tempDir.entryList(QStringList() << QString("%1_*.deb").arg(packageName), QDir::Files); - QString debPath; - if (!debs.isEmpty()) { - debPath = tempDir.absoluteFilePath(debs.first()); - } else { - debs = tempDir.entryList(QStringList() << QString("%1*.deb").arg(packageName), QDir::Files); - if (!debs.isEmpty()) { - debPath = tempDir.absoluteFilePath(debs.first()); - } - } - - if (debPath.isEmpty()) { - qWarning() << "未找到deb文件,包名:" << packageName; - m_downloads[packageName].isInstalling = false; - emit updateDisplay(packageName); - m_installingPackage.clear(); - startNextInstall(); - return; - } - - m_installProcess = new QProcess(this); - - // 新增:准备安装日志文件 - QString logPath = QString("/tmp/%1_install.log").arg(packageName); - QFile *logFile = new QFile(logPath, m_installProcess); - if (logFile->open(QIODevice::Append | QIODevice::Text)) { - // 设置权限为777 - QFile::setPermissions(logPath, QFile::ReadOwner | QFile::WriteOwner | QFile::ExeOwner | - QFile::ReadGroup | QFile::WriteGroup | QFile::ExeGroup | - QFile::ReadOther | QFile::WriteOther | QFile::ExeOther); - connect(m_installProcess, &QProcess::readyReadStandardOutput, this, [this, packageName, logFile]() { - QByteArray out = m_installProcess->readAllStandardOutput(); - logFile->write(out); - logFile->flush(); - QString text = QString::fromLocal8Bit(out); - qDebug().noquote() << text; - // 检查“软件包已安装”关键字 - if (text.contains(QStringLiteral("软件包已安装"))) { - m_downloads[packageName].isInstalling = false; - m_downloads[packageName].isInstalled = true; - emit updateDisplay(packageName); - } - }); - connect(m_installProcess, &QProcess::readyReadStandardError, this, [this, logFile]() { - QByteArray err = m_installProcess->readAllStandardError(); - logFile->write(err); - logFile->flush(); - qDebug().noquote() << QString::fromLocal8Bit(err); - }); - connect(m_installProcess, QOverload::of(&QProcess::finished), - this, [this, packageName, logFile](int exitCode, QProcess::ExitStatus status) { - if (logFile) logFile->close(); - m_downloads[packageName].isInstalling = false; - if (exitCode == 0) { - m_downloads[packageName].isInstalled = true; // 安装成功 - } - emit updateDisplay(packageName); - m_installProcess->deleteLater(); - m_installProcess = nullptr; - m_installingPackage.clear(); - startNextInstall(); - }); - } else { - // 日志文件无法打开时,仍然要连接原有信号 - connect(m_installProcess, &QProcess::readyReadStandardOutput, this, [this, packageName]() { - QByteArray out = m_installProcess->readAllStandardOutput(); - QString text = QString::fromLocal8Bit(out); - qDebug().noquote() << text; - if (text.contains(QStringLiteral("软件包已安装"))) { - m_downloads[packageName].isInstalling = false; - m_downloads[packageName].isInstalled = true; - emit updateDisplay(packageName); - } - }); - connect(m_installProcess, &QProcess::readyReadStandardError, this, [this]() { - QByteArray err = m_installProcess->readAllStandardError(); - qDebug().noquote() << QString::fromLocal8Bit(err); - }); - connect(m_installProcess, QOverload::of(&QProcess::finished), - this, [this, packageName](int /*exitCode*/, QProcess::ExitStatus /*status*/) { - emit updateDisplay(packageName); - m_installProcess->deleteLater(); - m_installProcess = nullptr; - m_installingPackage.clear(); - startNextInstall(); - }); - } - - // 注意参数顺序:deb路径在前,--no-create-desktop-entry在后 - QStringList args; - args << debPath << "--no-create-desktop-entry"; - m_installProcess->start("ssinstall", args); -} diff --git a/spark-update-tool/src/appdelegate.h b/spark-update-tool/src/appdelegate.h deleted file mode 100644 index 0545155e..00000000 --- a/spark-update-tool/src/appdelegate.h +++ /dev/null @@ -1,46 +0,0 @@ -#pragma once - -#include -#include -#include -#include -#include -#include "downloadmanager.h" - -struct DownloadInfo { - int progress = 0; - bool isDownloading = false; - bool isInstalled = false; - bool isInstalling = false; // 新增:标记是否正在安装 -}; - -class AppDelegate : public QStyledItemDelegate { - Q_OBJECT -public: - explicit AppDelegate(QObject *parent = nullptr); - - void setModel(QAbstractItemModel *model); - - void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const override; - QSize sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const override; - bool editorEvent(QEvent *event, QAbstractItemModel *model, - const QStyleOptionViewItem &option, const QModelIndex &index) override; - void startDownloadForAll(); - -signals: - void updateDisplay(const QString &packageName); - -private: - DownloadManager *m_downloadManager; - QHash m_downloads; - QAbstractItemModel *m_model = nullptr; - - QQueue m_installQueue; - bool m_isInstalling = false; - QProcess *m_installProcess = nullptr; - QString m_installingPackage; // 当前正在安装的包名 - QElapsedTimer m_spinnerTimer; // 用于转圈动画 - - void enqueueInstall(const QString &packageName); - void startNextInstall(); -}; diff --git a/spark-update-tool/src/applistmodel.cpp b/spark-update-tool/src/applistmodel.cpp deleted file mode 100644 index 31e244a9..00000000 --- a/spark-update-tool/src/applistmodel.cpp +++ /dev/null @@ -1,62 +0,0 @@ -#include "applistmodel.h" - -AppListModel::AppListModel(QObject *parent) : QAbstractListModel(parent) {} - -int AppListModel::rowCount(const QModelIndex &parent) const -{ - if (parent.isValid()) - return 0; - return m_data.size(); -} - -QVariant AppListModel::data(const QModelIndex &index, int role) const -{ - if (!index.isValid() || index.row() >= m_data.size()) - return QVariant(); - - const QVariantMap &map = m_data.at(index.row()); // 直接访问 QVariantMap - switch (role) { - case Qt::DisplayRole: - return map.value("name"); - case Qt::UserRole + 1: // 包名 - return map.value("package"); - case Qt::UserRole + 2: // 当前版本 - return map.value("current_version"); - case Qt::UserRole + 3: // 新版本 - return map.value("new_version"); - case Qt::UserRole + 4: // 图标路径 - return map.value("icon"); - case Qt::UserRole + 5: // 文件大小 - return map.value("size"); - case Qt::UserRole + 6: // 描述 - return map.value("description"); - case Qt::UserRole + 7: // 下载 URL - return map.value("download_url"); // 返回下载 URL - default: - return QVariant(); - } -} - -void AppListModel::setUpdateData(const QJsonArray &updateInfo) -{ - beginResetModel(); - m_data.clear(); // 清空 QList - - for (const auto &item : updateInfo) { - QJsonObject obj = item.toObject(); - QVariantMap map; - map["package"] = obj["package"].toString(); - map["name"] = obj["name"].toString(); - map["current_version"] = obj["current_version"].toString(); - map["new_version"] = obj["new_version"].toString(); - map["icon"] = obj["icon"].toString(); - map["size"] = obj["size"].toString(); - map["download_url"] = obj["download_url"].toString(); // 确保设置下载 URL - m_data.append(map); // 添加到 QList - - qDebug() << "设置到模型的包名:" << map["package"].toString(); - qDebug() << "设置到模型的下载 URL:" << map["download_url"].toString(); // 检查设置的数据 - } - - endResetModel(); -} diff --git a/spark-update-tool/src/applistmodel.h b/spark-update-tool/src/applistmodel.h deleted file mode 100644 index 2fb36c0d..00000000 --- a/spark-update-tool/src/applistmodel.h +++ /dev/null @@ -1,26 +0,0 @@ -#ifndef APPLISTMODEL_H -#define APPLISTMODEL_H - -#include -#include -// 添加 QJsonObject 头文件 -#include - -class AppListModel : public QAbstractListModel -{ - Q_OBJECT -public: - explicit AppListModel(QObject *parent = nullptr); - - // 重写方法 - int rowCount(const QModelIndex &parent = QModelIndex()) const override; - QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override; - - // 设置更新数据 - void setUpdateData(const QJsonArray &data); - -private: - QList m_data; // 修改类型为 QList -}; - -#endif // APPLISTMODEL_H diff --git a/spark-update-tool/src/aptssupdater.cpp b/spark-update-tool/src/aptssupdater.cpp deleted file mode 100644 index c4bd9060..00000000 --- a/spark-update-tool/src/aptssupdater.cpp +++ /dev/null @@ -1,398 +0,0 @@ -#include "aptssupdater.h" -#include -#include -#include -#include -#include - -aptssUpdater::aptssUpdater(QWidget *parent) - : QWidget(parent) -{ - packageName = getUpdateablePackages(); -} - -QStringList aptssUpdater::getUpdateablePackages() -{ - QStringList packageDetails; - QProcess process; - QString command = R"(env LANGUAGE=en_US /usr/bin/apt -c /opt/durapps/spark-store/bin/apt-fast-conf/aptss-apt.conf list --upgradable -o Dir::Etc::sourcelist="/opt/durapps/spark-store/bin/apt-fast-conf/sources.list.d/sparkstore.list" -o Dir::Etc::sourceparts="/dev/null" -o APT::Get::List-Cleanup="0" | awk 'NR>1')"; - - process.start("bash", QStringList() << "-c" << command); - if (!process.waitForFinished()) { - qWarning() << "Process failed to finish."; - return packageDetails; - } - - QString output = process.readAllStandardOutput(); - QStringList lines = output.split('\n', Qt::SkipEmptyParts); - - // 创建临时文件 - QTemporaryFile tempFile; - tempFile.setAutoRemove(false); - if (tempFile.open()) { - QTextStream stream(&tempFile); - - for (const QString &line : lines) { - QRegularExpression regex(R"(([\w\-\+\.]+)/\S+\s+([^\s]+)\s+\S+\s+\[upgradable from: ([^\]]+)\])"); - QRegularExpressionMatch match = regex.match(line); - if (match.hasMatch()) { - QString name = match.captured(1); - QString newVersion = match.captured(2); - QString oldVersion = match.captured(3); - - // 检查版本是否相同,相同则跳过 - if (newVersion == oldVersion) { - qDebug() << "跳过版本相同的包:" << name << "(" << oldVersion << "→" << newVersion << ")"; - continue; - } - - // 写入内存列表 - packageDetails << QString("%1: %2 → %3").arg(name, oldVersion, newVersion); - - // 写入临时文件(原始数据) - stream << name << "|" << oldVersion << "|" << newVersion << "\n"; - } - } - tempFile.close(); - m_tempFilePath = tempFile.fileName(); - qDebug()<< "临时文件路径:" << m_tempFilePath; - - } else { - qWarning() << "无法创建临时文件"; - } - - return packageDetails; -} - - -QStringList aptssUpdater::getPackageSizes() -{ - QStringList packageDetails; - QProcess process; - - // 获取可更新包名列表 - QStringList updateablePackages; - for (const QString &pkgInfo : packageName) { - updateablePackages << pkgInfo.section(":", 0, 0).trimmed(); - } - - foreach (const QString &packageName, updateablePackages) { - // 构建新命令(包含包名参数) - QString command = QString("apt download %1 --print-uris -c /opt/durapps/spark-store/bin/apt-fast-conf/aptss-apt.conf " - "-o Dir::Etc::sourcelist=\"/opt/durapps/spark-store/bin/apt-fast-conf/sources.list.d/sparkstore.list\" " - "-o Dir::Etc::sourceparts=\"/dev/null\"").arg(packageName); - - process.start("bash", QStringList() << "-c" << command); - if (!process.waitForFinished()) { - qWarning() << "获取包信息失败:" << packageName; - continue; - } - - QString output = process.readAllStandardOutput(); - // 使用正则匹配所有信息 - // 调整正则表达式匹配分组 - QRegularExpression regex(R"('([^']+)'\s+(\S+)\s+(\d+)\s+SHA512:([^\s]+))"); // 分组1:URL 分组2:文件名 分组3:大小 分组4:SHA512 - QRegularExpressionMatch match = regex.match(output); - - if (match.hasMatch()) { - QString url = match.captured(1); - QString fileName = match.captured(2); - QString size = match.captured(3); - QString sha512 = match.captured(4); - - // 调整字段顺序:包名 | 大小 | URL | SHA512 - packageDetails << QString("%1: %2|%3|%4").arg(packageName, size, url, sha512); - } - } - - qDebug() << "完整包信息:" << packageDetails; - return packageDetails; -} - - - - - -QStringList aptssUpdater::getDesktopAppNames() -{ - QStringList appNames; - QProcess dpkgProcess; - - // 获取当前系统语言环境 - QString lang = QLocale().name().replace("_", "-"); - - // 遍历所有可更新包(复用已有的临时文件数据) - QStringList packages = packageName; - - foreach (const QString &package, packages) { - QString packageName = package.split(":")[0]; - QString finalName = packageName; // 默认使用包名 - - // 获取包文件列表 - dpkgProcess.start("dpkg", QStringList() << "-L" << packageName); - dpkgProcess.waitForFinished(); - QStringList files = QString(dpkgProcess.readAllStandardOutput()).split('\n', Qt::SkipEmptyParts); - - // 先检查常规应用目录 - QStringList regularDesktopFiles = files.filter("/usr/share/applications/"); - QString regularAppName; - if (!regularDesktopFiles.isEmpty()) { - checkDesktopFiles(regularDesktopFiles, regularAppName, lang, packageName); - } - - // 如果常规目录没有找到,再检查特殊目录 - if (regularAppName.isEmpty()) { - QStringList specialDesktopFiles = files.filter(QRegularExpression(QString("/opt/apps/%1/entries/applications").arg(packageName))); - QString specialAppName; - if (!specialDesktopFiles.isEmpty()) { - checkDesktopFiles(specialDesktopFiles, specialAppName, lang, packageName); - if (!specialAppName.isEmpty()) { - finalName = specialAppName; - } - } - } else { - finalName = regularAppName; - } - - // 输出格式为[软件名|包名] - appNames << QString("[%1|%2]").arg(finalName, packageName); - } - qDebug()<< "应用名称列表:" << appNames; - return appNames; -} - - -bool aptssUpdater::checkDesktopFiles(const QStringList &desktopFiles, QString &appName, const QString &lang, const QString &packageName) -{ - QString lastValidName; - QRegularExpression noDisplayRe("^NoDisplay=(true|True)"); - QRegularExpression nameRe("^Name\\[?" + lang + "?\\]?=(.*)"); - QRegularExpression nameOrigRe("^Name=(.*)"); - - foreach (const QString &filePath, desktopFiles) { - if (!filePath.endsWith(".desktop")) continue; - - QFile file(filePath); - if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) continue; - - bool skip = false; - QString currentName; - - QTextStream in(&file); - while (!in.atEnd()) { - QString line = in.readLine().trimmed(); - - // 检查NoDisplay属性 - if (line.startsWith("NoDisplay=")) { - if (noDisplayRe.match(line).hasMatch()) { - skip = true; - break; - } - } - - // 优先匹配本地化名称 - if (currentName.isEmpty()) { - QRegularExpressionMatch match = nameRe.match(line); - if (match.hasMatch()) { - currentName = match.captured(1); - continue; - } - - // 匹配原始名称 - match = nameOrigRe.match(line); - if (match.hasMatch()) { - currentName = match.captured(1); - } - } - } - - if (!skip && !currentName.isEmpty()) { - lastValidName = currentName; - } - } - - // 处理最终的有效名称 - if (!lastValidName.isEmpty()) { - appName = lastValidName; // 直接赋值而不是使用<< - return true; - } - - // 回退到包名 - appName = packageName; - return false; -} - -QStringList aptssUpdater::getPackageIcons() -{ - QStringList packageIcons; - QProcess dpkgProcess; - - // 遍历所有可更新包 - QStringList packages = packageName; - - foreach (const QString &package, packages) { - QString packageName = package.split(":")[0]; - QString iconPath = ":/resources/default_icon.svg"; // 默认图标 - - // 获取包文件列表 - dpkgProcess.start("dpkg", QStringList() << "-L" << packageName); - dpkgProcess.waitForFinished(); - QStringList files = QString(dpkgProcess.readAllStandardOutput()).split('\n', Qt::SkipEmptyParts); - - // 查找.desktop文件 - QStringList desktopFiles = files.filter(QRegularExpression("/(usr/share|opt/apps)/.*\\.desktop$")); - - // 从.desktop文件中提取图标 - foreach (const QString &desktopFile, desktopFiles) { - QFile file(desktopFile); - if (file.open(QIODevice::ReadOnly | QIODevice::Text)) { - QTextStream in(&file); - while (!in.atEnd()) { - QString line = in.readLine().trimmed(); - if (line.startsWith("Icon=")) { - QString iconName = line.mid(5).trimmed(); - - // 处理相对图标名(如Icon=vscode) - if (!iconName.contains('/')) { - // 查找标准图标路径 - QStringList iconPaths = { - QString("/usr/share/pixmaps/%1.png").arg(iconName), - QString("/usr/share/icons/hicolor/48x48/apps/%1.png").arg(iconName), - QString("/usr/share/icons/hicolor/scalable/apps/%1.svg").arg(iconName), - QString("/opt/apps/%1/entries/icons/hicolor/48x48/apps/%2.png").arg(packageName, iconName) - }; - - foreach (const QString &path, iconPaths) { - if (QFile::exists(path)) { - iconPath = path; - break; - } - } - } else { - // 已经是绝对路径 - if (QFile::exists(iconName)) { - iconPath = iconName; - } - } - break; - } - } - file.close(); - } - } - - // 如果.desktop中没有找到图标,尝试直接查找包中的图标文件 - if (iconPath == ":/resources/default_icon.svg") { - QStringList iconFiles = files.filter(QRegularExpression("/(usr/share/pixmaps|usr/share/icons|opt/apps/.*/entries/icons)/.*\\.(png|svg)$")); - if (!iconFiles.isEmpty()) { - iconPath = iconFiles.first(); - } - } - - qDebug() << "包名:" << packageName << "图标路径:" << iconPath; - packageIcons << QString("%1: %2").arg(packageName, iconPath); - } - - return packageIcons; -} - - -QJsonArray aptssUpdater::getUpdateInfoAsJson() -{ - QJsonArray jsonArray; - - // 获取所有需要的信息 - QStringList sizes = getPackageSizes(); - QStringList names = getDesktopAppNames(); - QStringList icons = getPackageIcons(); - - // 创建包名到各种信息的映射 - QHash> packageInfo; - - // 解析包版本信息 - for (const QString &pkg : packageName) { - QStringList parts = pkg.split(": "); - if (parts.size() >= 2) { - QString packageName = parts[0]; - QStringList versions = parts[1].split(" → "); - if (versions.size() == 2) { - packageInfo[packageName]["current_version"] = versions[0]; - packageInfo[packageName]["new_version"] = versions[1]; - } - } - } - - // 解析包详细信息(新增部分) - for (const QString &sizeInfo : sizes) { - QStringList parts = sizeInfo.split(": "); - if (parts.size() == 2) { - QString packageName = parts[0]; - QStringList details = parts[1].split("|"); - if (details.size() == 3) { // 现在包含大小|URL|SHA512 - packageInfo[packageName]["size"] = details[0]; - packageInfo[packageName]["url"] = details[1]; - packageInfo[packageName]["sha512"] = details[2]; - } - } - } - - // 解析应用名称信息 - for (const QString &nameInfo : names) { - if (nameInfo.startsWith("[") && nameInfo.endsWith("]")) { - QString content = nameInfo.mid(1, nameInfo.length() - 2); - QStringList parts = content.split("|"); - if (parts.size() == 2) { - QString displayName = parts[0]; - QString packageName = parts[1]; - packageInfo[packageName]["display_name"] = displayName; - } - } - } - - // 解析图标信息 - for (const QString &iconInfo : icons) { - QStringList parts = iconInfo.split(": "); - if (parts.size() == 2) { - QString packageName = parts[0]; - packageInfo[packageName]["icon"] = parts[1].trimmed(); - } - } - - // 构建JSON数组 - for (const QString &packageName : packageInfo.keys()) { - QJsonObject jsonObj; - jsonObj["package"] = packageName; - - // 使用显示名称(如果有),否则使用包名 - if (packageInfo[packageName].contains("display_name")) { - jsonObj["name"] = packageInfo[packageName]["display_name"]; - } else { - jsonObj["name"] = packageName; - } - - jsonObj["current_version"] = packageInfo[packageName]["current_version"]; - jsonObj["new_version"] = packageInfo[packageName]["new_version"]; - jsonObj["icon"] = packageInfo[packageName]["icon"]; - jsonObj["ignored"] = false; // 默认不忽略 - - // 如果有大小信息也加入 - if (packageInfo[packageName].contains("size")) { - jsonObj["size"] = packageInfo[packageName]["size"]; - } - - // 在构建JSON对象时添加新字段(在jsonObj中添加): - if (packageInfo[packageName].contains("url")) { - jsonObj["download_url"] = packageInfo[packageName]["url"]; - qDebug() << "生成的下载 URL:" << packageInfo[packageName]["url"]; // 检查生成的 URL - } else { - qWarning() << "未找到下载 URL,包名:" << packageName; - jsonObj["download_url"] = ""; // 设置为空字符串以避免崩溃 - } - jsonObj["sha512"] = packageInfo[packageName]["sha512"]; - jsonArray.append(jsonObj); - } - qDebug()< -#include -#include -#include -#include -#include -class aptssUpdater : public QWidget -{ - Q_OBJECT -public: - explicit aptssUpdater(QWidget *parent = nullptr); - - QStringList getUpdateablePackages(); // 查询可更新包列表及更新内容 - QStringList getPackageSizes(); // 获取每个包的大小 - QStringList getDesktopAppNames(); // 获取桌面应用名称列表 - QStringList getPackageIcons(); // 获取包图标列表 - QJsonArray getUpdateInfoAsJson(); // 获取更新信息的 JSON 格式 - QString m_tempFilePath; -signals: -private: - bool checkDesktopFiles(const QStringList &desktopFiles, QString &appName, const QString &lang, const QString &packageName); - QStringList packageName; -}; - -#endif // APTSSUPDATER_H \ No newline at end of file diff --git a/spark-update-tool/src/downloadmanager.cpp b/spark-update-tool/src/downloadmanager.cpp deleted file mode 100644 index 97803249..00000000 --- a/spark-update-tool/src/downloadmanager.cpp +++ /dev/null @@ -1,117 +0,0 @@ -#include "downloadmanager.h" -#include -#include -#include -#include -#include - -DownloadManager::DownloadManager(QObject *parent) : QObject(parent) -{ - cleanupTempFiles(); -} - -void DownloadManager::startDownload(const QString &packageName, const QString &url, const QString &outputPath) -{ - if (m_processes.contains(packageName)) { - qWarning() << packageName << " is already downloading."; - return; - } - - QString metalinkUrl = url + ".metalink"; - QFileInfo fileInfo(outputPath); - - QStringList arguments = { - "--enable-rpc=false", - "--console-log-level=warn", - "--summary-interval=1", - "--allow-overwrite=true", - "--dir=" + fileInfo.absolutePath(), - "--out=" + fileInfo.fileName(), - metalinkUrl - }; - - QProcess *process = new QProcess(this); - m_processes.insert(packageName, process); - - // 新增:准备日志文件 - QString logPath = QString("/tmp/%1_download.log").arg(packageName); - QFile *logFile = new QFile(logPath, process); - if (logFile->open(QIODevice::Append | QIODevice::Text)) { - // 设置权限为777 - QFile::setPermissions(logPath, QFile::ReadOwner | QFile::WriteOwner | QFile::ExeOwner | - QFile::ReadGroup | QFile::WriteGroup | QFile::ExeGroup | - QFile::ReadOther | QFile::WriteOther | QFile::ExeOther); - connect(process, &QProcess::readyReadStandardOutput, this, [this, packageName, process, logFile]() { - while (process->canReadLine()) { - QString line = QString::fromUtf8(process->readLine()).trimmed(); - // 写入日志 - logFile->write(line.toUtf8() + '\n'); - logFile->flush(); - QRegularExpression regex(R"(\((\d+)%\))"); - QRegularExpressionMatch match = regex.match(line); - if (match.hasMatch()) { - int progress = match.captured(1).toInt(); - emit downloadProgress(packageName, progress); - } - } - }); - connect(process, &QProcess::readyReadStandardError, this, [process, logFile]() { - QByteArray err = process->readAllStandardError(); - logFile->write(err); - logFile->flush(); - }); - } - - connect(process, QOverload::of(&QProcess::finished), - this, [this, packageName, outputPath, logFile](int exitCode, QProcess::ExitStatus status) { - bool success = (exitCode == 0 && status == QProcess::NormalExit); - if (!success) { - qWarning() << "Download failed for" << packageName << "exit code:" << exitCode; - } - - removeAria2Files(outputPath); // 清理残留 .aria2 - emit downloadFinished(packageName, success); - - if (logFile) logFile->close(); - - QProcess *proc = m_processes.take(packageName); - if (proc) proc->deleteLater(); - }); - - process->start("aria2c", arguments); -} - -void DownloadManager::cancelDownload(const QString &packageName) -{ - if (!m_processes.contains(packageName)) return; - - QProcess *process = m_processes.take(packageName); - if (process) { - process->kill(); // 立即终止 - process->waitForFinished(3000); // 最多等待3秒 - process->deleteLater(); - } - - emit downloadFinished(packageName, false); // 显式通知取消 - -} - -void DownloadManager::removeAria2Files(const QString &filePath) -{ - QString ariaFile = filePath + ".aria2"; - QFile::remove(ariaFile); -} - -bool DownloadManager::isDownloading(const QString &packageName) const -{ - return m_processes.contains(packageName); -} - -void DownloadManager::cleanupTempFiles() -{ - QDir tempDir(QDir::tempPath()); - QStringList leftovers = tempDir.entryList(QStringList() << "*.aria2", QDir::Files); - for (const QString &f : leftovers) { - tempDir.remove(f); - } -} diff --git a/spark-update-tool/src/downloadmanager.h b/spark-update-tool/src/downloadmanager.h deleted file mode 100644 index 0614368a..00000000 --- a/spark-update-tool/src/downloadmanager.h +++ /dev/null @@ -1,28 +0,0 @@ -#ifndef DOWNLOADMANAGER_H -#define DOWNLOADMANAGER_H - -#include -#include -#include - -class DownloadManager : public QObject -{ - Q_OBJECT -public: - explicit DownloadManager(QObject *parent = nullptr); - void startDownload(const QString &packageName, const QString &url, const QString &outputPath); - void cancelDownload(const QString &packageName); - bool isDownloading(const QString &packageName) const; - -signals: - void downloadProgress(const QString &packageName, int progress); - void downloadFinished(const QString &packageName, bool success); - -private: - void cleanupTempFiles(); - void removeAria2Files(const QString &filePath); - - QMap m_processes; -}; - -#endif // DOWNLOADMANAGER_H diff --git a/spark-update-tool/src/icons.qrc b/spark-update-tool/src/icons.qrc deleted file mode 100644 index f81e1f88..00000000 --- a/spark-update-tool/src/icons.qrc +++ /dev/null @@ -1,8 +0,0 @@ - - - ../resources/down_arrow.svg - ../resources/default_icon.svg - ../resources/spark-update-tool.svg - ../resources/128*128/spark-update-tool.png - - diff --git a/spark-update-tool/src/main.cpp b/spark-update-tool/src/main.cpp deleted file mode 100644 index a3df5a43..00000000 --- a/spark-update-tool/src/main.cpp +++ /dev/null @@ -1,86 +0,0 @@ -#include "mainwindow.h" -#include -#include -#include -#include // for geteuid -#include // for getenv -#include // For debugging output - -bool isRoot() { - return geteuid() == 0; -} - -bool elevateToRoot() { - QString program = QCoreApplication::applicationFilePath(); - qDebug() << "Current application path:" << program; - - QByteArray display = qgetenv("DISPLAY"); - QByteArray xauthority = qgetenv("XAUTHORITY"); - - QStringList args; - args << "env" - << "DISPLAY=" + display - << "XAUTHORITY=" + xauthority - << program; - - QProcess process; - process.setProgram("pkexec"); - process.setArguments(args); - - qDebug() << "Attempting to elevate using pkexec with arguments:" << args; - - process.start(); - if (!process.waitForStarted(5000)) { - qDebug() << "Failed to start pkexec."; - return false; - } - - // 阻塞等待提权进程退出(比如主程序窗口关闭) - if (!process.waitForFinished(-1)) { // 等待直到新进程退出 - qDebug() << "pkexec process waitForFinished failed."; - return false; - } - - int exitCode = process.exitCode(); - QProcess::ExitStatus exitStatus = process.exitStatus(); - - qDebug() << "pkexec exit code:" << exitCode; - qDebug() << "pkexec exit status:" << exitStatus; - qDebug() << "pkexec stderr:" << process.readAllStandardError(); - - return (exitStatus == QProcess::NormalExit && exitCode == 0); -} - -int main(int argc, char *argv[]) -{ - // 必须在 QGuiApplication 实例创建之前调用 - // QGuiApplication::setHighDpiScaleFactorRoundingPolicy(Qt::HighDpiScaleFactorRoundingPolicy::PassThrough); - - QApplication a(argc, argv); - a.setWindowIcon(QIcon(":/resources/128*128/spark-update-tool.png")); - if (!isRoot()) { - qDebug() << "Not running as root. Attempting to elevate..."; - if (!elevateToRoot()) { - qDebug() << "Elevation failed or pkexec command was not executed successfully."; - QMessageBox::critical(nullptr, - "权限不足", - "提权失败!\n\n您的系统可能不支持 `pkexec` 或 `polkit` 配置不正确," - "或者您取消了授权。\n\n请尝试使用 `sudo` 命令运行此程序:" - "\n\n在终端中输入:\n`sudo " + QCoreApplication::applicationName() + "`"); - return 0; // 提权失败,退出程序 - } else { - // 如果 elevateToRoot 返回 true,说明 pkexec 命令本身执行成功 - // 但这并不意味着原始程序以 root 权限启动了 - // 因为 elevateToRoot 启动的是一个新的进程,当前进程应该退出 - // 否则会并行运行两个程序实例 - qDebug() << "pkexec command executed successfully (new process likely started). Exiting current process."; - return 0; // 当前非root进程退出 - } - } else { - qDebug() << "Running as root."; - } - - MainWindow w; - w.show(); - return a.exec(); -} \ No newline at end of file diff --git a/spark-update-tool/src/mainwindow.cpp b/spark-update-tool/src/mainwindow.cpp deleted file mode 100644 index 102bda6f..00000000 --- a/spark-update-tool/src/mainwindow.cpp +++ /dev/null @@ -1,268 +0,0 @@ -#include "mainwindow.h" -#include "./ui_mainwindow.h" -#include -#include -#include -#include // 新增 -#include // 新增 -#include -#include -MainWindow::MainWindow(QWidget *parent) - : QMainWindow(parent) - , ui(new Ui::MainWindow) - , m_model(new AppListModel(this)) - , m_delegate(new AppDelegate(this)) -{ - QIcon icon(":/resources/128*128/spark-update-tool.png"); - setWindowIcon(icon); - QProgressDialog *progressDialog = new QProgressDialog("正在与服务器通信,获取更新信息中...", QString(), 0, 0, this); - progressDialog->setWindowModality(Qt::ApplicationModal); - progressDialog->setCancelButton(nullptr); - progressDialog->setWindowTitle("请稍候"); - progressDialog->setMinimumDuration(0); - progressDialog->setWindowFlags(progressDialog->windowFlags() & ~Qt::WindowCloseButtonHint); // 禁用关闭按钮 - progressDialog->show(); - //异步执行runAptssUpgrade - QFutureWatcher *watcher = new QFutureWatcher(this); - connect(watcher, &QFutureWatcher::finished, this, [=]() { - progressDialog->close(); - progressDialog->deleteLater(); - watcher->deleteLater(); - ui->setupUi(this); - QIcon icon(":/resources/128*128/spark-update-tool.png"); - setWindowIcon(icon); - // 创建 QListView 并设置父控件为 ui->appWidget - listView = new QListView(ui->appWidget); - listView->setModel(m_model); - listView->setItemDelegate(m_delegate); - - // 新增:确保 delegate 拥有 model 指针 - m_delegate->setModel(m_model); - - // 设置 QListView 填充 ui->appWidget - QVBoxLayout *layout = new QVBoxLayout(ui->appWidget); - layout->addWidget(listView); - layout->setContentsMargins(0, 0, 0, 0); - connect(m_delegate, &AppDelegate::updateDisplay, this, [=](const QString &packageName) { - for (int i = 0; i < m_model->rowCount(); ++i) { - QModelIndex index = m_model->index(i); - if (index.data(Qt::UserRole + 1).toString() == packageName) { - m_model->dataChanged(index, index); // 刷新该行 - break; - } - } - }); - - // 新增:点击“更新全部”按钮批量下载 - connect(ui->updatePushButton, &QPushButton::clicked, this, [=](){ - qDebug()<<"更新全部按钮被点击"; - m_delegate->startDownloadForAll(); - }); - - checkUpdates(); - // 新增:监听搜索框文本变化 - connect(ui->searchPlainTextEdit, &QPlainTextEdit::textChanged, this, [=]() { - QString keyword = ui->searchPlainTextEdit->toPlainText(); - filterAppsByKeyword(keyword); - }); - initStyle(); - - // 确保搜索框内容为空,placeholder 能显示 - ui->searchPlainTextEdit->clear(); - }); - - // 启动异步任务 - watcher->setFuture(QtConcurrent::run([this](){ - runAptssUpgrade(); - })); - QScreen *screen = QGuiApplication::screenAt(QCursor::pos()); - if (!screen) screen = QGuiApplication::primaryScreen(); - QRect screenGeometry = screen->geometry(); - int x = screenGeometry.x() + (screenGeometry.width() - this->width()) / 2; - int y = screenGeometry.y() + (screenGeometry.height() - this->height()) / 2; - this->move(x, y); -} -//初始化控件样式 -void MainWindow::initStyle() -{ - //设置窗口标题 - this->setWindowTitle("软件更新中心"); - - //查询框样式 - ui->searchPlainTextEdit->setStyleSheet(R"( - QPlainTextEdit { - background-color: #FFFFFF; - border: 1px solid #E5E7EB; - border-radius: 4px; - padding-top: 8px; - padding-bottom: 8px; - font-size: 9px; - line-height: 1.4; - color: #9CA3AF; - } - QPlainTextEdit[placeholderText]:empty { - color: #9CA3AF; - } - )"); - - ui->searchPlainTextEdit->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff); - ui->searchPlainTextEdit->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); - - //筛选框样式 - ui->FilterComboBox->setStyleSheet(R"( - QComboBox { - background-color: #FFFFFF; - border: 1px solid #E5E7EB; - border-radius: 4px; - color: #4B5563; - padding: 4px 8px; - } - - QComboBox::drop-down { - border: none; - width: 20px; - } - - QComboBox::down-arrow { - image: url(:/resources/down_arrow.svg); - width: 12px; - height: 16px; - } - QComboBox QAbstractItemView { - background-color: #FFFFFF; - border: 1px solid #E5E7EB; - color: #4B5563; - selection-background-color: #F3F4F6; - selection-color: #111827; - } - )"); - - //更新软件按钮样式 - ui->updatePushButton->setStyleSheet(R"( - QPushButton { - background-color: #2563EB; - color: #FFFFFF; - border: none; - border-radius: 4px; - font-size: 14px; - padding: 6px 12px; - text-align: center; - } - - QPushButton:hover { - background-color: #1D4ED8; /* 深一点的 hover 效果,可选 */ - } - - QPushButton:pressed { - background-color: #1E40AF; /* 按下效果,可选 */ - } - - QPushButton:disabled { - background-color: #A5B4FC; - color: #F9FAFB; - } - )"); - - //设置背景填充颜色 - ui->backgroundWidget->setStyleSheet(R"( - QWidget { - background-color: #FFFFFF; - border-radius: 12px; - } - )"); - - //设置主背景颜色 - this->setStyleSheet("background-color: #F8FAFC;"); - - // 添加滚动条样式 - this->setStyleSheet(R"( - QScrollBar:vertical { - background: #F3F4F6; - width: 8px; - margin: 0px; - } - QScrollBar::handle:vertical { - background: #D1D5DB; - border-radius: 4px; - min-height: 30px; - } - QScrollBar::handle:vertical:hover { - background: #9CA3AF; - } - QScrollBar::add-line:vertical, QScrollBar::sub-line:vertical { - background: none; - height: 0px; - } - - QScrollBar:horizontal { - background: #F3F4F6; - height: 8px; - margin: 0px; - } - QScrollBar::handle:horizontal { - background: #D1D5DB; - border-radius: 4px; - min-width: 30px; - } - QScrollBar::handle:horizontal:hover { - background: #9CA3AF; - } - )"); -} -void MainWindow::checkUpdates() -{ - aptssUpdater updater; - QJsonArray updateInfo = updater.getUpdateInfoAsJson(); - m_allApps = updateInfo; // 保存所有应用数据 - m_model->setUpdateData(updateInfo); - - for (const auto &item : updateInfo) { - QJsonObject obj = item.toObject(); - qDebug() << "模型设置的包名:" << obj["package"].toString(); - qDebug() << "模型设置的下载 URL:" << obj["download_url"].toString(); // 检查模型数据 - } -} - -// 新增:根据关键字过滤应用 -void MainWindow::filterAppsByKeyword(const QString &keyword) -{ - if (keyword.trimmed().isEmpty()) { - m_model->setUpdateData(m_allApps); - return; - } - QJsonArray filtered; - for (const auto &item : m_allApps) { - QJsonObject obj = item.toObject(); - // 可根据需要匹配更多字段 - QString name = obj.value("name").toString(); - QString package = obj.value("package").toString(); - if (name.contains(keyword, Qt::CaseInsensitive) || - package.contains(keyword, Qt::CaseInsensitive)) { - filtered.append(item); - } - } - m_model->setUpdateData(filtered); -} - -void MainWindow::runAptssUpgrade() -{ - QProcess process; - QStringList args; - args << "sudo" <<"aptss" << "ssupdate"; - process.start("sudo", args); - if (!process.waitForStarted(5000)) { - QMessageBox::warning(this, "升级失败", "无法启动 sudo aptss ssupdate"); - return; - } - process.write("n\n"); - process.closeWriteChannel(); - process.waitForFinished(-1); - if (process.exitCode() != 0) { - QMessageBox::warning(this, "升级失败", "执行 sudo aptss ssupdate 失败,请检查系统环境。"); - } -} - -MainWindow::~MainWindow() -{ - delete ui; -} diff --git a/spark-update-tool/src/mainwindow.h b/spark-update-tool/src/mainwindow.h deleted file mode 100644 index d754b5f7..00000000 --- a/spark-update-tool/src/mainwindow.h +++ /dev/null @@ -1,36 +0,0 @@ -#ifndef MAINWINDOW_H -#define MAINWINDOW_H - -#include -#include "aptssupdater.h" -#include "applistmodel.h" -#include "appdelegate.h" -#include -#include // 添加头文件 -#include -QT_BEGIN_NAMESPACE -namespace Ui { -class MainWindow; -} -QT_END_NAMESPACE - -class MainWindow : public QMainWindow -{ - Q_OBJECT - -public: - MainWindow(QWidget *parent = nullptr); - ~MainWindow(); - -private: - Ui::MainWindow *ui; - void checkUpdates(); - void initStyle(); - void runAptssUpgrade(); - AppListModel *m_model; - AppDelegate *m_delegate; - QListView *listView; // 声明 QListView 指针 - QJsonArray m_allApps; // 新增:保存所有应用数据 - void filterAppsByKeyword(const QString &keyword); // 新增:搜索过滤函数声明 -}; -#endif // MAINWINDOW_H diff --git a/spark-update-tool/src/mainwindow.ui b/spark-update-tool/src/mainwindow.ui deleted file mode 100644 index a53a4b88..00000000 --- a/spark-update-tool/src/mainwindow.ui +++ /dev/null @@ -1,256 +0,0 @@ - - - MainWindow - - - - 0 - 0 - 1440 - 858 - - - - MainWindow - - - - - - - - 0 - - - 0 - - - 0 - - - 0 - - - 0 - - - - - - Noto Sans Vai - 22 - - - - 软件更新中心 - - - - - - - Qt::Orientation::Horizontal - - - - 1245 - 20 - - - - - - - - - - - - - - - 0 - 0 - - - - - 0 - - - 0 - - - 0 - - - 0 - - - 0 - - - - - - 320 - 38 - - - - - 320 - 38 - - - - - 0 - - - 0 - - - 0 - - - 0 - - - 0 - - - - - - 200 - 38 - - - - - - - 81.000000000000000 - - - 搜索软件... - - - - - - - - - - Qt::Orientation::Horizontal - - - - 40 - 20 - - - - - - - - - 214 - 40 - - - - - 214 - 40 - - - - - - 0 - 0 - 102 - 38 - - - - - 102 - 38 - - - - - 102 - 38 - - - - - - - Qt::LayoutDirection::LeftToRight - - - QComboBox::SizeAdjustPolicy::AdjustToContentsOnFirstShow - - - - 按名称 - - - - - - - 118 - 0 - 96 - 40 - - - - 更新全部 - - - - - - - - - - - true - - - - 0 - 0 - - - - - - - - - - - - - 0 - 0 - 1440 - 23 - - - - - - - diff --git a/update-tool/.gitignore b/update-tool/.gitignore deleted file mode 100644 index 79c9ac74..00000000 --- a/update-tool/.gitignore +++ /dev/null @@ -1,62 +0,0 @@ -build -.vscode -.cache -CMakeLists.txt.user -CMakeLists.txt.user.* -obj-x86_64-linux-gnu -# C++ objects and libs -*.slo -*.lo -*.o -*.a -*.la -*.lai -*.so -*.dll -*.dylib - -# Qt-es -object_script.*.Release -object_script.*.Debug -*_plugin_import.cpp -/.qmake.cache -/.qmake.stash -*.pro.user -*.pro.user.* -*.qbs.user -*.qbs.user.* -*.moc -moc_*.cpp -moc_*.h -qrc_*.cpp -ui_*.h -*.qmlc -*.jsc -Makefile* -*build-* - -# Qt unit tests -target_wrapper.* - -# Qt qm files -translations/*.qm - -# QtCreator -*.autosave - -# QtCreator Qml -*.qmlproject.user -*.qmlproject.user.* - -# QtCreator CMake -CMakeLists.txt.user* -build - -# Debian dpkg-buildpackage -debian/*.debhelper* -debian/files -debian/*.substvars -debian/spark-update-tool - -.vscode/* -src/spark-update-tool diff --git a/update-tool/CMakeLists.txt b/update-tool/CMakeLists.txt deleted file mode 100644 index 6c624b41..00000000 --- a/update-tool/CMakeLists.txt +++ /dev/null @@ -1,75 +0,0 @@ -cmake_minimum_required(VERSION 3.16) - -project(spark-update-tool VERSION 0.1 LANGUAGES CXX) - -set(CMAKE_AUTOUIC ON) -set(CMAKE_AUTOMOC ON) -set(CMAKE_AUTORCC ON) - -set(CMAKE_CXX_STANDARD 17) -set(CMAKE_CXX_STANDARD_REQUIRED ON) - -find_package(QT NAMES Qt6 Qt5 REQUIRED COMPONENTS Widgets Network Concurrent) -find_package(Qt${QT_VERSION_MAJOR} REQUIRED COMPONENTS Widgets Network Concurrent) - -set(PROJECT_SOURCES - src/main.cpp - src/mainwindow.cpp - src/mainwindow.h - src/mainwindow.ui -) - -if(${QT_VERSION_MAJOR} GREATER_EQUAL 6) - qt_add_executable(spark-update-tool - MANUAL_FINALIZATION - ${PROJECT_SOURCES} - src/aptssupdater.h src/aptssupdater.cpp - src/icons.qrc - src/appdelegate.h src/appdelegate.cpp - src/applistmodel.h src/applistmodel.cpp - src/downloadmanager.h src/downloadmanager.cpp - ) -# Define target properties for Android with Qt 6 as: -# set_property(TARGET spark-update-tool APPEND PROPERTY QT_ANDROID_PACKAGE_SOURCE_DIR -# ${CMAKE_CURRENT_SOURCE_DIR}/android) -# For more information, see https://doc.qt.io/qt-6/qt-add-executable.html#target-creation -else() - if(ANDROID) - add_library(spark-update-tool SHARED - ${PROJECT_SOURCES} - ) -# Define properties for Android with Qt 5 after find_package() calls as: -# set(ANDROID_PACKAGE_SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/android") - else() - add_executable(spark-update-tool - ${PROJECT_SOURCES} - ) - endif() -endif() - -target_link_libraries(spark-update-tool PRIVATE Qt${QT_VERSION_MAJOR}::Widgets Qt${QT_VERSION_MAJOR}::Network Qt${QT_VERSION_MAJOR}::Concurrent) - -# Qt for iOS sets MACOSX_BUNDLE_GUI_IDENTIFIER automatically since Qt 6.1. -# If you are developing for iOS or macOS you should consider setting an -# explicit, fixed bundle identifier manually though. -if(${QT_VERSION} VERSION_LESS 6.1.0) - set(BUNDLE_ID_OPTION MACOSX_BUNDLE_GUI_IDENTIFIER com.example.spark-update-tool) -endif() -set_target_properties(spark-update-tool PROPERTIES - ${BUNDLE_ID_OPTION} - MACOSX_BUNDLE_BUNDLE_VERSION ${PROJECT_VERSION} - MACOSX_BUNDLE_SHORT_VERSION_STRING ${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR} - MACOSX_BUNDLE TRUE - WIN32_EXECUTABLE TRUE -) - -include(GNUInstallDirs) -install(TARGETS spark-update-tool - BUNDLE DESTINATION . - LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} - RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} -) - -if(QT_VERSION_MAJOR EQUAL 6) - qt_finalize_executable(spark-update-tool) -endif() diff --git a/update-tool/LICENSE b/update-tool/LICENSE deleted file mode 100644 index 3877ae0a..00000000 --- a/update-tool/LICENSE +++ /dev/null @@ -1,674 +0,0 @@ - GNU GENERAL PUBLIC LICENSE - Version 3, 29 June 2007 - - Copyright (C) 2007 Free Software Foundation, Inc. - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - - Preamble - - The GNU General Public License is a free, copyleft license for -software and other kinds of works. - - The licenses for most software and other practical works are designed -to take away your freedom to share and change the works. By contrast, -the GNU General Public License is intended to guarantee your freedom to -share and change all versions of a program--to make sure it remains free -software for all its users. We, the Free Software Foundation, use the -GNU General Public License for most of our software; it applies also to -any other work released this way by its authors. You can apply it to -your programs, too. - - When we speak of free software, we are referring to freedom, not -price. Our General Public Licenses are designed to make sure that you -have the freedom to distribute copies of free software (and charge for -them if you wish), that you receive source code or can get it if you -want it, that you can change the software or use pieces of it in new -free programs, and that you know you can do these things. - - To protect your rights, we need to prevent others from denying you -these rights or asking you to surrender the rights. Therefore, you have -certain responsibilities if you distribute copies of the software, or if -you modify it: responsibilities to respect the freedom of others. - - For example, if you distribute copies of such a program, whether -gratis or for a fee, you must pass on to the recipients the same -freedoms that you received. You must make sure that they, too, receive -or can get the source code. And you must show them these terms so they -know their rights. - - Developers that use the GNU GPL protect your rights with two steps: -(1) assert copyright on the software, and (2) offer you this License -giving you legal permission to copy, distribute and/or modify it. - - For the developers' and authors' protection, the GPL clearly explains -that there is no warranty for this free software. For both users' and -authors' sake, the GPL requires that modified versions be marked as -changed, so that their problems will not be attributed erroneously to -authors of previous versions. - - Some devices are designed to deny users access to install or run -modified versions of the software inside them, although the manufacturer -can do so. This is fundamentally incompatible with the aim of -protecting users' freedom to change the software. The systematic -pattern of such abuse occurs in the area of products for individuals to -use, which is precisely where it is most unacceptable. Therefore, we -have designed this version of the GPL to prohibit the practice for those -products. If such problems arise substantially in other domains, we -stand ready to extend this provision to those domains in future versions -of the GPL, as needed to protect the freedom of users. - - Finally, every program is threatened constantly by software patents. -States should not allow patents to restrict development and use of -software on general-purpose computers, but in those that do, we wish to -avoid the special danger that patents applied to a free program could -make it effectively proprietary. To prevent this, the GPL assures that -patents cannot be used to render the program non-free. - - The precise terms and conditions for copying, distribution and -modification follow. - - TERMS AND CONDITIONS - - 0. Definitions. - - "This License" refers to version 3 of the GNU General Public License. - - "Copyright" also means copyright-like laws that apply to other kinds of -works, such as semiconductor masks. - - "The Program" refers to any copyrightable work licensed under this -License. Each licensee is addressed as "you". "Licensees" and -"recipients" may be individuals or organizations. - - To "modify" a work means to copy from or adapt all or part of the work -in a fashion requiring copyright permission, other than the making of an -exact copy. The resulting work is called a "modified version" of the -earlier work or a work "based on" the earlier work. - - A "covered work" means either the unmodified Program or a work based -on the Program. - - To "propagate" a work means to do anything with it that, without -permission, would make you directly or secondarily liable for -infringement under applicable copyright law, except executing it on a -computer or modifying a private copy. Propagation includes copying, -distribution (with or without modification), making available to the -public, and in some countries other activities as well. - - To "convey" a work means any kind of propagation that enables other -parties to make or receive copies. Mere interaction with a user through -a computer network, with no transfer of a copy, is not conveying. - - An interactive user interface displays "Appropriate Legal Notices" -to the extent that it includes a convenient and prominently visible -feature that (1) displays an appropriate copyright notice, and (2) -tells the user that there is no warranty for the work (except to the -extent that warranties are provided), that licensees may convey the -work under this License, and how to view a copy of this License. If -the interface presents a list of user commands or options, such as a -menu, a prominent item in the list meets this criterion. - - 1. Source Code. - - The "source code" for a work means the preferred form of the work -for making modifications to it. "Object code" means any non-source -form of a work. - - A "Standard Interface" means an interface that either is an official -standard defined by a recognized standards body, or, in the case of -interfaces specified for a particular programming language, one that -is widely used among developers working in that language. - - The "System Libraries" of an executable work include anything, other -than the work as a whole, that (a) is included in the normal form of -packaging a Major Component, but which is not part of that Major -Component, and (b) serves only to enable use of the work with that -Major Component, or to implement a Standard Interface for which an -implementation is available to the public in source code form. A -"Major Component", in this context, means a major essential component -(kernel, window system, and so on) of the specific operating system -(if any) on which the executable work runs, or a compiler used to -produce the work, or an object code interpreter used to run it. - - The "Corresponding Source" for a work in object code form means all -the source code needed to generate, install, and (for an executable -work) run the object code and to modify the work, including scripts to -control those activities. However, it does not include the work's -System Libraries, or general-purpose tools or generally available free -programs which are used unmodified in performing those activities but -which are not part of the work. For example, Corresponding Source -includes interface definition files associated with source files for -the work, and the source code for shared libraries and dynamically -linked subprograms that the work is specifically designed to require, -such as by intimate data communication or control flow between those -subprograms and other parts of the work. - - The Corresponding Source need not include anything that users -can regenerate automatically from other parts of the Corresponding -Source. - - The Corresponding Source for a work in source code form is that -same work. - - 2. Basic Permissions. - - All rights granted under this License are granted for the term of -copyright on the Program, and are irrevocable provided the stated -conditions are met. This License explicitly affirms your unlimited -permission to run the unmodified Program. The output from running a -covered work is covered by this License only if the output, given its -content, constitutes a covered work. This License acknowledges your -rights of fair use or other equivalent, as provided by copyright law. - - You may make, run and propagate covered works that you do not -convey, without conditions so long as your license otherwise remains -in force. You may convey covered works to others for the sole purpose -of having them make modifications exclusively for you, or provide you -with facilities for running those works, provided that you comply with -the terms of this License in conveying all material for which you do -not control copyright. Those thus making or running the covered works -for you must do so exclusively on your behalf, under your direction -and control, on terms that prohibit them from making any copies of -your copyrighted material outside their relationship with you. - - Conveying under any other circumstances is permitted solely under -the conditions stated below. Sublicensing is not allowed; section 10 -makes it unnecessary. - - 3. Protecting Users' Legal Rights From Anti-Circumvention Law. - - No covered work shall be deemed part of an effective technological -measure under any applicable law fulfilling obligations under article -11 of the WIPO copyright treaty adopted on 20 December 1996, or -similar laws prohibiting or restricting circumvention of such -measures. - - When you convey a covered work, you waive any legal power to forbid -circumvention of technological measures to the extent such circumvention -is effected by exercising rights under this License with respect to -the covered work, and you disclaim any intention to limit operation or -modification of the work as a means of enforcing, against the work's -users, your or third parties' legal rights to forbid circumvention of -technological measures. - - 4. Conveying Verbatim Copies. - - You may convey verbatim copies of the Program's source code as you -receive it, in any medium, provided that you conspicuously and -appropriately publish on each copy an appropriate copyright notice; -keep intact all notices stating that this License and any -non-permissive terms added in accord with section 7 apply to the code; -keep intact all notices of the absence of any warranty; and give all -recipients a copy of this License along with the Program. - - You may charge any price or no price for each copy that you convey, -and you may offer support or warranty protection for a fee. - - 5. Conveying Modified Source Versions. - - You may convey a work based on the Program, or the modifications to -produce it from the Program, in the form of source code under the -terms of section 4, provided that you also meet all of these conditions: - - a) The work must carry prominent notices stating that you modified - it, and giving a relevant date. - - b) The work must carry prominent notices stating that it is - released under this License and any conditions added under section - 7. This requirement modifies the requirement in section 4 to - "keep intact all notices". - - c) You must license the entire work, as a whole, under this - License to anyone who comes into possession of a copy. This - License will therefore apply, along with any applicable section 7 - additional terms, to the whole of the work, and all its parts, - regardless of how they are packaged. This License gives no - permission to license the work in any other way, but it does not - invalidate such permission if you have separately received it. - - d) If the work has interactive user interfaces, each must display - Appropriate Legal Notices; however, if the Program has interactive - interfaces that do not display Appropriate Legal Notices, your - work need not make them do so. - - A compilation of a covered work with other separate and independent -works, which are not by their nature extensions of the covered work, -and which are not combined with it such as to form a larger program, -in or on a volume of a storage or distribution medium, is called an -"aggregate" if the compilation and its resulting copyright are not -used to limit the access or legal rights of the compilation's users -beyond what the individual works permit. Inclusion of a covered work -in an aggregate does not cause this License to apply to the other -parts of the aggregate. - - 6. Conveying Non-Source Forms. - - You may convey a covered work in object code form under the terms -of sections 4 and 5, provided that you also convey the -machine-readable Corresponding Source under the terms of this License, -in one of these ways: - - a) Convey the object code in, or embodied in, a physical product - (including a physical distribution medium), accompanied by the - Corresponding Source fixed on a durable physical medium - customarily used for software interchange. - - b) Convey the object code in, or embodied in, a physical product - (including a physical distribution medium), accompanied by a - written offer, valid for at least three years and valid for as - long as you offer spare parts or customer support for that product - model, to give anyone who possesses the object code either (1) a - copy of the Corresponding Source for all the software in the - product that is covered by this License, on a durable physical - medium customarily used for software interchange, for a price no - more than your reasonable cost of physically performing this - conveying of source, or (2) access to copy the - Corresponding Source from a network server at no charge. - - c) Convey individual copies of the object code with a copy of the - written offer to provide the Corresponding Source. This - alternative is allowed only occasionally and noncommercially, and - only if you received the object code with such an offer, in accord - with subsection 6b. - - d) Convey the object code by offering access from a designated - place (gratis or for a charge), and offer equivalent access to the - Corresponding Source in the same way through the same place at no - further charge. You need not require recipients to copy the - Corresponding Source along with the object code. If the place to - copy the object code is a network server, the Corresponding Source - may be on a different server (operated by you or a third party) - that supports equivalent copying facilities, provided you maintain - clear directions next to the object code saying where to find the - Corresponding Source. Regardless of what server hosts the - Corresponding Source, you remain obligated to ensure that it is - available for as long as needed to satisfy these requirements. - - e) Convey the object code using peer-to-peer transmission, provided - you inform other peers where the object code and Corresponding - Source of the work are being offered to the general public at no - charge under subsection 6d. - - A separable portion of the object code, whose source code is excluded -from the Corresponding Source as a System Library, need not be -included in conveying the object code work. - - A "User Product" is either (1) a "consumer product", which means any -tangible personal property which is normally used for personal, family, -or household purposes, or (2) anything designed or sold for incorporation -into a dwelling. In determining whether a product is a consumer product, -doubtful cases shall be resolved in favor of coverage. For a particular -product received by a particular user, "normally used" refers to a -typical or common use of that class of product, regardless of the status -of the particular user or of the way in which the particular user -actually uses, or expects or is expected to use, the product. A product -is a consumer product regardless of whether the product has substantial -commercial, industrial or non-consumer uses, unless such uses represent -the only significant mode of use of the product. - - "Installation Information" for a User Product means any methods, -procedures, authorization keys, or other information required to install -and execute modified versions of a covered work in that User Product from -a modified version of its Corresponding Source. The information must -suffice to ensure that the continued functioning of the modified object -code is in no case prevented or interfered with solely because -modification has been made. - - If you convey an object code work under this section in, or with, or -specifically for use in, a User Product, and the conveying occurs as -part of a transaction in which the right of possession and use of the -User Product is transferred to the recipient in perpetuity or for a -fixed term (regardless of how the transaction is characterized), the -Corresponding Source conveyed under this section must be accompanied -by the Installation Information. But this requirement does not apply -if neither you nor any third party retains the ability to install -modified object code on the User Product (for example, the work has -been installed in ROM). - - The requirement to provide Installation Information does not include a -requirement to continue to provide support service, warranty, or updates -for a work that has been modified or installed by the recipient, or for -the User Product in which it has been modified or installed. Access to a -network may be denied when the modification itself materially and -adversely affects the operation of the network or violates the rules and -protocols for communication across the network. - - Corresponding Source conveyed, and Installation Information provided, -in accord with this section must be in a format that is publicly -documented (and with an implementation available to the public in -source code form), and must require no special password or key for -unpacking, reading or copying. - - 7. Additional Terms. - - "Additional permissions" are terms that supplement the terms of this -License by making exceptions from one or more of its conditions. -Additional permissions that are applicable to the entire Program shall -be treated as though they were included in this License, to the extent -that they are valid under applicable law. If additional permissions -apply only to part of the Program, that part may be used separately -under those permissions, but the entire Program remains governed by -this License without regard to the additional permissions. - - When you convey a copy of a covered work, you may at your option -remove any additional permissions from that copy, or from any part of -it. (Additional permissions may be written to require their own -removal in certain cases when you modify the work.) You may place -additional permissions on material, added by you to a covered work, -for which you have or can give appropriate copyright permission. - - Notwithstanding any other provision of this License, for material you -add to a covered work, you may (if authorized by the copyright holders of -that material) supplement the terms of this License with terms: - - a) Disclaiming warranty or limiting liability differently from the - terms of sections 15 and 16 of this License; or - - b) Requiring preservation of specified reasonable legal notices or - author attributions in that material or in the Appropriate Legal - Notices displayed by works containing it; or - - c) Prohibiting misrepresentation of the origin of that material, or - requiring that modified versions of such material be marked in - reasonable ways as different from the original version; or - - d) Limiting the use for publicity purposes of names of licensors or - authors of the material; or - - e) Declining to grant rights under trademark law for use of some - trade names, trademarks, or service marks; or - - f) Requiring indemnification of licensors and authors of that - material by anyone who conveys the material (or modified versions of - it) with contractual assumptions of liability to the recipient, for - any liability that these contractual assumptions directly impose on - those licensors and authors. - - All other non-permissive additional terms are considered "further -restrictions" within the meaning of section 10. If the Program as you -received it, or any part of it, contains a notice stating that it is -governed by this License along with a term that is a further -restriction, you may remove that term. If a license document contains -a further restriction but permits relicensing or conveying under this -License, you may add to a covered work material governed by the terms -of that license document, provided that the further restriction does -not survive such relicensing or conveying. - - If you add terms to a covered work in accord with this section, you -must place, in the relevant source files, a statement of the -additional terms that apply to those files, or a notice indicating -where to find the applicable terms. - - Additional terms, permissive or non-permissive, may be stated in the -form of a separately written license, or stated as exceptions; -the above requirements apply either way. - - 8. Termination. - - You may not propagate or modify a covered work except as expressly -provided under this License. Any attempt otherwise to propagate or -modify it is void, and will automatically terminate your rights under -this License (including any patent licenses granted under the third -paragraph of section 11). - - However, if you cease all violation of this License, then your -license from a particular copyright holder is reinstated (a) -provisionally, unless and until the copyright holder explicitly and -finally terminates your license, and (b) permanently, if the copyright -holder fails to notify you of the violation by some reasonable means -prior to 60 days after the cessation. - - Moreover, your license from a particular copyright holder is -reinstated permanently if the copyright holder notifies you of the -violation by some reasonable means, this is the first time you have -received notice of violation of this License (for any work) from that -copyright holder, and you cure the violation prior to 30 days after -your receipt of the notice. - - Termination of your rights under this section does not terminate the -licenses of parties who have received copies or rights from you under -this License. If your rights have been terminated and not permanently -reinstated, you do not qualify to receive new licenses for the same -material under section 10. - - 9. Acceptance Not Required for Having Copies. - - You are not required to accept this License in order to receive or -run a copy of the Program. Ancillary propagation of a covered work -occurring solely as a consequence of using peer-to-peer transmission -to receive a copy likewise does not require acceptance. However, -nothing other than this License grants you permission to propagate or -modify any covered work. These actions infringe copyright if you do -not accept this License. Therefore, by modifying or propagating a -covered work, you indicate your acceptance of this License to do so. - - 10. Automatic Licensing of Downstream Recipients. - - Each time you convey a covered work, the recipient automatically -receives a license from the original licensors, to run, modify and -propagate that work, subject to this License. You are not responsible -for enforcing compliance by third parties with this License. - - An "entity transaction" is a transaction transferring control of an -organization, or substantially all assets of one, or subdividing an -organization, or merging organizations. If propagation of a covered -work results from an entity transaction, each party to that -transaction who receives a copy of the work also receives whatever -licenses to the work the party's predecessor in interest had or could -give under the previous paragraph, plus a right to possession of the -Corresponding Source of the work from the predecessor in interest, if -the predecessor has it or can get it with reasonable efforts. - - You may not impose any further restrictions on the exercise of the -rights granted or affirmed under this License. For example, you may -not impose a license fee, royalty, or other charge for exercise of -rights granted under this License, and you may not initiate litigation -(including a cross-claim or counterclaim in a lawsuit) alleging that -any patent claim is infringed by making, using, selling, offering for -sale, or importing the Program or any portion of it. - - 11. Patents. - - A "contributor" is a copyright holder who authorizes use under this -License of the Program or a work on which the Program is based. The -work thus licensed is called the contributor's "contributor version". - - A contributor's "essential patent claims" are all patent claims -owned or controlled by the contributor, whether already acquired or -hereafter acquired, that would be infringed by some manner, permitted -by this License, of making, using, or selling its contributor version, -but do not include claims that would be infringed only as a -consequence of further modification of the contributor version. For -purposes of this definition, "control" includes the right to grant -patent sublicenses in a manner consistent with the requirements of -this License. - - Each contributor grants you a non-exclusive, worldwide, royalty-free -patent license under the contributor's essential patent claims, to -make, use, sell, offer for sale, import and otherwise run, modify and -propagate the contents of its contributor version. - - In the following three paragraphs, a "patent license" is any express -agreement or commitment, however denominated, not to enforce a patent -(such as an express permission to practice a patent or covenant not to -sue for patent infringement). To "grant" such a patent license to a -party means to make such an agreement or commitment not to enforce a -patent against the party. - - If you convey a covered work, knowingly relying on a patent license, -and the Corresponding Source of the work is not available for anyone -to copy, free of charge and under the terms of this License, through a -publicly available network server or other readily accessible means, -then you must either (1) cause the Corresponding Source to be so -available, or (2) arrange to deprive yourself of the benefit of the -patent license for this particular work, or (3) arrange, in a manner -consistent with the requirements of this License, to extend the patent -license to downstream recipients. "Knowingly relying" means you have -actual knowledge that, but for the patent license, your conveying the -covered work in a country, or your recipient's use of the covered work -in a country, would infringe one or more identifiable patents in that -country that you have reason to believe are valid. - - If, pursuant to or in connection with a single transaction or -arrangement, you convey, or propagate by procuring conveyance of, a -covered work, and grant a patent license to some of the parties -receiving the covered work authorizing them to use, propagate, modify -or convey a specific copy of the covered work, then the patent license -you grant is automatically extended to all recipients of the covered -work and works based on it. - - A patent license is "discriminatory" if it does not include within -the scope of its coverage, prohibits the exercise of, or is -conditioned on the non-exercise of one or more of the rights that are -specifically granted under this License. You may not convey a covered -work if you are a party to an arrangement with a third party that is -in the business of distributing software, under which you make payment -to the third party based on the extent of your activity of conveying -the work, and under which the third party grants, to any of the -parties who would receive the covered work from you, a discriminatory -patent license (a) in connection with copies of the covered work -conveyed by you (or copies made from those copies), or (b) primarily -for and in connection with specific products or compilations that -contain the covered work, unless you entered into that arrangement, -or that patent license was granted, prior to 28 March 2007. - - Nothing in this License shall be construed as excluding or limiting -any implied license or other defenses to infringement that may -otherwise be available to you under applicable patent law. - - 12. No Surrender of Others' Freedom. - - If conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot convey a -covered work so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you may -not convey it at all. For example, if you agree to terms that obligate you -to collect a royalty for further conveying from those to whom you convey -the Program, the only way you could satisfy both those terms and this -License would be to refrain entirely from conveying the Program. - - 13. Use with the GNU Affero General Public License. - - Notwithstanding any other provision of this License, you have -permission to link or combine any covered work with a work licensed -under version 3 of the GNU Affero General Public License into a single -combined work, and to convey the resulting work. The terms of this -License will continue to apply to the part which is the covered work, -but the special requirements of the GNU Affero General Public License, -section 13, concerning interaction through a network will apply to the -combination as such. - - 14. Revised Versions of this License. - - The Free Software Foundation may publish revised and/or new versions of -the GNU General Public License from time to time. Such new versions will -be similar in spirit to the present version, but may differ in detail to -address new problems or concerns. - - Each version is given a distinguishing version number. If the -Program specifies that a certain numbered version of the GNU General -Public License "or any later version" applies to it, you have the -option of following the terms and conditions either of that numbered -version or of any later version published by the Free Software -Foundation. If the Program does not specify a version number of the -GNU General Public License, you may choose any version ever published -by the Free Software Foundation. - - If the Program specifies that a proxy can decide which future -versions of the GNU General Public License can be used, that proxy's -public statement of acceptance of a version permanently authorizes you -to choose that version for the Program. - - Later license versions may give you additional or different -permissions. However, no additional obligations are imposed on any -author or copyright holder as a result of your choosing to follow a -later version. - - 15. Disclaimer of Warranty. - - THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY -APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT -HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY -OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, -THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM -IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF -ALL NECESSARY SERVICING, REPAIR OR CORRECTION. - - 16. Limitation of Liability. - - IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING -WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS -THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY -GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE -USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF -DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD -PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), -EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF -SUCH DAMAGES. - - 17. Interpretation of Sections 15 and 16. - - If the disclaimer of warranty and limitation of liability provided -above cannot be given local legal effect according to their terms, -reviewing courts shall apply local law that most closely approximates -an absolute waiver of all civil liability in connection with the -Program, unless a warranty or assumption of liability accompanies a -copy of the Program in return for a fee. - - END OF TERMS AND CONDITIONS - - How to Apply These Terms to Your New Programs - - If you develop a new program, and you want it to be of the greatest -possible use to the public, the best way to achieve this is to make it -free software which everyone can redistribute and change under these terms. - - To do so, attach the following notices to the program. It is safest -to attach them to the start of each source file to most effectively -state the exclusion of warranty; and each file should have at least -the "copyright" line and a pointer to where the full notice is found. - - - Copyright (C) - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . - -Also add information on how to contact you by electronic and paper mail. - - If the program does terminal interaction, make it output a short -notice like this when it starts in an interactive mode: - - Copyright (C) - This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. - This is free software, and you are welcome to redistribute it - under certain conditions; type `show c' for details. - -The hypothetical commands `show w' and `show c' should show the appropriate -parts of the General Public License. Of course, your program's commands -might be different; for a GUI interface, you would use an "about box". - - You should also get your employer (if you work as a programmer) or school, -if any, to sign a "copyright disclaimer" for the program, if necessary. -For more information on this, and how to apply and follow the GNU GPL, see -. - - The GNU General Public License does not permit incorporating your program -into proprietary programs. If your program is a subroutine library, you -may consider it more useful to permit linking proprietary applications with -the library. If this is what you want to do, use the GNU Lesser General -Public License instead of this License. But first, please read -. diff --git a/update-tool/README.md b/update-tool/README.md deleted file mode 100644 index 778029c2..00000000 --- a/update-tool/README.md +++ /dev/null @@ -1,15 +0,0 @@ -### Spark Update Tool -#### Introduction - -Welcome to Spark Software Updater. Use this tool to update applications on your Linux system. -This version is specifically designed for Linux distributions with Qt6 support. -Please run under root privileges (recommended: use `sudo`). -#### Currently Supported Linux Distributions -- [x] GXDE OS -- [x] Ubuntu -- [x] deepin -- [ ] Kylin - - -#### Contact & Feedback -momen@momen.world diff --git a/update-tool/README.zh.md b/update-tool/README.zh.md deleted file mode 100644 index c597ce44..00000000 --- a/update-tool/README.zh.md +++ /dev/null @@ -1,25 +0,0 @@ -### 星火软件更新器 -#### 简介 - -欢迎使用星火软件更新器,您可以使用此更新器更新位于您 Linux 计算机的程序。 -此版本专为有qt6的Linux发行版所使用。 -请在root环境下运行。 -#### 当前支持的 Linux 发行版 -- [x] GXDE OS -- [x] Ubuntu -- [x] deepin -- [ ] Kylin - -#### 功能清单 - -| 功能模块 | 描述 | -|------------------|--------------------------------------| -| 应用名识别 | 基于 `ss-do-upgrade.sh` 部分代码实现 | -| 应用包大小识别 | 通过 dpkg 获取包大小信息 | -| 获取应用图标 | 利用 QDesktopServices 实现 | -| 支持 ACE 兼容环境| | -| 多线程下载 | 基于 aptss 方案 | - -如您已安装星火应用商店,则会附带本程序。 -#### 联系与反馈 -momen@momen.world \ No newline at end of file diff --git a/update-tool/debian/changelog b/update-tool/debian/changelog deleted file mode 100644 index b414feaa..00000000 --- a/update-tool/debian/changelog +++ /dev/null @@ -1,5 +0,0 @@ -spark-update-tool (1.0.0) unstable; urgency=low - - * Initial release. - - -- momen Wed, 18 Jun 2025 00:00:00 +0000 \ No newline at end of file diff --git a/update-tool/debian/compat b/update-tool/debian/compat deleted file mode 100644 index f11c82a4..00000000 --- a/update-tool/debian/compat +++ /dev/null @@ -1 +0,0 @@ -9 \ No newline at end of file diff --git a/update-tool/debian/control b/update-tool/debian/control deleted file mode 100644 index 19c9d624..00000000 --- a/update-tool/debian/control +++ /dev/null @@ -1,13 +0,0 @@ -Source: spark-update-tool -Section: utils -Priority: optional -Maintainer: momen -Build-Depends: debhelper (>= 9) -Standards-Version: 3.9.6 -Homepage: https://gitee.com/spark-store-project/Spark-Update-Tool - -Package: spark-update-tool -Architecture: any -Depends: ${shlibs:Depends}, ${misc:Depends} -Description: Spark Update Tool - 星火应用商店更新组件。This package provides the Spark Update Tool. It includes features for checking for updates, downloading, and applying them seamlessly. \ No newline at end of file diff --git a/update-tool/debian/copyright b/update-tool/debian/copyright deleted file mode 100644 index 163489ed..00000000 --- a/update-tool/debian/copyright +++ /dev/null @@ -1,7 +0,0 @@ -Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/ -Upstream-Name: spark-update-tool -Source: https://gitee.com/spark-store-project/Spark-Update-Tool - -Files: * -Copyright: 2025, momen -License: GPL-3.0+ \ No newline at end of file diff --git a/update-tool/debian/install b/update-tool/debian/install deleted file mode 100644 index ed44f2cf..00000000 --- a/update-tool/debian/install +++ /dev/null @@ -1,3 +0,0 @@ -build/spark-update-tool /usr/bin/ -debian/spark-update-tool.desktop /usr/share/applications -resources/128*128/spark-update-tool.png /usr/share/icons/hicolor/128x128/apps diff --git a/update-tool/debian/postrm b/update-tool/debian/postrm deleted file mode 100644 index 263e9c42..00000000 --- a/update-tool/debian/postrm +++ /dev/null @@ -1,11 +0,0 @@ -#!/bin/sh -set -e - -case "$1" in - purge) - - rm -rf /usr/share/spark-update-tool - ;; -esac - -exit 0 \ No newline at end of file diff --git a/update-tool/debian/rules b/update-tool/debian/rules deleted file mode 100755 index 1159ac4f..00000000 --- a/update-tool/debian/rules +++ /dev/null @@ -1,7 +0,0 @@ -#!/usr/bin/make -f - -%: - dh $@ - -override_dh_auto_configure: - dh_auto_configure -- -DCMAKE_INSTALL_PREFIX=/usr diff --git a/update-tool/debian/source/format b/update-tool/debian/source/format deleted file mode 100644 index 9f674278..00000000 --- a/update-tool/debian/source/format +++ /dev/null @@ -1 +0,0 @@ -3.0 (native) \ No newline at end of file diff --git a/update-tool/debian/spark-update-tool.desktop b/update-tool/debian/spark-update-tool.desktop deleted file mode 100644 index 688ba0cd..00000000 --- a/update-tool/debian/spark-update-tool.desktop +++ /dev/null @@ -1,9 +0,0 @@ -[Desktop Entry] -Version=1.0 -Name=Spark Update Tool -Comment=A Qt-based application for managing and updating software -Exec=spark-update-tool -Icon=spark-update-tool -Terminal=false -Type=Application -Categories=Utility; diff --git a/update-tool/resources/128*128/spark-update-tool.png b/update-tool/resources/128*128/spark-update-tool.png deleted file mode 100644 index 138ed83770cf4cce8fdead9c11908a0446e8a135..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 9142 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 AL;wH) diff --git a/update-tool/resources/default_icon.svg b/update-tool/resources/default_icon.svg deleted file mode 100644 index 7c9cb42d..00000000 --- a/update-tool/resources/default_icon.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/update-tool/resources/down_arrow.svg b/update-tool/resources/down_arrow.svg deleted file mode 100644 index 4989662c..00000000 --- a/update-tool/resources/down_arrow.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/update-tool/resources/spark-update-tool.svg b/update-tool/resources/spark-update-tool.svg deleted file mode 100644 index 3d21d816..00000000 --- a/update-tool/resources/spark-update-tool.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/update-tool/src/appdelegate.cpp b/update-tool/src/appdelegate.cpp deleted file mode 100644 index 1a1c3e98..00000000 --- a/update-tool/src/appdelegate.cpp +++ /dev/null @@ -1,321 +0,0 @@ -#include "appdelegate.h" -#include -#include -#include -#include -#include -#include -#include -#include - -AppDelegate::AppDelegate(QObject *parent) - : QStyledItemDelegate(parent), m_downloadManager(new DownloadManager(this)), m_installProcess(nullptr) { - connect(m_downloadManager, &DownloadManager::downloadFinished, this, - [this](const QString &packageName, bool success) { - if (m_downloads.contains(packageName)) { - m_downloads[packageName].isDownloading = false; - emit updateDisplay(packageName); - qDebug() << (success ? "下载完成:" : "下载失败:") << packageName; - if (success) { - enqueueInstall(packageName); - } - } - }); - - connect(m_downloadManager, &DownloadManager::downloadProgress, this, - [this](const QString &packageName, int progress) { - if (m_downloads.contains(packageName)) { - m_downloads[packageName].progress = progress; - qDebug()<save(); - - if (option.state & QStyle::State_Selected) - painter->fillRect(option.rect, option.palette.highlight()); - else - painter->fillRect(option.rect, QColor("#F3F4F6")); - - QFont boldFont = option.font; - boldFont.setBold(true); - QFont normalFont = option.font; - - QString name = index.data(Qt::DisplayRole).toString(); - QString currentVersion = index.data(Qt::UserRole + 2).toString(); - QString newVersion = index.data(Qt::UserRole + 3).toString(); - QString iconPath = index.data(Qt::UserRole + 4).toString(); - QString size = index.data(Qt::UserRole + 5).toString(); - QString description = index.data(Qt::UserRole + 6).toString(); - - QRect rect = option.rect; - int margin = 10, spacing = 6, iconSize = 40; - - QRect iconRect(rect.left() + margin, rect.top() + (rect.height() - iconSize) / 2, iconSize, iconSize); - QIcon(iconPath).paint(painter, iconRect); - - int textX = iconRect.right() + margin; - int textWidth = rect.width() - textX - 100; - - QRect nameRect(textX, rect.top() + margin, textWidth, 20); - painter->setFont(boldFont); - painter->setPen(QColor("#333333")); - painter->drawText(nameRect, Qt::AlignLeft | Qt::AlignVCenter, name); - - QRect versionRect(textX, nameRect.bottom() + spacing, textWidth, 20); - painter->setFont(normalFont); - painter->setPen(QColor("#888888")); - painter->drawText(versionRect, Qt::AlignLeft | Qt::AlignVCenter, - QString("当前版本: %1 → 新版本: %2").arg(currentVersion, newVersion)); - - QRect descRect(textX, versionRect.bottom() + spacing, textWidth, 40); - painter->setFont(normalFont); - painter->setPen(QColor("#AAAAAA")); - painter->drawText(descRect, Qt::TextWordWrap, - QString("包大小:%1 MB").arg(QString::number(size.toDouble() / (1024 * 1024), 'f', 2))); - - QString packageName = index.data(Qt::UserRole + 1).toString(); - bool isDownloading = m_downloads.contains(packageName) && m_downloads[packageName].isDownloading; - int progress = m_downloads.value(packageName, DownloadInfo{0, false}).progress; - bool isInstalled = m_downloads.value(packageName).isInstalled; - bool isInstalling = m_downloads.value(packageName).isInstalling; - - if (isDownloading) { - QRect progressRect(rect.right() - 270, rect.top() + (rect.height() - 20) / 2, 150, 20); - QStyleOptionProgressBar progressBarOption; - progressBarOption.rect = progressRect; - progressBarOption.minimum = 0; - progressBarOption.maximum = 100; - progressBarOption.progress = progress; - progressBarOption.text = QString("%1%").arg(progress); - progressBarOption.textVisible = true; - QApplication::style()->drawControl(QStyle::CE_ProgressBar, &progressBarOption, painter); - - // 修改后的取消按钮绘制代码 - QRect buttonRect(rect.right() - 80, rect.top() + (rect.height() - 30) / 2, 70, 30); - painter->setPen(Qt::NoPen); - painter->setBrush(QColor("#ff4444")); // 红色背景 - painter->drawRoundedRect(buttonRect, 4, 4); // 圆角矩形 - - painter->setPen(Qt::white); // 白色文字 - painter->setFont(option.font); - painter->drawText(buttonRect, Qt::AlignCenter, "取消"); - } else if (isInstalling) { - // 安装中:显示转圈和文字 - QRect spinnerRect(option.rect.right() - 80, option.rect.top() + (option.rect.height() - 30) / 2, 30, 30); - int angle = (m_spinnerTimer.elapsed() / 10) % 360; - QPen pen(QColor("#2563EB"), 3); - painter->setPen(pen); - painter->setRenderHint(QPainter::Antialiasing, true); - QRectF arcRect = spinnerRect.adjusted(3, 3, -3, -3); - painter->drawArc(arcRect, angle * 16, 120 * 16); // 120度弧 - - QRect textRect(option.rect.right() - 120, option.rect.top() + (option.rect.height() - 30) / 2, 110, 30); - painter->setPen(QColor("#2563EB")); - painter->setFont(option.font); - painter->drawText(textRect, Qt::AlignLeft | Qt::AlignVCenter, "正在安装中"); - } else { - QRect buttonRect(option.rect.right() - 80, option.rect.top() + (option.rect.height() - 30) / 2, 70, 30); - painter->setPen(Qt::NoPen); - if (isInstalled) { - painter->setBrush(QColor("#10B981")); - painter->drawRoundedRect(buttonRect, 4, 4); - painter->setPen(Qt::white); - painter->drawText(buttonRect, Qt::AlignCenter, "已安装"); - } else if (m_downloads.contains(packageName) && !m_downloads[packageName].isDownloading) { - // 下载完成,按钮绿色,样式不变 - painter->setBrush(QColor("#10B981")); - painter->drawRoundedRect(buttonRect, 4, 4); - painter->setPen(Qt::white); - painter->drawText(buttonRect, Qt::AlignCenter, "下载完成"); - // 不需要特殊处理样式,交互在 editorEvent 控制 - } else { - painter->setBrush(QColor("#e9effd")); - painter->drawRoundedRect(buttonRect, 4, 4); - painter->setPen(QColor("#2563EB")); - painter->drawText(buttonRect, Qt::AlignCenter, "更新"); - } - } - - painter->restore(); -} - -QSize AppDelegate::sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const { - return QSize(option.rect.width(), 110); -} - -bool AppDelegate::editorEvent(QEvent *event, QAbstractItemModel *model, - const QStyleOptionViewItem &option, const QModelIndex &index) { - if (event->type() == QEvent::MouseButtonRelease) { - QMouseEvent *mouseEvent = static_cast(event); - QRect rect = option.rect; - QString packageName = index.data(Qt::UserRole + 1).toString(); - - if (m_downloads.contains(packageName) && m_downloads[packageName].isDownloading) { - QRect cancelButtonRect(rect.right() - 70, rect.top() + (rect.height() - 20) / 2, 60, 20); - if (cancelButtonRect.contains(mouseEvent->pos())) { - m_downloadManager->cancelDownload(packageName); - m_downloads.remove(packageName); - emit updateDisplay(packageName); - return true; - } - } else { - QRect buttonRect(rect.right() - 80, rect.top() + (rect.height() - 30) / 2, 70, 30); - if (buttonRect.contains(mouseEvent->pos())) { - // 判断是否为“下载完成”状态,如果是则不响应点击 - if (m_downloads.contains(packageName) && !m_downloads[packageName].isDownloading) { - // “下载完成”状态,按钮失效,点击无效 - return false; - } - QString downloadUrl = index.data(Qt::UserRole + 7).toString(); - QString outputPath = QString("%1/%2.metalink").arg(QDir::tempPath(), packageName); - - m_downloads[packageName] = {0, true}; - m_downloadManager->startDownload(packageName, downloadUrl, outputPath); - emit updateDisplay(packageName); - return true; - } - } - } - - return QStyledItemDelegate::editorEvent(event, model, option, index); -} - -void AppDelegate::startDownloadForAll() { - if (!m_model) return; - for (int row = 0; row < m_model->rowCount(); ++row) { - QModelIndex index = m_model->index(row, 0); - QString packageName = index.data(Qt::UserRole + 1).toString(); - if (m_downloads.contains(packageName) && (m_downloads[packageName].isDownloading || m_downloads[packageName].isInstalled)) - continue; // 跳过正在下载或已安装的 - QString downloadUrl = index.data(Qt::UserRole + 7).toString(); - QString outputPath = QString("%1/%2.metalink").arg(QDir::tempPath(), packageName); - m_downloads[packageName] = {0, true, false}; - m_downloadManager->startDownload(packageName, downloadUrl, outputPath); - emit updateDisplay(packageName); - } -} - -// 新增:安装队列相关实现 -void AppDelegate::enqueueInstall(const QString &packageName) { - m_installQueue.enqueue(packageName); - if (!m_isInstalling) { - startNextInstall(); - } -} - -void AppDelegate::startNextInstall() { - if (m_installQueue.isEmpty()) { - m_isInstalling = false; - m_installingPackage.clear(); - return; - } - m_isInstalling = true; - QString packageName = m_installQueue.dequeue(); - m_installingPackage = packageName; - m_downloads[packageName].isInstalling = true; - emit updateDisplay(packageName); - - // 查找 /tmp 下以包名开头的 .deb 文件 - QDir tempDir(QDir::tempPath()); - QStringList debs = tempDir.entryList(QStringList() << QString("%1_*.deb").arg(packageName), QDir::Files); - QString debPath; - if (!debs.isEmpty()) { - debPath = tempDir.absoluteFilePath(debs.first()); - } else { - debs = tempDir.entryList(QStringList() << QString("%1*.deb").arg(packageName), QDir::Files); - if (!debs.isEmpty()) { - debPath = tempDir.absoluteFilePath(debs.first()); - } - } - - if (debPath.isEmpty()) { - qWarning() << "未找到deb文件,包名:" << packageName; - m_downloads[packageName].isInstalling = false; - emit updateDisplay(packageName); - m_installingPackage.clear(); - startNextInstall(); - return; - } - - m_installProcess = new QProcess(this); - - // 新增:准备安装日志文件 - QString logPath = QString("/tmp/%1_install.log").arg(packageName); - QFile *logFile = new QFile(logPath, m_installProcess); - if (logFile->open(QIODevice::Append | QIODevice::Text)) { - // 设置权限为777 - QFile::setPermissions(logPath, QFile::ReadOwner | QFile::WriteOwner | QFile::ExeOwner | - QFile::ReadGroup | QFile::WriteGroup | QFile::ExeGroup | - QFile::ReadOther | QFile::WriteOther | QFile::ExeOther); - connect(m_installProcess, &QProcess::readyReadStandardOutput, this, [this, packageName, logFile]() { - QByteArray out = m_installProcess->readAllStandardOutput(); - logFile->write(out); - logFile->flush(); - QString text = QString::fromLocal8Bit(out); - qDebug().noquote() << text; - // 检查“软件包已安装”关键字 - if (text.contains(QStringLiteral("软件包已安装"))) { - m_downloads[packageName].isInstalling = false; - m_downloads[packageName].isInstalled = true; - emit updateDisplay(packageName); - } - }); - connect(m_installProcess, &QProcess::readyReadStandardError, this, [this, logFile]() { - QByteArray err = m_installProcess->readAllStandardError(); - logFile->write(err); - logFile->flush(); - qDebug().noquote() << QString::fromLocal8Bit(err); - }); - connect(m_installProcess, QOverload::of(&QProcess::finished), - this, [this, packageName, logFile](int /*exitCode*/, QProcess::ExitStatus /*status*/) { - if (logFile) logFile->close(); - // 若未检测到“软件包已安装”,此处兜底 - if (!m_downloads[packageName].isInstalled) { - m_downloads[packageName].isInstalling = false; - } - emit updateDisplay(packageName); - m_installProcess->deleteLater(); - m_installProcess = nullptr; - m_installingPackage.clear(); - startNextInstall(); - }); - } else { - // 日志文件无法打开时,仍然要连接原有信号 - connect(m_installProcess, &QProcess::readyReadStandardOutput, this, [this, packageName]() { - QByteArray out = m_installProcess->readAllStandardOutput(); - QString text = QString::fromLocal8Bit(out); - qDebug().noquote() << text; - if (text.contains(QStringLiteral("软件包已安装"))) { - m_downloads[packageName].isInstalling = false; - m_downloads[packageName].isInstalled = true; - emit updateDisplay(packageName); - } - }); - connect(m_installProcess, &QProcess::readyReadStandardError, this, [this]() { - QByteArray err = m_installProcess->readAllStandardError(); - qDebug().noquote() << QString::fromLocal8Bit(err); - }); - connect(m_installProcess, QOverload::of(&QProcess::finished), - this, [this, packageName](int /*exitCode*/, QProcess::ExitStatus /*status*/) { - emit updateDisplay(packageName); - m_installProcess->deleteLater(); - m_installProcess = nullptr; - m_installingPackage.clear(); - startNextInstall(); - }); - } - - // 注意参数顺序:deb路径在前,--no-create-desktop-entry在后 - QStringList args; - args << debPath << "--no-create-desktop-entry"; - m_installProcess->start("ssinstall", args); -} diff --git a/update-tool/src/appdelegate.h b/update-tool/src/appdelegate.h deleted file mode 100644 index 0545155e..00000000 --- a/update-tool/src/appdelegate.h +++ /dev/null @@ -1,46 +0,0 @@ -#pragma once - -#include -#include -#include -#include -#include -#include "downloadmanager.h" - -struct DownloadInfo { - int progress = 0; - bool isDownloading = false; - bool isInstalled = false; - bool isInstalling = false; // 新增:标记是否正在安装 -}; - -class AppDelegate : public QStyledItemDelegate { - Q_OBJECT -public: - explicit AppDelegate(QObject *parent = nullptr); - - void setModel(QAbstractItemModel *model); - - void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const override; - QSize sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const override; - bool editorEvent(QEvent *event, QAbstractItemModel *model, - const QStyleOptionViewItem &option, const QModelIndex &index) override; - void startDownloadForAll(); - -signals: - void updateDisplay(const QString &packageName); - -private: - DownloadManager *m_downloadManager; - QHash m_downloads; - QAbstractItemModel *m_model = nullptr; - - QQueue m_installQueue; - bool m_isInstalling = false; - QProcess *m_installProcess = nullptr; - QString m_installingPackage; // 当前正在安装的包名 - QElapsedTimer m_spinnerTimer; // 用于转圈动画 - - void enqueueInstall(const QString &packageName); - void startNextInstall(); -}; diff --git a/update-tool/src/applistmodel.cpp b/update-tool/src/applistmodel.cpp deleted file mode 100644 index 31e244a9..00000000 --- a/update-tool/src/applistmodel.cpp +++ /dev/null @@ -1,62 +0,0 @@ -#include "applistmodel.h" - -AppListModel::AppListModel(QObject *parent) : QAbstractListModel(parent) {} - -int AppListModel::rowCount(const QModelIndex &parent) const -{ - if (parent.isValid()) - return 0; - return m_data.size(); -} - -QVariant AppListModel::data(const QModelIndex &index, int role) const -{ - if (!index.isValid() || index.row() >= m_data.size()) - return QVariant(); - - const QVariantMap &map = m_data.at(index.row()); // 直接访问 QVariantMap - switch (role) { - case Qt::DisplayRole: - return map.value("name"); - case Qt::UserRole + 1: // 包名 - return map.value("package"); - case Qt::UserRole + 2: // 当前版本 - return map.value("current_version"); - case Qt::UserRole + 3: // 新版本 - return map.value("new_version"); - case Qt::UserRole + 4: // 图标路径 - return map.value("icon"); - case Qt::UserRole + 5: // 文件大小 - return map.value("size"); - case Qt::UserRole + 6: // 描述 - return map.value("description"); - case Qt::UserRole + 7: // 下载 URL - return map.value("download_url"); // 返回下载 URL - default: - return QVariant(); - } -} - -void AppListModel::setUpdateData(const QJsonArray &updateInfo) -{ - beginResetModel(); - m_data.clear(); // 清空 QList - - for (const auto &item : updateInfo) { - QJsonObject obj = item.toObject(); - QVariantMap map; - map["package"] = obj["package"].toString(); - map["name"] = obj["name"].toString(); - map["current_version"] = obj["current_version"].toString(); - map["new_version"] = obj["new_version"].toString(); - map["icon"] = obj["icon"].toString(); - map["size"] = obj["size"].toString(); - map["download_url"] = obj["download_url"].toString(); // 确保设置下载 URL - m_data.append(map); // 添加到 QList - - qDebug() << "设置到模型的包名:" << map["package"].toString(); - qDebug() << "设置到模型的下载 URL:" << map["download_url"].toString(); // 检查设置的数据 - } - - endResetModel(); -} diff --git a/update-tool/src/applistmodel.h b/update-tool/src/applistmodel.h deleted file mode 100644 index 2fb36c0d..00000000 --- a/update-tool/src/applistmodel.h +++ /dev/null @@ -1,26 +0,0 @@ -#ifndef APPLISTMODEL_H -#define APPLISTMODEL_H - -#include -#include -// 添加 QJsonObject 头文件 -#include - -class AppListModel : public QAbstractListModel -{ - Q_OBJECT -public: - explicit AppListModel(QObject *parent = nullptr); - - // 重写方法 - int rowCount(const QModelIndex &parent = QModelIndex()) const override; - QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override; - - // 设置更新数据 - void setUpdateData(const QJsonArray &data); - -private: - QList m_data; // 修改类型为 QList -}; - -#endif // APPLISTMODEL_H diff --git a/update-tool/src/aptssupdater.cpp b/update-tool/src/aptssupdater.cpp deleted file mode 100644 index c4bd9060..00000000 --- a/update-tool/src/aptssupdater.cpp +++ /dev/null @@ -1,398 +0,0 @@ -#include "aptssupdater.h" -#include -#include -#include -#include -#include - -aptssUpdater::aptssUpdater(QWidget *parent) - : QWidget(parent) -{ - packageName = getUpdateablePackages(); -} - -QStringList aptssUpdater::getUpdateablePackages() -{ - QStringList packageDetails; - QProcess process; - QString command = R"(env LANGUAGE=en_US /usr/bin/apt -c /opt/durapps/spark-store/bin/apt-fast-conf/aptss-apt.conf list --upgradable -o Dir::Etc::sourcelist="/opt/durapps/spark-store/bin/apt-fast-conf/sources.list.d/sparkstore.list" -o Dir::Etc::sourceparts="/dev/null" -o APT::Get::List-Cleanup="0" | awk 'NR>1')"; - - process.start("bash", QStringList() << "-c" << command); - if (!process.waitForFinished()) { - qWarning() << "Process failed to finish."; - return packageDetails; - } - - QString output = process.readAllStandardOutput(); - QStringList lines = output.split('\n', Qt::SkipEmptyParts); - - // 创建临时文件 - QTemporaryFile tempFile; - tempFile.setAutoRemove(false); - if (tempFile.open()) { - QTextStream stream(&tempFile); - - for (const QString &line : lines) { - QRegularExpression regex(R"(([\w\-\+\.]+)/\S+\s+([^\s]+)\s+\S+\s+\[upgradable from: ([^\]]+)\])"); - QRegularExpressionMatch match = regex.match(line); - if (match.hasMatch()) { - QString name = match.captured(1); - QString newVersion = match.captured(2); - QString oldVersion = match.captured(3); - - // 检查版本是否相同,相同则跳过 - if (newVersion == oldVersion) { - qDebug() << "跳过版本相同的包:" << name << "(" << oldVersion << "→" << newVersion << ")"; - continue; - } - - // 写入内存列表 - packageDetails << QString("%1: %2 → %3").arg(name, oldVersion, newVersion); - - // 写入临时文件(原始数据) - stream << name << "|" << oldVersion << "|" << newVersion << "\n"; - } - } - tempFile.close(); - m_tempFilePath = tempFile.fileName(); - qDebug()<< "临时文件路径:" << m_tempFilePath; - - } else { - qWarning() << "无法创建临时文件"; - } - - return packageDetails; -} - - -QStringList aptssUpdater::getPackageSizes() -{ - QStringList packageDetails; - QProcess process; - - // 获取可更新包名列表 - QStringList updateablePackages; - for (const QString &pkgInfo : packageName) { - updateablePackages << pkgInfo.section(":", 0, 0).trimmed(); - } - - foreach (const QString &packageName, updateablePackages) { - // 构建新命令(包含包名参数) - QString command = QString("apt download %1 --print-uris -c /opt/durapps/spark-store/bin/apt-fast-conf/aptss-apt.conf " - "-o Dir::Etc::sourcelist=\"/opt/durapps/spark-store/bin/apt-fast-conf/sources.list.d/sparkstore.list\" " - "-o Dir::Etc::sourceparts=\"/dev/null\"").arg(packageName); - - process.start("bash", QStringList() << "-c" << command); - if (!process.waitForFinished()) { - qWarning() << "获取包信息失败:" << packageName; - continue; - } - - QString output = process.readAllStandardOutput(); - // 使用正则匹配所有信息 - // 调整正则表达式匹配分组 - QRegularExpression regex(R"('([^']+)'\s+(\S+)\s+(\d+)\s+SHA512:([^\s]+))"); // 分组1:URL 分组2:文件名 分组3:大小 分组4:SHA512 - QRegularExpressionMatch match = regex.match(output); - - if (match.hasMatch()) { - QString url = match.captured(1); - QString fileName = match.captured(2); - QString size = match.captured(3); - QString sha512 = match.captured(4); - - // 调整字段顺序:包名 | 大小 | URL | SHA512 - packageDetails << QString("%1: %2|%3|%4").arg(packageName, size, url, sha512); - } - } - - qDebug() << "完整包信息:" << packageDetails; - return packageDetails; -} - - - - - -QStringList aptssUpdater::getDesktopAppNames() -{ - QStringList appNames; - QProcess dpkgProcess; - - // 获取当前系统语言环境 - QString lang = QLocale().name().replace("_", "-"); - - // 遍历所有可更新包(复用已有的临时文件数据) - QStringList packages = packageName; - - foreach (const QString &package, packages) { - QString packageName = package.split(":")[0]; - QString finalName = packageName; // 默认使用包名 - - // 获取包文件列表 - dpkgProcess.start("dpkg", QStringList() << "-L" << packageName); - dpkgProcess.waitForFinished(); - QStringList files = QString(dpkgProcess.readAllStandardOutput()).split('\n', Qt::SkipEmptyParts); - - // 先检查常规应用目录 - QStringList regularDesktopFiles = files.filter("/usr/share/applications/"); - QString regularAppName; - if (!regularDesktopFiles.isEmpty()) { - checkDesktopFiles(regularDesktopFiles, regularAppName, lang, packageName); - } - - // 如果常规目录没有找到,再检查特殊目录 - if (regularAppName.isEmpty()) { - QStringList specialDesktopFiles = files.filter(QRegularExpression(QString("/opt/apps/%1/entries/applications").arg(packageName))); - QString specialAppName; - if (!specialDesktopFiles.isEmpty()) { - checkDesktopFiles(specialDesktopFiles, specialAppName, lang, packageName); - if (!specialAppName.isEmpty()) { - finalName = specialAppName; - } - } - } else { - finalName = regularAppName; - } - - // 输出格式为[软件名|包名] - appNames << QString("[%1|%2]").arg(finalName, packageName); - } - qDebug()<< "应用名称列表:" << appNames; - return appNames; -} - - -bool aptssUpdater::checkDesktopFiles(const QStringList &desktopFiles, QString &appName, const QString &lang, const QString &packageName) -{ - QString lastValidName; - QRegularExpression noDisplayRe("^NoDisplay=(true|True)"); - QRegularExpression nameRe("^Name\\[?" + lang + "?\\]?=(.*)"); - QRegularExpression nameOrigRe("^Name=(.*)"); - - foreach (const QString &filePath, desktopFiles) { - if (!filePath.endsWith(".desktop")) continue; - - QFile file(filePath); - if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) continue; - - bool skip = false; - QString currentName; - - QTextStream in(&file); - while (!in.atEnd()) { - QString line = in.readLine().trimmed(); - - // 检查NoDisplay属性 - if (line.startsWith("NoDisplay=")) { - if (noDisplayRe.match(line).hasMatch()) { - skip = true; - break; - } - } - - // 优先匹配本地化名称 - if (currentName.isEmpty()) { - QRegularExpressionMatch match = nameRe.match(line); - if (match.hasMatch()) { - currentName = match.captured(1); - continue; - } - - // 匹配原始名称 - match = nameOrigRe.match(line); - if (match.hasMatch()) { - currentName = match.captured(1); - } - } - } - - if (!skip && !currentName.isEmpty()) { - lastValidName = currentName; - } - } - - // 处理最终的有效名称 - if (!lastValidName.isEmpty()) { - appName = lastValidName; // 直接赋值而不是使用<< - return true; - } - - // 回退到包名 - appName = packageName; - return false; -} - -QStringList aptssUpdater::getPackageIcons() -{ - QStringList packageIcons; - QProcess dpkgProcess; - - // 遍历所有可更新包 - QStringList packages = packageName; - - foreach (const QString &package, packages) { - QString packageName = package.split(":")[0]; - QString iconPath = ":/resources/default_icon.svg"; // 默认图标 - - // 获取包文件列表 - dpkgProcess.start("dpkg", QStringList() << "-L" << packageName); - dpkgProcess.waitForFinished(); - QStringList files = QString(dpkgProcess.readAllStandardOutput()).split('\n', Qt::SkipEmptyParts); - - // 查找.desktop文件 - QStringList desktopFiles = files.filter(QRegularExpression("/(usr/share|opt/apps)/.*\\.desktop$")); - - // 从.desktop文件中提取图标 - foreach (const QString &desktopFile, desktopFiles) { - QFile file(desktopFile); - if (file.open(QIODevice::ReadOnly | QIODevice::Text)) { - QTextStream in(&file); - while (!in.atEnd()) { - QString line = in.readLine().trimmed(); - if (line.startsWith("Icon=")) { - QString iconName = line.mid(5).trimmed(); - - // 处理相对图标名(如Icon=vscode) - if (!iconName.contains('/')) { - // 查找标准图标路径 - QStringList iconPaths = { - QString("/usr/share/pixmaps/%1.png").arg(iconName), - QString("/usr/share/icons/hicolor/48x48/apps/%1.png").arg(iconName), - QString("/usr/share/icons/hicolor/scalable/apps/%1.svg").arg(iconName), - QString("/opt/apps/%1/entries/icons/hicolor/48x48/apps/%2.png").arg(packageName, iconName) - }; - - foreach (const QString &path, iconPaths) { - if (QFile::exists(path)) { - iconPath = path; - break; - } - } - } else { - // 已经是绝对路径 - if (QFile::exists(iconName)) { - iconPath = iconName; - } - } - break; - } - } - file.close(); - } - } - - // 如果.desktop中没有找到图标,尝试直接查找包中的图标文件 - if (iconPath == ":/resources/default_icon.svg") { - QStringList iconFiles = files.filter(QRegularExpression("/(usr/share/pixmaps|usr/share/icons|opt/apps/.*/entries/icons)/.*\\.(png|svg)$")); - if (!iconFiles.isEmpty()) { - iconPath = iconFiles.first(); - } - } - - qDebug() << "包名:" << packageName << "图标路径:" << iconPath; - packageIcons << QString("%1: %2").arg(packageName, iconPath); - } - - return packageIcons; -} - - -QJsonArray aptssUpdater::getUpdateInfoAsJson() -{ - QJsonArray jsonArray; - - // 获取所有需要的信息 - QStringList sizes = getPackageSizes(); - QStringList names = getDesktopAppNames(); - QStringList icons = getPackageIcons(); - - // 创建包名到各种信息的映射 - QHash> packageInfo; - - // 解析包版本信息 - for (const QString &pkg : packageName) { - QStringList parts = pkg.split(": "); - if (parts.size() >= 2) { - QString packageName = parts[0]; - QStringList versions = parts[1].split(" → "); - if (versions.size() == 2) { - packageInfo[packageName]["current_version"] = versions[0]; - packageInfo[packageName]["new_version"] = versions[1]; - } - } - } - - // 解析包详细信息(新增部分) - for (const QString &sizeInfo : sizes) { - QStringList parts = sizeInfo.split(": "); - if (parts.size() == 2) { - QString packageName = parts[0]; - QStringList details = parts[1].split("|"); - if (details.size() == 3) { // 现在包含大小|URL|SHA512 - packageInfo[packageName]["size"] = details[0]; - packageInfo[packageName]["url"] = details[1]; - packageInfo[packageName]["sha512"] = details[2]; - } - } - } - - // 解析应用名称信息 - for (const QString &nameInfo : names) { - if (nameInfo.startsWith("[") && nameInfo.endsWith("]")) { - QString content = nameInfo.mid(1, nameInfo.length() - 2); - QStringList parts = content.split("|"); - if (parts.size() == 2) { - QString displayName = parts[0]; - QString packageName = parts[1]; - packageInfo[packageName]["display_name"] = displayName; - } - } - } - - // 解析图标信息 - for (const QString &iconInfo : icons) { - QStringList parts = iconInfo.split(": "); - if (parts.size() == 2) { - QString packageName = parts[0]; - packageInfo[packageName]["icon"] = parts[1].trimmed(); - } - } - - // 构建JSON数组 - for (const QString &packageName : packageInfo.keys()) { - QJsonObject jsonObj; - jsonObj["package"] = packageName; - - // 使用显示名称(如果有),否则使用包名 - if (packageInfo[packageName].contains("display_name")) { - jsonObj["name"] = packageInfo[packageName]["display_name"]; - } else { - jsonObj["name"] = packageName; - } - - jsonObj["current_version"] = packageInfo[packageName]["current_version"]; - jsonObj["new_version"] = packageInfo[packageName]["new_version"]; - jsonObj["icon"] = packageInfo[packageName]["icon"]; - jsonObj["ignored"] = false; // 默认不忽略 - - // 如果有大小信息也加入 - if (packageInfo[packageName].contains("size")) { - jsonObj["size"] = packageInfo[packageName]["size"]; - } - - // 在构建JSON对象时添加新字段(在jsonObj中添加): - if (packageInfo[packageName].contains("url")) { - jsonObj["download_url"] = packageInfo[packageName]["url"]; - qDebug() << "生成的下载 URL:" << packageInfo[packageName]["url"]; // 检查生成的 URL - } else { - qWarning() << "未找到下载 URL,包名:" << packageName; - jsonObj["download_url"] = ""; // 设置为空字符串以避免崩溃 - } - jsonObj["sha512"] = packageInfo[packageName]["sha512"]; - jsonArray.append(jsonObj); - } - qDebug()< -#include -#include -#include -#include -#include -class aptssUpdater : public QWidget -{ - Q_OBJECT -public: - explicit aptssUpdater(QWidget *parent = nullptr); - - QStringList getUpdateablePackages(); // 查询可更新包列表及更新内容 - QStringList getPackageSizes(); // 获取每个包的大小 - QStringList getDesktopAppNames(); // 获取桌面应用名称列表 - QStringList getPackageIcons(); // 获取包图标列表 - QJsonArray getUpdateInfoAsJson(); // 获取更新信息的 JSON 格式 - QString m_tempFilePath; -signals: -private: - bool checkDesktopFiles(const QStringList &desktopFiles, QString &appName, const QString &lang, const QString &packageName); - QStringList packageName; -}; - -#endif // APTSSUPDATER_H \ No newline at end of file diff --git a/update-tool/src/downloadmanager.cpp b/update-tool/src/downloadmanager.cpp deleted file mode 100644 index 97803249..00000000 --- a/update-tool/src/downloadmanager.cpp +++ /dev/null @@ -1,117 +0,0 @@ -#include "downloadmanager.h" -#include -#include -#include -#include -#include - -DownloadManager::DownloadManager(QObject *parent) : QObject(parent) -{ - cleanupTempFiles(); -} - -void DownloadManager::startDownload(const QString &packageName, const QString &url, const QString &outputPath) -{ - if (m_processes.contains(packageName)) { - qWarning() << packageName << " is already downloading."; - return; - } - - QString metalinkUrl = url + ".metalink"; - QFileInfo fileInfo(outputPath); - - QStringList arguments = { - "--enable-rpc=false", - "--console-log-level=warn", - "--summary-interval=1", - "--allow-overwrite=true", - "--dir=" + fileInfo.absolutePath(), - "--out=" + fileInfo.fileName(), - metalinkUrl - }; - - QProcess *process = new QProcess(this); - m_processes.insert(packageName, process); - - // 新增:准备日志文件 - QString logPath = QString("/tmp/%1_download.log").arg(packageName); - QFile *logFile = new QFile(logPath, process); - if (logFile->open(QIODevice::Append | QIODevice::Text)) { - // 设置权限为777 - QFile::setPermissions(logPath, QFile::ReadOwner | QFile::WriteOwner | QFile::ExeOwner | - QFile::ReadGroup | QFile::WriteGroup | QFile::ExeGroup | - QFile::ReadOther | QFile::WriteOther | QFile::ExeOther); - connect(process, &QProcess::readyReadStandardOutput, this, [this, packageName, process, logFile]() { - while (process->canReadLine()) { - QString line = QString::fromUtf8(process->readLine()).trimmed(); - // 写入日志 - logFile->write(line.toUtf8() + '\n'); - logFile->flush(); - QRegularExpression regex(R"(\((\d+)%\))"); - QRegularExpressionMatch match = regex.match(line); - if (match.hasMatch()) { - int progress = match.captured(1).toInt(); - emit downloadProgress(packageName, progress); - } - } - }); - connect(process, &QProcess::readyReadStandardError, this, [process, logFile]() { - QByteArray err = process->readAllStandardError(); - logFile->write(err); - logFile->flush(); - }); - } - - connect(process, QOverload::of(&QProcess::finished), - this, [this, packageName, outputPath, logFile](int exitCode, QProcess::ExitStatus status) { - bool success = (exitCode == 0 && status == QProcess::NormalExit); - if (!success) { - qWarning() << "Download failed for" << packageName << "exit code:" << exitCode; - } - - removeAria2Files(outputPath); // 清理残留 .aria2 - emit downloadFinished(packageName, success); - - if (logFile) logFile->close(); - - QProcess *proc = m_processes.take(packageName); - if (proc) proc->deleteLater(); - }); - - process->start("aria2c", arguments); -} - -void DownloadManager::cancelDownload(const QString &packageName) -{ - if (!m_processes.contains(packageName)) return; - - QProcess *process = m_processes.take(packageName); - if (process) { - process->kill(); // 立即终止 - process->waitForFinished(3000); // 最多等待3秒 - process->deleteLater(); - } - - emit downloadFinished(packageName, false); // 显式通知取消 - -} - -void DownloadManager::removeAria2Files(const QString &filePath) -{ - QString ariaFile = filePath + ".aria2"; - QFile::remove(ariaFile); -} - -bool DownloadManager::isDownloading(const QString &packageName) const -{ - return m_processes.contains(packageName); -} - -void DownloadManager::cleanupTempFiles() -{ - QDir tempDir(QDir::tempPath()); - QStringList leftovers = tempDir.entryList(QStringList() << "*.aria2", QDir::Files); - for (const QString &f : leftovers) { - tempDir.remove(f); - } -} diff --git a/update-tool/src/downloadmanager.h b/update-tool/src/downloadmanager.h deleted file mode 100644 index 0614368a..00000000 --- a/update-tool/src/downloadmanager.h +++ /dev/null @@ -1,28 +0,0 @@ -#ifndef DOWNLOADMANAGER_H -#define DOWNLOADMANAGER_H - -#include -#include -#include - -class DownloadManager : public QObject -{ - Q_OBJECT -public: - explicit DownloadManager(QObject *parent = nullptr); - void startDownload(const QString &packageName, const QString &url, const QString &outputPath); - void cancelDownload(const QString &packageName); - bool isDownloading(const QString &packageName) const; - -signals: - void downloadProgress(const QString &packageName, int progress); - void downloadFinished(const QString &packageName, bool success); - -private: - void cleanupTempFiles(); - void removeAria2Files(const QString &filePath); - - QMap m_processes; -}; - -#endif // DOWNLOADMANAGER_H diff --git a/update-tool/src/icons.qrc b/update-tool/src/icons.qrc deleted file mode 100644 index f81e1f88..00000000 --- a/update-tool/src/icons.qrc +++ /dev/null @@ -1,8 +0,0 @@ - - - ../resources/down_arrow.svg - ../resources/default_icon.svg - ../resources/spark-update-tool.svg - ../resources/128*128/spark-update-tool.png - - diff --git a/update-tool/src/main.cpp b/update-tool/src/main.cpp deleted file mode 100644 index a3df5a43..00000000 --- a/update-tool/src/main.cpp +++ /dev/null @@ -1,86 +0,0 @@ -#include "mainwindow.h" -#include -#include -#include -#include // for geteuid -#include // for getenv -#include // For debugging output - -bool isRoot() { - return geteuid() == 0; -} - -bool elevateToRoot() { - QString program = QCoreApplication::applicationFilePath(); - qDebug() << "Current application path:" << program; - - QByteArray display = qgetenv("DISPLAY"); - QByteArray xauthority = qgetenv("XAUTHORITY"); - - QStringList args; - args << "env" - << "DISPLAY=" + display - << "XAUTHORITY=" + xauthority - << program; - - QProcess process; - process.setProgram("pkexec"); - process.setArguments(args); - - qDebug() << "Attempting to elevate using pkexec with arguments:" << args; - - process.start(); - if (!process.waitForStarted(5000)) { - qDebug() << "Failed to start pkexec."; - return false; - } - - // 阻塞等待提权进程退出(比如主程序窗口关闭) - if (!process.waitForFinished(-1)) { // 等待直到新进程退出 - qDebug() << "pkexec process waitForFinished failed."; - return false; - } - - int exitCode = process.exitCode(); - QProcess::ExitStatus exitStatus = process.exitStatus(); - - qDebug() << "pkexec exit code:" << exitCode; - qDebug() << "pkexec exit status:" << exitStatus; - qDebug() << "pkexec stderr:" << process.readAllStandardError(); - - return (exitStatus == QProcess::NormalExit && exitCode == 0); -} - -int main(int argc, char *argv[]) -{ - // 必须在 QGuiApplication 实例创建之前调用 - // QGuiApplication::setHighDpiScaleFactorRoundingPolicy(Qt::HighDpiScaleFactorRoundingPolicy::PassThrough); - - QApplication a(argc, argv); - a.setWindowIcon(QIcon(":/resources/128*128/spark-update-tool.png")); - if (!isRoot()) { - qDebug() << "Not running as root. Attempting to elevate..."; - if (!elevateToRoot()) { - qDebug() << "Elevation failed or pkexec command was not executed successfully."; - QMessageBox::critical(nullptr, - "权限不足", - "提权失败!\n\n您的系统可能不支持 `pkexec` 或 `polkit` 配置不正确," - "或者您取消了授权。\n\n请尝试使用 `sudo` 命令运行此程序:" - "\n\n在终端中输入:\n`sudo " + QCoreApplication::applicationName() + "`"); - return 0; // 提权失败,退出程序 - } else { - // 如果 elevateToRoot 返回 true,说明 pkexec 命令本身执行成功 - // 但这并不意味着原始程序以 root 权限启动了 - // 因为 elevateToRoot 启动的是一个新的进程,当前进程应该退出 - // 否则会并行运行两个程序实例 - qDebug() << "pkexec command executed successfully (new process likely started). Exiting current process."; - return 0; // 当前非root进程退出 - } - } else { - qDebug() << "Running as root."; - } - - MainWindow w; - w.show(); - return a.exec(); -} \ No newline at end of file diff --git a/update-tool/src/mainwindow.cpp b/update-tool/src/mainwindow.cpp deleted file mode 100644 index 102bda6f..00000000 --- a/update-tool/src/mainwindow.cpp +++ /dev/null @@ -1,268 +0,0 @@ -#include "mainwindow.h" -#include "./ui_mainwindow.h" -#include -#include -#include -#include // 新增 -#include // 新增 -#include -#include -MainWindow::MainWindow(QWidget *parent) - : QMainWindow(parent) - , ui(new Ui::MainWindow) - , m_model(new AppListModel(this)) - , m_delegate(new AppDelegate(this)) -{ - QIcon icon(":/resources/128*128/spark-update-tool.png"); - setWindowIcon(icon); - QProgressDialog *progressDialog = new QProgressDialog("正在与服务器通信,获取更新信息中...", QString(), 0, 0, this); - progressDialog->setWindowModality(Qt::ApplicationModal); - progressDialog->setCancelButton(nullptr); - progressDialog->setWindowTitle("请稍候"); - progressDialog->setMinimumDuration(0); - progressDialog->setWindowFlags(progressDialog->windowFlags() & ~Qt::WindowCloseButtonHint); // 禁用关闭按钮 - progressDialog->show(); - //异步执行runAptssUpgrade - QFutureWatcher *watcher = new QFutureWatcher(this); - connect(watcher, &QFutureWatcher::finished, this, [=]() { - progressDialog->close(); - progressDialog->deleteLater(); - watcher->deleteLater(); - ui->setupUi(this); - QIcon icon(":/resources/128*128/spark-update-tool.png"); - setWindowIcon(icon); - // 创建 QListView 并设置父控件为 ui->appWidget - listView = new QListView(ui->appWidget); - listView->setModel(m_model); - listView->setItemDelegate(m_delegate); - - // 新增:确保 delegate 拥有 model 指针 - m_delegate->setModel(m_model); - - // 设置 QListView 填充 ui->appWidget - QVBoxLayout *layout = new QVBoxLayout(ui->appWidget); - layout->addWidget(listView); - layout->setContentsMargins(0, 0, 0, 0); - connect(m_delegate, &AppDelegate::updateDisplay, this, [=](const QString &packageName) { - for (int i = 0; i < m_model->rowCount(); ++i) { - QModelIndex index = m_model->index(i); - if (index.data(Qt::UserRole + 1).toString() == packageName) { - m_model->dataChanged(index, index); // 刷新该行 - break; - } - } - }); - - // 新增:点击“更新全部”按钮批量下载 - connect(ui->updatePushButton, &QPushButton::clicked, this, [=](){ - qDebug()<<"更新全部按钮被点击"; - m_delegate->startDownloadForAll(); - }); - - checkUpdates(); - // 新增:监听搜索框文本变化 - connect(ui->searchPlainTextEdit, &QPlainTextEdit::textChanged, this, [=]() { - QString keyword = ui->searchPlainTextEdit->toPlainText(); - filterAppsByKeyword(keyword); - }); - initStyle(); - - // 确保搜索框内容为空,placeholder 能显示 - ui->searchPlainTextEdit->clear(); - }); - - // 启动异步任务 - watcher->setFuture(QtConcurrent::run([this](){ - runAptssUpgrade(); - })); - QScreen *screen = QGuiApplication::screenAt(QCursor::pos()); - if (!screen) screen = QGuiApplication::primaryScreen(); - QRect screenGeometry = screen->geometry(); - int x = screenGeometry.x() + (screenGeometry.width() - this->width()) / 2; - int y = screenGeometry.y() + (screenGeometry.height() - this->height()) / 2; - this->move(x, y); -} -//初始化控件样式 -void MainWindow::initStyle() -{ - //设置窗口标题 - this->setWindowTitle("软件更新中心"); - - //查询框样式 - ui->searchPlainTextEdit->setStyleSheet(R"( - QPlainTextEdit { - background-color: #FFFFFF; - border: 1px solid #E5E7EB; - border-radius: 4px; - padding-top: 8px; - padding-bottom: 8px; - font-size: 9px; - line-height: 1.4; - color: #9CA3AF; - } - QPlainTextEdit[placeholderText]:empty { - color: #9CA3AF; - } - )"); - - ui->searchPlainTextEdit->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff); - ui->searchPlainTextEdit->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); - - //筛选框样式 - ui->FilterComboBox->setStyleSheet(R"( - QComboBox { - background-color: #FFFFFF; - border: 1px solid #E5E7EB; - border-radius: 4px; - color: #4B5563; - padding: 4px 8px; - } - - QComboBox::drop-down { - border: none; - width: 20px; - } - - QComboBox::down-arrow { - image: url(:/resources/down_arrow.svg); - width: 12px; - height: 16px; - } - QComboBox QAbstractItemView { - background-color: #FFFFFF; - border: 1px solid #E5E7EB; - color: #4B5563; - selection-background-color: #F3F4F6; - selection-color: #111827; - } - )"); - - //更新软件按钮样式 - ui->updatePushButton->setStyleSheet(R"( - QPushButton { - background-color: #2563EB; - color: #FFFFFF; - border: none; - border-radius: 4px; - font-size: 14px; - padding: 6px 12px; - text-align: center; - } - - QPushButton:hover { - background-color: #1D4ED8; /* 深一点的 hover 效果,可选 */ - } - - QPushButton:pressed { - background-color: #1E40AF; /* 按下效果,可选 */ - } - - QPushButton:disabled { - background-color: #A5B4FC; - color: #F9FAFB; - } - )"); - - //设置背景填充颜色 - ui->backgroundWidget->setStyleSheet(R"( - QWidget { - background-color: #FFFFFF; - border-radius: 12px; - } - )"); - - //设置主背景颜色 - this->setStyleSheet("background-color: #F8FAFC;"); - - // 添加滚动条样式 - this->setStyleSheet(R"( - QScrollBar:vertical { - background: #F3F4F6; - width: 8px; - margin: 0px; - } - QScrollBar::handle:vertical { - background: #D1D5DB; - border-radius: 4px; - min-height: 30px; - } - QScrollBar::handle:vertical:hover { - background: #9CA3AF; - } - QScrollBar::add-line:vertical, QScrollBar::sub-line:vertical { - background: none; - height: 0px; - } - - QScrollBar:horizontal { - background: #F3F4F6; - height: 8px; - margin: 0px; - } - QScrollBar::handle:horizontal { - background: #D1D5DB; - border-radius: 4px; - min-width: 30px; - } - QScrollBar::handle:horizontal:hover { - background: #9CA3AF; - } - )"); -} -void MainWindow::checkUpdates() -{ - aptssUpdater updater; - QJsonArray updateInfo = updater.getUpdateInfoAsJson(); - m_allApps = updateInfo; // 保存所有应用数据 - m_model->setUpdateData(updateInfo); - - for (const auto &item : updateInfo) { - QJsonObject obj = item.toObject(); - qDebug() << "模型设置的包名:" << obj["package"].toString(); - qDebug() << "模型设置的下载 URL:" << obj["download_url"].toString(); // 检查模型数据 - } -} - -// 新增:根据关键字过滤应用 -void MainWindow::filterAppsByKeyword(const QString &keyword) -{ - if (keyword.trimmed().isEmpty()) { - m_model->setUpdateData(m_allApps); - return; - } - QJsonArray filtered; - for (const auto &item : m_allApps) { - QJsonObject obj = item.toObject(); - // 可根据需要匹配更多字段 - QString name = obj.value("name").toString(); - QString package = obj.value("package").toString(); - if (name.contains(keyword, Qt::CaseInsensitive) || - package.contains(keyword, Qt::CaseInsensitive)) { - filtered.append(item); - } - } - m_model->setUpdateData(filtered); -} - -void MainWindow::runAptssUpgrade() -{ - QProcess process; - QStringList args; - args << "sudo" <<"aptss" << "ssupdate"; - process.start("sudo", args); - if (!process.waitForStarted(5000)) { - QMessageBox::warning(this, "升级失败", "无法启动 sudo aptss ssupdate"); - return; - } - process.write("n\n"); - process.closeWriteChannel(); - process.waitForFinished(-1); - if (process.exitCode() != 0) { - QMessageBox::warning(this, "升级失败", "执行 sudo aptss ssupdate 失败,请检查系统环境。"); - } -} - -MainWindow::~MainWindow() -{ - delete ui; -} diff --git a/update-tool/src/mainwindow.h b/update-tool/src/mainwindow.h deleted file mode 100644 index bc7f9d72..00000000 --- a/update-tool/src/mainwindow.h +++ /dev/null @@ -1,36 +0,0 @@ -#ifndef MAINWINDOW_H -#define MAINWINDOW_H - -#include -#include "aptssupdater.h" -#include "applistmodel.h" -#include "appdelegate.h" -#include -#include // 添加头文件 - -QT_BEGIN_NAMESPACE -namespace Ui { -class MainWindow; -} -QT_END_NAMESPACE - -class MainWindow : public QMainWindow -{ - Q_OBJECT - -public: - MainWindow(QWidget *parent = nullptr); - ~MainWindow(); - -private: - Ui::MainWindow *ui; - void checkUpdates(); - void initStyle(); - void runAptssUpgrade(); - AppListModel *m_model; - AppDelegate *m_delegate; - QListView *listView; // 声明 QListView 指针 - QJsonArray m_allApps; // 新增:保存所有应用数据 - void filterAppsByKeyword(const QString &keyword); // 新增:搜索过滤函数声明 -}; -#endif // MAINWINDOW_H diff --git a/update-tool/src/mainwindow.ui b/update-tool/src/mainwindow.ui deleted file mode 100644 index a53a4b88..00000000 --- a/update-tool/src/mainwindow.ui +++ /dev/null @@ -1,256 +0,0 @@ - - - MainWindow - - - - 0 - 0 - 1440 - 858 - - - - MainWindow - - - - - - - - 0 - - - 0 - - - 0 - - - 0 - - - 0 - - - - - - Noto Sans Vai - 22 - - - - 软件更新中心 - - - - - - - Qt::Orientation::Horizontal - - - - 1245 - 20 - - - - - - - - - - - - - - - 0 - 0 - - - - - 0 - - - 0 - - - 0 - - - 0 - - - 0 - - - - - - 320 - 38 - - - - - 320 - 38 - - - - - 0 - - - 0 - - - 0 - - - 0 - - - 0 - - - - - - 200 - 38 - - - - - - - 81.000000000000000 - - - 搜索软件... - - - - - - - - - - Qt::Orientation::Horizontal - - - - 40 - 20 - - - - - - - - - 214 - 40 - - - - - 214 - 40 - - - - - - 0 - 0 - 102 - 38 - - - - - 102 - 38 - - - - - 102 - 38 - - - - - - - Qt::LayoutDirection::LeftToRight - - - QComboBox::SizeAdjustPolicy::AdjustToContentsOnFirstShow - - - - 按名称 - - - - - - - 118 - 0 - 96 - 40 - - - - 更新全部 - - - - - - - - - - - true - - - - 0 - 0 - - - - - - - - - - - - - 0 - 0 - 1440 - 23 - - - - - - - -- Gitee From 3c22d7cf5fc241a05e8c9c9af373fe72583a2d3f Mon Sep 17 00:00:00 2001 From: momen Date: Fri, 29 Aug 2025 23:23:59 +0800 Subject: [PATCH 031/105] =?UTF-8?q?update:=E6=9B=B4=E6=96=B0=E7=89=88?= =?UTF-8?q?=E6=9C=AC=E5=8F=B7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- debian/changelog | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/debian/changelog b/debian/changelog index 53324041..5bbbb5fb 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,9 @@ +spark-store (4.8.1~test2) UNRELEASED; urgency=medium + + * 修复了更新器安装完成后显示下载完成的bug + + -- momen Fri, 29 Aug 2025 01:03:08 +0800 + spark-store (4.8.1~test1) UNRELEASED; urgency=medium * 添加全新的更新器 -- Gitee From a7e45d37da8088ea0460104e2100d682e41c67ae Mon Sep 17 00:00:00 2001 From: momen Date: Tue, 9 Sep 2025 22:28:18 +0800 Subject: [PATCH 032/105] =?UTF-8?q?update:=E5=8A=A0=E5=85=A5QDebug?= =?UTF-8?q?=E5=A4=B4=E6=96=87=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/applistmodel.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/applistmodel.h b/src/applistmodel.h index 2fb36c0d..9e5e79ab 100644 --- a/src/applistmodel.h +++ b/src/applistmodel.h @@ -5,7 +5,7 @@ #include // 添加 QJsonObject 头文件 #include - +#include class AppListModel : public QAbstractListModel { Q_OBJECT -- Gitee From 964231a77feb2c6b92fd05faaafa61d111d13ae5 Mon Sep 17 00:00:00 2001 From: shenmo Date: Fri, 5 Sep 2025 13:26:30 +0000 Subject: [PATCH 033/105] Release 4.8.1 --- debian/changelog | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/debian/changelog b/debian/changelog index 5bbbb5fb..9e6ddfe1 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,4 +1,4 @@ -spark-store (4.8.1~test2) UNRELEASED; urgency=medium +spark-store (4.8.1) UNRELEASED; urgency=medium * 修复了更新器安装完成后显示下载完成的bug -- Gitee From ff97cd276981f811d1dbbbdc3324ae34f55126e5 Mon Sep 17 00:00:00 2001 From: shenmo Date: Fri, 5 Sep 2025 13:48:52 +0000 Subject: [PATCH 034/105] =?UTF-8?q?aptss=E6=94=AF=E6=8C=81=E5=9C=A8?= =?UTF-8?q?=E5=AE=89=E8=A3=85=E8=BD=AF=E4=BB=B6=E7=9A=84=E5=90=8C=E6=97=B6?= =?UTF-8?q?=E4=BD=BF=E7=94=A8download=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- tool/apt-fast/ss-apt-fast | 117 +++++++++++++++++++------------------- 1 file changed, 60 insertions(+), 57 deletions(-) diff --git a/tool/apt-fast/ss-apt-fast b/tool/apt-fast/ss-apt-fast index dea3648a..f1a07464 100755 --- a/tool/apt-fast/ss-apt-fast +++ b/tool/apt-fast/ss-apt-fast @@ -20,6 +20,13 @@ shopt -s nullglob # third argument are piped to stderr. THREADS=$(nproc 2>/dev/null || echo 4) + +# Set color variables. +cGreen='\e[0;32m' +cRed='\e[0;31m' +cBlue='\e[0;34m' +endColor='\e[0m' + msg(){ msg_options=() case "$2" in @@ -36,6 +43,51 @@ msg(){ echo -e "${msg_options[@]}" "${aptfast_prefix}${beginColor}$1${endColor}" >&2 fi } +msg_already_running() +{ + msg "Other aptss is running. Waited $timer senconds..." "normal" + msg "有其他的aptss正在运行。已经等待了$timer秒" "normal" +} + +# Check if a lock file exists. +#if [ -f "$LCK_FILE.lock" ]; then +# msg_already_running +# exit 1 +#fi + +LCK_FD=99 +# create the lock file and lock it, die on failure +_create_lock() +{ + eval "exec $LCK_FD>\"$LCK_FILE.lock\"" + + # 设置 trap 来清理资源 + trap "cleanup_aptfast" EXIT + trap "cleanup_aptfast; exit 1" INT TERM + + timer=0 + max_wait=180 # 最大等待时间为180秒(3分钟) + + until $(flock -xn $LCK_FD); do + msg_already_running + sleep 1 + let timer+=1 + + if [ $timer -ge $max_wait ]; then + echo "timeout" + exit 1 + fi + done + + unset timer +} + +# unlock and remove the lock file +_remove_lock() +{ + flock -u "$LCK_FD" 2>/dev/null + rm -f "$LCK_FILE.lock" +} # Search for known options and decide if root privileges are needed. root=$# @@ -44,6 +96,7 @@ for argument in "$@"; do case "$argument" in upgrade | full-upgrade | install | dist-upgrade | build-dep) option="install" + _create_lock ;; clean | autoclean) option="clean" @@ -122,7 +175,7 @@ LCK_FILE="/tmp/apt-fast-in-container.lock" else LCK_FILE="/tmp/apt-fast.lock" fi -LCK_FD=99 + # Set default package manager, APT cache, temporary download dir, # temporary download list file, and maximal parallel downloads @@ -145,11 +198,9 @@ if [ -f "$NETRC" ]; then fi APTAUTHFILES+=("$NETRCDIR"*) -if [ "$IS_ACE_ENV" != "" ];then -DLLIST="/tmp/apt-fast-in-container.list" -else -DLLIST="/tmp/apt-fast.list" -fi +LISTTEMP=$(mktemp -d) +DLLIST="${LISTTEMP}/apt-fast.list" + @@ -164,11 +215,7 @@ MIRRORS=() aptfast_prefix= # aptfast_prefix="$(date '+%b %_d %T.%N') apt-fast: " -# Set color variables. -cGreen='\e[0;32m' -cRed='\e[0;31m' -cBlue='\e[0;34m' -endColor='\e[0m' + # Set timout value for apt-fast download confirmation dialog. # Value is in seconds. @@ -240,51 +287,7 @@ if [ ! -t 1 ]; then fi -msg_already_running() -{ - msg "Other aptss is running. Waited $timer senconds..." "normal" - msg "有其他的aptss正在运行。已经等待了$timer秒" "normal" -} - -# Check if a lock file exists. -#if [ -f "$LCK_FILE.lock" ]; then -# msg_already_running -# exit 1 -#fi - - -# create the lock file and lock it, die on failure -_create_lock() -{ - eval "exec $LCK_FD>\"$LCK_FILE.lock\"" - - # 设置 trap 来清理资源 - trap "cleanup_aptfast" EXIT - trap "cleanup_aptfast; exit 1" INT TERM - - timer=0 - max_wait=180 # 最大等待时间为180秒(3分钟) - until $(flock -xn $LCK_FD); do - msg_already_running - sleep 1 - let timer+=1 - - if [ $timer -ge $max_wait ]; then - echo "timeout" - exit 1 - fi - done - - unset timer -} - -# unlock and remove the lock file -_remove_lock() -{ - flock -u "$LCK_FD" 2>/dev/null - rm -f "$LCK_FILE.lock" -} # Move download file away so missing permissions won't stop usage. CLEANUP_STATE=0 @@ -294,7 +297,7 @@ cleanup_dllist() then if ! mv -- "$DLLIST{,.old}" 2>/dev/null then - if ! rm -f -- "$DLLIST" 2>/dev/null + if ! rm -fr -- "${LISTTEMP}" 2>/dev/null then msg "Could not clean up download list file." "warning" msg "无法清除下载列表文件." "warning" @@ -608,7 +611,7 @@ display_downloadfile(){ # Create and insert a PID number to lockfile. -_create_lock + # Make sure aria2c (in general first parameter from _DOWNLOADER) is available. CMD="$(echo "$_DOWNLOADER" | sed 's/^\s*\([^ ]\+\).*$/\1/')" -- Gitee From 083674f6a5ea2040a7b14331b06b9d6ac3e4c6a4 Mon Sep 17 00:00:00 2001 From: shenmo Date: Sat, 6 Sep 2025 05:10:41 +0000 Subject: [PATCH 035/105] update spark-update-tool/CMakeLists.txt. Signed-off-by: shenmo --- spark-update-tool/CMakeLists.txt | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/spark-update-tool/CMakeLists.txt b/spark-update-tool/CMakeLists.txt index 6c624b41..8b9a2d7b 100644 --- a/spark-update-tool/CMakeLists.txt +++ b/spark-update-tool/CMakeLists.txt @@ -17,17 +17,21 @@ set(PROJECT_SOURCES src/mainwindow.cpp src/mainwindow.h src/mainwindow.ui + src/aptssupdater.h + src/aptssupdater.cpp + src/appdelegate.h # 添加这一行 + src/appdelegate.cpp # 添加这一行 + src/applistmodel.h + src/applistmodel.cpp + src/downloadmanager.h + src/downloadmanager.cpp ) if(${QT_VERSION_MAJOR} GREATER_EQUAL 6) qt_add_executable(spark-update-tool MANUAL_FINALIZATION ${PROJECT_SOURCES} - src/aptssupdater.h src/aptssupdater.cpp src/icons.qrc - src/appdelegate.h src/appdelegate.cpp - src/applistmodel.h src/applistmodel.cpp - src/downloadmanager.h src/downloadmanager.cpp ) # Define target properties for Android with Qt 6 as: # set_property(TARGET spark-update-tool APPEND PROPERTY QT_ANDROID_PACKAGE_SOURCE_DIR @@ -72,4 +76,4 @@ install(TARGETS spark-update-tool if(QT_VERSION_MAJOR EQUAL 6) qt_finalize_executable(spark-update-tool) -endif() +endif() \ No newline at end of file -- Gitee From 62da8242633437d7e6b1aa5be9b97f4a8be55e4b Mon Sep 17 00:00:00 2001 From: shenmo Date: Sat, 6 Sep 2025 14:57:24 +0000 Subject: [PATCH 036/105] =?UTF-8?q?aptss=E9=97=AE=E9=A2=98=E4=BF=AE?= =?UTF-8?q?=E5=A4=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: shenmo --- debian/changelog | 2 +- tool/apt-fast/ss-apt-fast | 60 +++++++++++++++++++-------------------- 2 files changed, 31 insertions(+), 31 deletions(-) diff --git a/debian/changelog b/debian/changelog index 9e6ddfe1..0a3cdf3b 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,4 +1,4 @@ -spark-store (4.8.1) UNRELEASED; urgency=medium +spark-store (4.8.1-1) UNRELEASED; urgency=medium * 修复了更新器安装完成后显示下载完成的bug diff --git a/tool/apt-fast/ss-apt-fast b/tool/apt-fast/ss-apt-fast index f1a07464..2832d5bd 100755 --- a/tool/apt-fast/ss-apt-fast +++ b/tool/apt-fast/ss-apt-fast @@ -55,6 +55,36 @@ msg_already_running() # exit 1 #fi +# Move download file away so missing permissions won't stop usage. +CLEANUP_STATE=0 +cleanup_dllist() +{ + if [ -f "$DLLIST" ] + then + if ! mv -- "$DLLIST{,.old}" 2>/dev/null + then + if ! rm -fr -- "${LISTTEMP}" 2>/dev/null + then + msg "Could not clean up download list file." "warning" + msg "无法清除下载列表文件." "warning" + CLEANUP_STATE=1 + fi + fi + fi +} + +cleanup_aptfast() +{ + local last_exit_code=$? + [ "$CLEANUP_STATE" -eq 0 ] && CLEANUP_STATE=$last_exit_code + cleanup_dllist + _remove_lock +} + +exit_cleanup_state() +{ + exit $CLEANUP_STATE +} LCK_FD=99 # create the lock file and lock it, die on failure _create_lock() @@ -289,36 +319,6 @@ fi -# Move download file away so missing permissions won't stop usage. -CLEANUP_STATE=0 -cleanup_dllist() -{ - if [ -f "$DLLIST" ] - then - if ! mv -- "$DLLIST{,.old}" 2>/dev/null - then - if ! rm -fr -- "${LISTTEMP}" 2>/dev/null - then - msg "Could not clean up download list file." "warning" - msg "无法清除下载列表文件." "warning" - CLEANUP_STATE=1 - fi - fi - fi -} - -cleanup_aptfast() -{ - local last_exit_code=$? - [ "$CLEANUP_STATE" -eq 0 ] && CLEANUP_STATE=$last_exit_code - cleanup_dllist - _remove_lock -} - -exit_cleanup_state() -{ - exit $CLEANUP_STATE -} # decode url string # translates %xx but must not convert '+' in spaces -- Gitee From f07ca5aac03b9d0961ea3c7f2d444eaa893cf0bb Mon Sep 17 00:00:00 2001 From: momen Date: Wed, 10 Sep 2025 22:52:24 +0800 Subject: [PATCH 037/105] =?UTF-8?q?update:=E6=94=B9=E7=94=A8qtimer?= =?UTF-8?q?=E6=9D=A5=E5=88=B7=E6=96=B0=E5=8A=A0=E8=BD=BD=E8=BD=AC=E5=9C=88?= =?UTF-8?q?=E5=8A=A8=E7=94=BB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/appdelegate.cpp | 43 ++++++++++++++++++++++--------------------- src/appdelegate.h | 16 ++++++++++++---- 2 files changed, 34 insertions(+), 25 deletions(-) diff --git a/src/appdelegate.cpp b/src/appdelegate.cpp index 0c930657..77209946 100644 --- a/src/appdelegate.cpp +++ b/src/appdelegate.cpp @@ -7,6 +7,7 @@ #include #include #include +#include AppDelegate::AppDelegate(QObject *parent) : QStyledItemDelegate(parent), m_downloadManager(new DownloadManager(this)), m_installProcess(nullptr) { @@ -31,7 +32,11 @@ AppDelegate::AppDelegate(QObject *parent) emit updateDisplay(packageName); // 实时刷新进度条 } }); - m_spinnerTimer.start(); + // m_spinnerTimer.start(); // 移除这行 + + // 新增:初始化和连接 QTimer + m_spinnerUpdateTimer.setInterval(20); // 刷新间隔,可以调整 + connect(&m_spinnerUpdateTimer, &QTimer::timeout, this, &AppDelegate::updateSpinner); } void AppDelegate::setModel(QAbstractItemModel *model) { @@ -100,24 +105,23 @@ void AppDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, c progressBarOption.textVisible = true; QApplication::style()->drawControl(QStyle::CE_ProgressBar, &progressBarOption, painter); - // 修改后的取消按钮绘制代码 QRect buttonRect(rect.right() - 80, rect.top() + (rect.height() - 30) / 2, 70, 30); painter->setPen(Qt::NoPen); - painter->setBrush(QColor("#ff4444")); // 红色背景 - painter->drawRoundedRect(buttonRect, 4, 4); // 圆角矩形 + painter->setBrush(QColor("#ff4444")); + painter->drawRoundedRect(buttonRect, 4, 4); - painter->setPen(Qt::white); // 白色文字 + painter->setPen(Qt::white); painter->setFont(option.font); painter->drawText(buttonRect, Qt::AlignCenter, "取消"); } else if (isInstalling) { - // 安装中:显示转圈和文字 QRect spinnerRect(option.rect.right() - 80, option.rect.top() + (option.rect.height() - 30) / 2, 30, 30); - int angle = (m_spinnerTimer.elapsed() / 10) % 360; + + // 修改:使用 m_spinnerAngle QPen pen(QColor("#2563EB"), 3); painter->setPen(pen); painter->setRenderHint(QPainter::Antialiasing, true); QRectF arcRect = spinnerRect.adjusted(3, 3, -3, -3); - painter->drawArc(arcRect, angle * 16, 120 * 16); // 120度弧 + painter->drawArc(arcRect, m_spinnerAngle * 16, 120 * 16); // 120度弧 QRect textRect(option.rect.right() - 120, option.rect.top() + (option.rect.height() - 30) / 2, 110, 30); painter->setPen(QColor("#2563EB")); @@ -132,12 +136,10 @@ void AppDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, c painter->setPen(Qt::white); painter->drawText(buttonRect, Qt::AlignCenter, "已安装"); } else if (m_downloads.contains(packageName) && !m_downloads[packageName].isDownloading) { - // 下载完成,按钮绿色,样式不变 painter->setBrush(QColor("#10B981")); painter->drawRoundedRect(buttonRect, 4, 4); painter->setPen(Qt::white); painter->drawText(buttonRect, Qt::AlignCenter, "下载完成"); - // 不需要特殊处理样式,交互在 editorEvent 控制 } else { painter->setBrush(QColor("#e9effd")); painter->drawRoundedRect(buttonRect, 4, 4); @@ -171,9 +173,7 @@ bool AppDelegate::editorEvent(QEvent *event, QAbstractItemModel *model, } else { QRect buttonRect(rect.right() - 80, rect.top() + (rect.height() - 30) / 2, 70, 30); if (buttonRect.contains(mouseEvent->pos())) { - // 判断是否为“下载完成”状态,如果是则不响应点击 if (m_downloads.contains(packageName) && !m_downloads[packageName].isDownloading) { - // “下载完成”状态,按钮失效,点击无效 return false; } QString downloadUrl = index.data(Qt::UserRole + 7).toString(); @@ -196,7 +196,7 @@ void AppDelegate::startDownloadForAll() { QModelIndex index = m_model->index(row, 0); QString packageName = index.data(Qt::UserRole + 1).toString(); if (m_downloads.contains(packageName) && (m_downloads[packageName].isDownloading || m_downloads[packageName].isInstalled)) - continue; // 跳过正在下载或已安装的 + continue; QString downloadUrl = index.data(Qt::UserRole + 7).toString(); QString outputPath = QString("%1/%2.metalink").arg(QDir::tempPath(), packageName); m_downloads[packageName] = {0, true, false}; @@ -205,7 +205,6 @@ void AppDelegate::startDownloadForAll() { } } -// 新增:安装队列相关实现 void AppDelegate::enqueueInstall(const QString &packageName) { m_installQueue.enqueue(packageName); if (!m_isInstalling) { @@ -217,15 +216,16 @@ void AppDelegate::startNextInstall() { if (m_installQueue.isEmpty()) { m_isInstalling = false; m_installingPackage.clear(); + m_spinnerUpdateTimer.stop(); // 新增:停止定时器 return; } m_isInstalling = true; QString packageName = m_installQueue.dequeue(); m_installingPackage = packageName; m_downloads[packageName].isInstalling = true; + m_spinnerUpdateTimer.start(); // 新增:启动定时器 emit updateDisplay(packageName); - // 查找 /tmp 下以包名开头的 .deb 文件 QDir tempDir(QDir::tempPath()); QStringList debs = tempDir.entryList(QStringList() << QString("%1_*.deb").arg(packageName), QDir::Files); QString debPath; @@ -249,11 +249,9 @@ void AppDelegate::startNextInstall() { m_installProcess = new QProcess(this); - // 新增:准备安装日志文件 QString logPath = QString("/tmp/%1_install.log").arg(packageName); QFile *logFile = new QFile(logPath, m_installProcess); if (logFile->open(QIODevice::Append | QIODevice::Text)) { - // 设置权限为777 QFile::setPermissions(logPath, QFile::ReadOwner | QFile::WriteOwner | QFile::ExeOwner | QFile::ReadGroup | QFile::WriteGroup | QFile::ExeGroup | QFile::ReadOther | QFile::WriteOther | QFile::ExeOther); @@ -263,7 +261,6 @@ void AppDelegate::startNextInstall() { logFile->flush(); QString text = QString::fromLocal8Bit(out); qDebug().noquote() << text; - // 检查“软件包已安装”关键字 if (text.contains(QStringLiteral("软件包已安装"))) { m_downloads[packageName].isInstalling = false; m_downloads[packageName].isInstalled = true; @@ -281,7 +278,7 @@ void AppDelegate::startNextInstall() { if (logFile) logFile->close(); m_downloads[packageName].isInstalling = false; if (exitCode == 0) { - m_downloads[packageName].isInstalled = true; // 安装成功 + m_downloads[packageName].isInstalled = true; } emit updateDisplay(packageName); m_installProcess->deleteLater(); @@ -290,7 +287,6 @@ void AppDelegate::startNextInstall() { startNextInstall(); }); } else { - // 日志文件无法打开时,仍然要连接原有信号 connect(m_installProcess, &QProcess::readyReadStandardOutput, this, [this, packageName]() { QByteArray out = m_installProcess->readAllStandardOutput(); QString text = QString::fromLocal8Bit(out); @@ -315,8 +311,13 @@ void AppDelegate::startNextInstall() { }); } - // 注意参数顺序:deb路径在前,--no-create-desktop-entry在后 QStringList args; args << debPath << "--no-create-desktop-entry"; m_installProcess->start("ssinstall", args); } + +// 新增槽函数,用于更新旋转角度并触发刷新 +void AppDelegate::updateSpinner() { + m_spinnerAngle = (m_spinnerAngle + 10) % 360; // 每次增加10度 + emit updateDisplay(m_installingPackage); // 仅刷新当前正在安装的项 +} \ No newline at end of file diff --git a/src/appdelegate.h b/src/appdelegate.h index 0545155e..216d9be5 100644 --- a/src/appdelegate.h +++ b/src/appdelegate.h @@ -5,13 +5,15 @@ #include #include #include +#include + #include "downloadmanager.h" struct DownloadInfo { int progress = 0; bool isDownloading = false; bool isInstalled = false; - bool isInstalling = false; // 新增:标记是否正在安装 + bool isInstalling = false; }; class AppDelegate : public QStyledItemDelegate { @@ -30,6 +32,9 @@ public: signals: void updateDisplay(const QString &packageName); +private slots: + void updateSpinner(); // 新增槽函数 + private: DownloadManager *m_downloadManager; QHash m_downloads; @@ -38,9 +43,12 @@ private: QQueue m_installQueue; bool m_isInstalling = false; QProcess *m_installProcess = nullptr; - QString m_installingPackage; // 当前正在安装的包名 - QElapsedTimer m_spinnerTimer; // 用于转圈动画 + QString m_installingPackage; + QElapsedTimer m_spinnerTimer; + + QTimer m_spinnerUpdateTimer; // 新增定时器 + int m_spinnerAngle = 0; // 新增角度变量 void enqueueInstall(const QString &packageName); void startNextInstall(); -}; +}; \ No newline at end of file -- Gitee From 84c5897d9b74241fe82b12ad8e8c68d9230f1f6d Mon Sep 17 00:00:00 2001 From: momen Date: Thu, 11 Sep 2025 22:54:38 +0800 Subject: [PATCH 038/105] =?UTF-8?q?chore:=E6=9B=B4=E6=96=B0=E5=A4=B1?= =?UTF-8?q?=E8=B4=A5=E6=8F=90=E9=86=92=E5=86=85=E5=AE=B9=E6=9B=B4=E6=96=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/mainwindow.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index 102bda6f..23dd3798 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -258,7 +258,7 @@ void MainWindow::runAptssUpgrade() process.closeWriteChannel(); process.waitForFinished(-1); if (process.exitCode() != 0) { - QMessageBox::warning(this, "升级失败", "执行 sudo aptss ssupdate 失败,请检查系统环境。"); + QMessageBox::warning(this, "升级失败", "执行 sudo aptss ssupdate 失败,请检查系统环境或稍后再试。"); } } -- Gitee From a78ee36ae7e0e78ee5963025449b7423d87598cf Mon Sep 17 00:00:00 2001 From: momen Date: Fri, 12 Sep 2025 23:18:17 +0800 Subject: [PATCH 039/105] =?UTF-8?q?chore:=E7=BB=99=E5=85=B3=E9=97=AD?= =?UTF-8?q?=E7=AA=97=E5=8F=A3=E6=B7=BB=E5=8A=A0=E8=AF=A2=E9=97=AE=E4=BA=8B?= =?UTF-8?q?=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/mainwindow.cpp | 4 ++++ src/mainwindow.h | 3 +++ 2 files changed, 7 insertions(+) diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index 23dd3798..466a730b 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -261,7 +261,11 @@ void MainWindow::runAptssUpgrade() QMessageBox::warning(this, "升级失败", "执行 sudo aptss ssupdate 失败,请检查系统环境或稍后再试。"); } } +void MainWindow::closeEvent(QCloseEvent *event) +{ + QMessageBox::StandardButton reply = QMessageBox::question(this, "确认关闭", "正在更新,是否确认关闭窗口?", QMessageBox::Yes | QMessageBox::No); +} MainWindow::~MainWindow() { delete ui; diff --git a/src/mainwindow.h b/src/mainwindow.h index d754b5f7..b587750c 100644 --- a/src/mainwindow.h +++ b/src/mainwindow.h @@ -22,6 +22,9 @@ public: MainWindow(QWidget *parent = nullptr); ~MainWindow(); +protected: + void closeEvent(QCloseEvent *event) override; + private: Ui::MainWindow *ui; void checkUpdates(); -- Gitee From 6799dff2c5f4479e69ba83c47755b00f5676b365 Mon Sep 17 00:00:00 2001 From: momen Date: Sat, 13 Sep 2025 18:16:58 +0800 Subject: [PATCH 040/105] =?UTF-8?q?update:=E5=8A=A0=E5=85=A5=E6=A3=80?= =?UTF-8?q?=E6=B5=8B=E6=9B=B4=E6=96=B0=E4=BF=A1=E5=8F=B7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/appdelegate.h | 1 + src/mainwindow.cpp | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/appdelegate.h b/src/appdelegate.h index 216d9be5..579b8739 100644 --- a/src/appdelegate.h +++ b/src/appdelegate.h @@ -31,6 +31,7 @@ public: signals: void updateDisplay(const QString &packageName); + void updateFinished(bool success); //传递是否完成更新 private slots: void updateSpinner(); // 新增槽函数 diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index 466a730b..2c43e9eb 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -264,7 +264,7 @@ void MainWindow::runAptssUpgrade() void MainWindow::closeEvent(QCloseEvent *event) { - QMessageBox::StandardButton reply = QMessageBox::question(this, "确认关闭", "正在更新,是否确认关闭窗口?", QMessageBox::Yes | QMessageBox::No); + QMessageBox::StandardButton reply = QMessageBox::question(this, "确认关闭", "正在更新,是否确认关闭窗口?", QMessageBox::Yes | QMessageBox::No); } MainWindow::~MainWindow() { -- Gitee From 95ee0f538130d199970acd4e8486b70f4bea507e Mon Sep 17 00:00:00 2001 From: momen Date: Sun, 14 Sep 2025 23:29:33 +0800 Subject: [PATCH 041/105] =?UTF-8?q?chore:=E6=B7=BB=E5=8A=A0=E6=A7=BD?= =?UTF-8?q?=E5=87=BD=E6=95=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/mainwindow.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/mainwindow.h b/src/mainwindow.h index b587750c..41002cd9 100644 --- a/src/mainwindow.h +++ b/src/mainwindow.h @@ -24,7 +24,9 @@ public: protected: void closeEvent(QCloseEvent *event) override; - +private slots: + // ⬅️ 声明一个槽函数,它将接收来自Updater的信号 + void handleUpdateFinished(bool success); private: Ui::MainWindow *ui; void checkUpdates(); -- Gitee From a44131b9c846d73e0af187efcc8af325e237522e Mon Sep 17 00:00:00 2001 From: momen Date: Mon, 15 Sep 2025 19:34:20 +0800 Subject: [PATCH 042/105] =?UTF-8?q?chore:=E8=AE=BE=E7=BD=AE=E7=95=8C?= =?UTF-8?q?=E9=9D=A2=E6=B7=BB=E5=8A=A0=E5=AF=BC=E5=87=BA=E6=97=A5=E5=BF=97?= =?UTF-8?q?=E6=8C=89=E9=92=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/pages/settingspage.ui | 70 ++++++++++++++++++++++++++++++++++----- 1 file changed, 61 insertions(+), 9 deletions(-) diff --git a/src/pages/settingspage.ui b/src/pages/settingspage.ui index 28609ae2..a3d53d56 100644 --- a/src/pages/settingspage.ui +++ b/src/pages/settingspage.ui @@ -32,10 +32,10 @@ - QFrame::StyledPanel + QFrame::Shape::StyledPanel - QFrame::Raised + QFrame::Shadow::Raised @@ -59,7 +59,7 @@ - QFrame::NoFrame + QFrame::Shape::NoFrame 0 @@ -72,8 +72,8 @@ 0 0 - 688 - 940 + 666 + 1123 @@ -147,7 +147,7 @@ - Qt::Horizontal + Qt::Orientation::Horizontal @@ -166,7 +166,7 @@ - Qt::Horizontal + Qt::Orientation::Horizontal @@ -295,7 +295,7 @@ - Qt::Horizontal + Qt::Orientation::Horizontal @@ -338,6 +338,58 @@ + + + + + + + + 18 + false + + + + Log + + + + + + + + + + Export Logs:/tmp/spark-store + + + + + + + Export + + + + + + + Qt::Orientation::Horizontal + + + + 351 + 20 + + + + + + + + + + @@ -372,7 +424,7 @@ - Qt::Vertical + Qt::Orientation::Vertical -- Gitee From b3cd99ac51fbb06898bd7ff1531c638c6d51d016 Mon Sep 17 00:00:00 2001 From: momen Date: Mon, 15 Sep 2025 19:35:47 +0800 Subject: [PATCH 043/105] =?UTF-8?q?chore:=E5=B0=86=E5=AF=BC=E5=87=BA?= =?UTF-8?q?=E6=97=A5=E5=BF=97=E6=8C=89=E9=92=AE=E5=8F=98=E9=87=8F=E5=90=8D?= =?UTF-8?q?=E6=94=B9=E4=B8=BApushButton=5FexportLog?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/pages/settingspage.ui | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pages/settingspage.ui b/src/pages/settingspage.ui index a3d53d56..85fef3c0 100644 --- a/src/pages/settingspage.ui +++ b/src/pages/settingspage.ui @@ -365,7 +365,7 @@ - + Export -- Gitee From c0811ef6d2f57a6c67099fe9afb15a9efeea8b94 Mon Sep 17 00:00:00 2001 From: momen Date: Tue, 16 Sep 2025 23:52:26 +0800 Subject: [PATCH 044/105] =?UTF-8?q?chore:=E5=8A=A0=E5=85=A5=E5=85=B3?= =?UTF-8?q?=E9=97=ADweb=E6=B2=99=E7=AE=B1=E6=8C=89=E9=92=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/pages/settingspage.ui | 55 +++++++++++++++++++++++++++++++++++++-- 1 file changed, 53 insertions(+), 2 deletions(-) diff --git a/src/pages/settingspage.ui b/src/pages/settingspage.ui index 85fef3c0..8ad67858 100644 --- a/src/pages/settingspage.ui +++ b/src/pages/settingspage.ui @@ -71,9 +71,9 @@ 0 - 0 + -131 666 - 1123 + 1270 @@ -390,6 +390,57 @@ + + + + + + + + 18 + + + + Safe Mode + + + + + + + + + + close the Web Sandbox + + + + + + + ON + + + + + + + Qt::Orientation::Horizontal + + + + 424 + 20 + + + + + + + + + + -- Gitee From 6b67f0ec0acc4df0f499f1a1ce55db7ff8e1c895 Mon Sep 17 00:00:00 2001 From: momen Date: Wed, 17 Sep 2025 22:09:47 +0800 Subject: [PATCH 045/105] =?UTF-8?q?chore:=E6=9B=B4=E6=96=B0=E5=85=B3?= =?UTF-8?q?=E9=97=ADweb=E6=B2=99=E7=AE=B1=E6=96=87=E6=9C=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/pages/settingspage.ui | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/pages/settingspage.ui b/src/pages/settingspage.ui index 8ad67858..af0c20f9 100644 --- a/src/pages/settingspage.ui +++ b/src/pages/settingspage.ui @@ -71,7 +71,7 @@ 0 - -131 + -434 666 1270 @@ -401,7 +401,7 @@ - Safe Mode + Disable Safe Mode @@ -411,14 +411,14 @@ - close the Web Sandbox + Disable the webEngine sandbox feature. - + - ON + Disable -- Gitee From 161b268c245fcba4955f1ecd2e05bcb7ee111907 Mon Sep 17 00:00:00 2001 From: momen Date: Thu, 18 Sep 2025 23:43:24 +0800 Subject: [PATCH 046/105] =?UTF-8?q?chore:=E6=9B=B4=E6=96=B0=E7=89=88?= =?UTF-8?q?=E6=9C=AC=E4=BF=A1=E6=81=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- debian/changelog | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/debian/changelog b/debian/changelog index 0a3cdf3b..c47c7cde 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,8 @@ +spark-store (4.8.2~test1) UNRELEASED; urgency=medium + + * 增加导出日志功能。 + -- momen Tur, 18 Sep 2025 01:03:08 +0800 + spark-store (4.8.1-1) UNRELEASED; urgency=medium * 修复了更新器安装完成后显示下载完成的bug -- Gitee From be6fb10019bc3220db338aec0aa2b30f994ac08f Mon Sep 17 00:00:00 2001 From: momen Date: Fri, 19 Sep 2025 20:11:49 +0800 Subject: [PATCH 047/105] =?UTF-8?q?chore:=E6=A3=80=E6=B5=8Bconfig.ini?= =?UTF-8?q?=E6=98=AF=E5=90=A6=E5=AF=B9webengine=E6=B2=99=E7=AE=B1=E6=9C=89?= =?UTF-8?q?=E8=A6=81=E6=B1=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/utils/utils.cpp | 15 +++++++++++++++ src/utils/utils.h | 3 ++- 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/src/utils/utils.cpp b/src/utils/utils.cpp index 7d270544..c00d0a0d 100644 --- a/src/utils/utils.cpp +++ b/src/utils/utils.cpp @@ -261,3 +261,18 @@ QJsonObject Utils::parseFeatureJsonFile() return jsonDoc.object(); } + +/** + * @brief Utils::shouldDisableWebEngineSandbox 检查是否应关闭webengine沙箱 + * @return bool true: 配置文件中设置了关闭沙箱 false: 未设置或设置为false + */ +bool Utils::shouldDisableWebEngineSandbox() +{ + // WARNING: 请在 组织名称 和 应用程序名称 初始化完成后调用 + QSettings config(QStandardPaths::writableLocation(QStandardPaths::AppConfigLocation) + "/config.ini", QSettings::IniFormat); + + // 检查配置文件中[webengine]部分的noSandbox配置项 + // 如果配置存在且值为true,则返回true;否则返回false + qDebug()<<"shaxiang"< Date: Fri, 19 Sep 2025 20:16:08 +0800 Subject: [PATCH 048/105] =?UTF-8?q?chore:=E5=BD=93config.ini=E4=B8=BA[webe?= =?UTF-8?q?ngine]=20noSandbox=3Dtrue=20=E6=97=B6=EF=BC=8C=E5=88=99?= =?UTF-8?q?=E5=85=B3=E9=97=AD=E6=B2=99=E7=AE=B1=E8=BF=90=E8=A1=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/main.cpp b/src/main.cpp index 2e155e8a..776a3e7f 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -153,6 +153,10 @@ int main(int argc, char *argv[]) #if defined __sw_64__ || __loongarch__ chromium_flags.append("--no-sandbox"); #endif + // 如果配置文件中设置了关闭沙箱,则添加no-sandbox标志 + if (Utils::shouldDisableWebEngineSandbox()) { + chromium_flags.append("--no-sandbox"); + } qputenv("QTWEBENGINE_CHROMIUM_FLAGS", chromium_flags.join(" ").toUtf8()); /** @@ -199,4 +203,4 @@ int main(int argc, char *argv[]) w.show(); return a.exec(); -} +} \ No newline at end of file -- Gitee From 39887285de3a050b39f29805822057502034e268 Mon Sep 17 00:00:00 2001 From: momen Date: Fri, 19 Sep 2025 20:29:12 +0800 Subject: [PATCH 049/105] =?UTF-8?q?chore:=E5=90=8C=E6=AD=A5=E7=BF=BB?= =?UTF-8?q?=E8=AF=91=E6=96=87=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- translations/spark-store_en.ts | 34 +++++++++++++++++++++++++++++-- translations/spark-store_es.ts | 34 +++++++++++++++++++++++++++++-- translations/spark-store_fr.ts | 34 +++++++++++++++++++++++++++++-- translations/spark-store_zh_CN.ts | 34 +++++++++++++++++++++++++++++-- translations/spark-store_zh_TW.ts | 34 +++++++++++++++++++++++++++++-- 5 files changed, 160 insertions(+), 10 deletions(-) diff --git a/translations/spark-store_en.ts b/translations/spark-store_en.ts index b093bf8e..0360d215 100644 --- a/translations/spark-store_en.ts +++ b/translations/spark-store_en.ts @@ -639,12 +639,42 @@ - + + Log + + + + + Export Logs:/tmp/spark-store + + + + + Export + + + + + Disable Safe Mode + + + + + Disable the webEngine sandbox feature. + + + + + Disable + + + + About us - + <html><head/><body><p>Our services and software are free for individuals and non-profit organizations to use, communicate and learn, but you must comply with local laws and regulations in the process of use, otherwise any problems have nothing to do with us. </p><p>We don't make a profit from the Community version store, we rely on donations from the community for most of our operating expenses, and we appreciate that this allows us to spend less energy worrying about money. However, in order to better provide continuous service, Spark is only free for individual users to open the service warehouse, if you or your organization needs to provide commercial services or your organization is a for-profit organization, please contact us to obtain commercial authorization. </p><p>When using the Software, users or organizations are strictly forbidden to engage in any form of malicious behavior, including but not limited to malicious attacks, abuse, destruction, bulk crawling of the software warehouse, etc. The definition of malicious behavior is judged by the Spark community, and violators will be held legally responsible. Spark Community reserves the right to distribute the software packages it produces. </p><p>Any person or organization is prohibited from using the Spark Community software package for commercial purposes or redistributing it without the express authorization of the Spark Community. This clause is intended to ensure the spirit of open source while safeguarding the intellectual property rights of the Spark community. In addition to the above, if you use the Spark Store main program or part of its code, you are subject to all other terms and requirements of the GPL v3.</p><p>If any part of the store infringes your rights, please tell us <a href="mailto:jifengshenmo@outlook.com"><span style=" text-decoration: underline; color:#0082fa;">jifengshenmo@outlook.com</span></a> 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><span style=" text-decoration: underline; color:#0000ff;"><br/></span>Our contact method can be found at <a href="https://blog.shenmo.tech/post/%E6%95%85%E9%9A%9C%E5%85%AC%E5%91%8A/"><span style=" text-decoration: underline; color:#0082fa;">Here</span></a></p></body></html> diff --git a/translations/spark-store_es.ts b/translations/spark-store_es.ts index f38a6f04..3f396f74 100644 --- a/translations/spark-store_es.ts +++ b/translations/spark-store_es.ts @@ -639,12 +639,42 @@ Borrar la caché web - + + Log + + + + + Export Logs:/tmp/spark-store + + + + + Export + + + + + Disable Safe Mode + + + + + Disable the webEngine sandbox feature. + + + + + Disable + + + + About us Sobre nosotros - + <html><head/><body><p>Our services and software are free for individuals and non-profit organizations to use, communicate and learn, but you must comply with local laws and regulations in the process of use, otherwise any problems have nothing to do with us. </p><p>We don't make a profit from the Community version store, we rely on donations from the community for most of our operating expenses, and we appreciate that this allows us to spend less energy worrying about money. However, in order to better provide continuous service, Spark is only free for individual users to open the service warehouse, if you or your organization needs to provide commercial services or your organization is a for-profit organization, please contact us to obtain commercial authorization. </p><p>When using the Software, users or organizations are strictly forbidden to engage in any form of malicious behavior, including but not limited to malicious attacks, abuse, destruction, bulk crawling of the software warehouse, etc. The definition of malicious behavior is judged by the Spark community, and violators will be held legally responsible. Spark Community reserves the right to distribute the software packages it produces. </p><p>Any person or organization is prohibited from using the Spark Community software package for commercial purposes or redistributing it without the express authorization of the Spark Community. This clause is intended to ensure the spirit of open source while safeguarding the intellectual property rights of the Spark community. In addition to the above, if you use the Spark Store main program or part of its code, you are subject to all other terms and requirements of the GPL v3.</p><p>If any part of the store infringes your rights, please tell us <a href="mailto:jifengshenmo@outlook.com"><span style=" text-decoration: underline; color:#0082fa;">jifengshenmo@outlook.com</span></a> 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><span style=" text-decoration: underline; color:#0000ff;"><br/></span>Our contact method can be found at <a href="https://blog.shenmo.tech/post/%E6%95%85%E9%9A%9C%E5%85%AC%E5%91%8A/"><span style=" text-decoration: underline; color:#0082fa;">Here</span></a></p></body></html> diff --git a/translations/spark-store_fr.ts b/translations/spark-store_fr.ts index 0a6823d6..64dc703b 100644 --- a/translations/spark-store_fr.ts +++ b/translations/spark-store_fr.ts @@ -639,12 +639,42 @@ Effacer le cache Web - + + Log + + + + + Export Logs:/tmp/spark-store + + + + + Export + + + + + Disable Safe Mode + + + + + Disable the webEngine sandbox feature. + + + + + Disable + + + + About us À propos de nous - + <html><head/><body><p>Our services and software are free for individuals and non-profit organizations to use, communicate and learn, but you must comply with local laws and regulations in the process of use, otherwise any problems have nothing to do with us. </p><p>We don't make a profit from the Community version store, we rely on donations from the community for most of our operating expenses, and we appreciate that this allows us to spend less energy worrying about money. However, in order to better provide continuous service, Spark is only free for individual users to open the service warehouse, if you or your organization needs to provide commercial services or your organization is a for-profit organization, please contact us to obtain commercial authorization. </p><p>When using the Software, users or organizations are strictly forbidden to engage in any form of malicious behavior, including but not limited to malicious attacks, abuse, destruction, bulk crawling of the software warehouse, etc. The definition of malicious behavior is judged by the Spark community, and violators will be held legally responsible. Spark Community reserves the right to distribute the software packages it produces. </p><p>Any person or organization is prohibited from using the Spark Community software package for commercial purposes or redistributing it without the express authorization of the Spark Community. This clause is intended to ensure the spirit of open source while safeguarding the intellectual property rights of the Spark community. In addition to the above, if you use the Spark Store main program or part of its code, you are subject to all other terms and requirements of the GPL v3.</p><p>If any part of the store infringes your rights, please tell us <a href="mailto:jifengshenmo@outlook.com"><span style=" text-decoration: underline; color:#0082fa;">jifengshenmo@outlook.com</span></a> 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><span style=" text-decoration: underline; color:#0000ff;"><br/></span>Our contact method can be found at <a href="https://blog.shenmo.tech/post/%E6%95%85%E9%9A%9C%E5%85%AC%E5%91%8A/"><span style=" text-decoration: underline; color:#0082fa;">Here</span></a></p></body></html> diff --git a/translations/spark-store_zh_CN.ts b/translations/spark-store_zh_CN.ts index 6df066c1..ff599966 100644 --- a/translations/spark-store_zh_CN.ts +++ b/translations/spark-store_zh_CN.ts @@ -639,12 +639,42 @@ 清理网页缓存 - + + Log + + + + + Export Logs:/tmp/spark-store + + + + + Export + + + + + Disable Safe Mode + + + + + Disable the webEngine sandbox feature. + + + + + Disable + + + + About us 关于我们 - + <html><head/><body><p>Our services and software are free for individuals and non-profit organizations to use, communicate and learn, but you must comply with local laws and regulations in the process of use, otherwise any problems have nothing to do with us. </p><p>We don't make a profit from the Community version store, we rely on donations from the community for most of our operating expenses, and we appreciate that this allows us to spend less energy worrying about money. However, in order to better provide continuous service, Spark is only free for individual users to open the service warehouse, if you or your organization needs to provide commercial services or your organization is a for-profit organization, please contact us to obtain commercial authorization. </p><p>When using the Software, users or organizations are strictly forbidden to engage in any form of malicious behavior, including but not limited to malicious attacks, abuse, destruction, bulk crawling of the software warehouse, etc. The definition of malicious behavior is judged by the Spark community, and violators will be held legally responsible. Spark Community reserves the right to distribute the software packages it produces. </p><p>Any person or organization is prohibited from using the Spark Community software package for commercial purposes or redistributing it without the express authorization of the Spark Community. This clause is intended to ensure the spirit of open source while safeguarding the intellectual property rights of the Spark community. In addition to the above, if you use the Spark Store main program or part of its code, you are subject to all other terms and requirements of the GPL v3.</p><p>If any part of the store infringes your rights, please tell us <a href="mailto:jifengshenmo@outlook.com"><span style=" text-decoration: underline; color:#0082fa;">jifengshenmo@outlook.com</span></a> 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><span style=" text-decoration: underline; color:#0000ff;"><br/></span>Our contact method can be found at <a href="https://blog.shenmo.tech/post/%E6%95%85%E9%9A%9C%E5%85%AC%E5%91%8A/"><span style=" text-decoration: underline; color:#0082fa;">Here</span></a></p></body></html> <html><head/><body><p>我们的服务和软件免费供个人和非营利组织使用、交流和学习,但您在使用过程中必须遵守当地的法律法规,否则出现的任何问题与我们无关。</p><p>我们不从社区版本商店中获利,我们的大部分运营费用依靠社区的捐赠,我们很感激这让我们可以花更少的精力担心钱。但是,为了更好地提供持续的服务,Spark只对个人用户免费开放服务仓库,如果您或您的组织需要提供商业服务或者您的组织是营利性组织,请联系我们获取商业授权。</p><p>严禁用户或组织在使用本软件时从事任何形式的恶意行为,包括但不限于恶意攻击、滥用、破坏、批量抓取软件仓库等。恶意行为的定义由Spark社区判断,违规者将承担法律责任。Spark Community保留发布其生成的软件包的权利。</p><p>未经Spark Community明确授权,禁止任何个人或组织将Spark Community软件包用于商业目的或重新分发。该条款旨在确保开源精神,同时保护Spark社区的知识产权。除此之外,如果您使用Spark Store主程序或其部分代码,则必须遵守GPL v3的所有其他条款和要求。<span style=" font - family:宋体;" <span style=" font - family:宋体;color:#0082fa;">jifengshenmo@outlook.com</span></a>我们会尽快删除侵权内容。</p><p>如果你也想加入我们,无论你是参与开发、设计、推销还是提交作品,我们都欢迎你加入我们。<br/></span>我们的联系方法可以在<a href="https://blog.shenmo.tech/post/%E6%95%85%E9%9A%9C%E5%85%AC%E5%91%8A/"><span style=" text-decoration: underline; color:#0082fa;">找到</span></a></p></body></html> diff --git a/translations/spark-store_zh_TW.ts b/translations/spark-store_zh_TW.ts index f6cf9ade..464f5a1b 100644 --- a/translations/spark-store_zh_TW.ts +++ b/translations/spark-store_zh_TW.ts @@ -639,12 +639,42 @@ 清理网页缓存 - + + Log + + + + + Export Logs:/tmp/spark-store + + + + + Export + + + + + Disable Safe Mode + + + + + Disable the webEngine sandbox feature. + + + + + Disable + + + + About us 关于我们 - + <html><head/><body><p>Our services and software are free for individuals and non-profit organizations to use, communicate and learn, but you must comply with local laws and regulations in the process of use, otherwise any problems have nothing to do with us. </p><p>We don't make a profit from the Community version store, we rely on donations from the community for most of our operating expenses, and we appreciate that this allows us to spend less energy worrying about money. However, in order to better provide continuous service, Spark is only free for individual users to open the service warehouse, if you or your organization needs to provide commercial services or your organization is a for-profit organization, please contact us to obtain commercial authorization. </p><p>When using the Software, users or organizations are strictly forbidden to engage in any form of malicious behavior, including but not limited to malicious attacks, abuse, destruction, bulk crawling of the software warehouse, etc. The definition of malicious behavior is judged by the Spark community, and violators will be held legally responsible. Spark Community reserves the right to distribute the software packages it produces. </p><p>Any person or organization is prohibited from using the Spark Community software package for commercial purposes or redistributing it without the express authorization of the Spark Community. This clause is intended to ensure the spirit of open source while safeguarding the intellectual property rights of the Spark community. In addition to the above, if you use the Spark Store main program or part of its code, you are subject to all other terms and requirements of the GPL v3.</p><p>If any part of the store infringes your rights, please tell us <a href="mailto:jifengshenmo@outlook.com"><span style=" text-decoration: underline; color:#0082fa;">jifengshenmo@outlook.com</span></a> 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><span style=" text-decoration: underline; color:#0000ff;"><br/></span>Our contact method can be found at <a href="https://blog.shenmo.tech/post/%E6%95%85%E9%9A%9C%E5%85%AC%E5%91%8A/"><span style=" text-decoration: underline; color:#0082fa;">Here</span></a></p></body></html> <html><head/><body><p>我们的服务和软件免费供个人和非营利组织使用、交流和学习,但您在使用过程中必须遵守当地的法律法规,否则出现的任何问题与我们无关。</p><p>我们不从社区版本商店中获利,我们的大部分运营费用依靠社区的捐赠,我们很感激这让我们可以花更少的精力担心钱。但是,为了更好地提供持续的服务,Spark只对个人用户免费开放服务仓库,如果您或您的组织需要提供商业服务或者您的组织是营利性组织,请联系我们获取商业授权。</p><p>严禁用户或组织在使用本软件时从事任何形式的恶意行为,包括但不限于恶意攻击、滥用、破坏、批量抓取软件仓库等。恶意行为的定义由Spark社区判断,违规者将承担法律责任。Spark Community保留发布其生成的软件包的权利。</p><p>未经Spark Community明确授权,禁止任何个人或组织将Spark Community软件包用于商业目的或重新分发。该条款旨在确保开源精神,同时保护Spark社区的知识产权。除此之外,如果您使用Spark Store主程序或其部分代码,则必须遵守GPL v3的所有其他条款和要求。<span style=" font - family:宋体;" <span style=" font - family:宋体;color:#0082fa;">jifengshenmo@outlook.com</span></a>我们会尽快删除侵权内容。</p><p>如果你也想加入我们,无论你是参与开发、设计、推销还是提交作品,我们都欢迎你加入我们。<br/></span>我们的联系方法可以在<a href="https://blog.shenmo.tech/post/%E6%95%85%E9%9A%9C%E5%85%AC%E5%91%8A/"><span style=" text-decoration: underline; color:#0082fa;">找到</span></a></p></body></html> -- Gitee From eeb74c0a1cbf7b04490798eeaf102e099681064b Mon Sep 17 00:00:00 2001 From: momen Date: Fri, 19 Sep 2025 20:35:36 +0800 Subject: [PATCH 050/105] =?UTF-8?q?update:=E6=9B=B4=E6=96=B0AppIntoPage.ui?= =?UTF-8?q?=E7=9A=84=E4=B8=AD=E6=96=87=E7=BF=BB=E8=AF=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- translations/spark-store_zh_CN.ts | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/translations/spark-store_zh_CN.ts b/translations/spark-store_zh_CN.ts index ff599966..d4cf864d 100644 --- a/translations/spark-store_zh_CN.ts +++ b/translations/spark-store_zh_CN.ts @@ -27,13 +27,15 @@ <html><head/><body><p>Capable to deepin 23</p></body></html> - + 兼容 Deepin 23 + 兼容 Deepin 23 <html><head/><body><p>This app can only be installed natively</p></body></html> - + 该应用只能在本机原生环境中安装 + 该应用只能在本机原生环境中安装 -- Gitee From c66930f9a38bd317e11f9a0bab2626a3abbaf45e Mon Sep 17 00:00:00 2001 From: momen Date: Fri, 19 Sep 2025 20:40:32 +0800 Subject: [PATCH 051/105] =?UTF-8?q?chore:=E6=9B=B4=E6=96=B0QObject?= =?UTF-8?q?=E4=B8=AD=E7=9A=84=E7=BF=BB=E8=AF=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- translations/spark-store_zh_CN.ts | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/translations/spark-store_zh_CN.ts b/translations/spark-store_zh_CN.ts index d4cf864d..21bf6777 100644 --- a/translations/spark-store_zh_CN.ts +++ b/translations/spark-store_zh_CN.ts @@ -35,31 +35,35 @@ <html><head/><body><p>This app can only be installed natively</p></body></html> 该应用只能在本机原生环境中安装 - 该应用只能在本机原生环境中安装 + 该应用只能在本机原生环境中安装 <html><head/><body><p>This app will be installed to debian12 ACE</p></body></html> - + 此应用将会被安装到ACE Debian12兼容环境 + 此应用将会被安装到ACE Debian12兼容环境 <html><head/><body><p>This app will be installed to debian13 ACE</p></body></html> - + 此应用将会被安装到ACE Debian13兼容环境 + 此应用将会被安装到ACE Debian13兼容环境 <html><head/><body><p>This app will be installed to debian SID ACE</p></body></html> - + 此应用将会被安装到ACE Debian SID兼容环境 + 此应用将会被安装到ACE Debian SID兼容环境 <html><head/><body><p>This app will be installed to deepin23 ACE</p></body></html> - + 此应用将会被安装到ACE Deepin 23兼容环境 + 此应用将会被安装到ACE Deepin 23兼容环境 @@ -535,7 +539,8 @@ <span style=' font-size:10pt;font-weight:60;'>An appstore powered by community</span><br/><span style=' font-size:10pt;font-weight:60;'>Sparky is our mascot, designed by <a href='https://tai3.cn/'>Tyson Tan</a></span><br/> - + <span style=' font-size:10pt;font-weight:60;'>由社区打造的应用商店</span><br/><span style=' font-size:10pt;font-weight:60;'>Sparky 是我们的吉祥物。设计源于 <a href='https://tai3.cn/'>Tyson Tan</a></span><br/> + <span style=' font-size:10pt;font-weight:60;'>由社区打造的应用商店</span><br/><span style=' font-size:10pt;font-weight:60;'>Sparky 是我们的吉祥物。设计源于<a href='https://tai3.cn/'>Tyson Tan</a></span><br/> -- Gitee From c8dc09ef7eb20f87570e54dc80bf94a8b6dddfb6 Mon Sep 17 00:00:00 2001 From: momen Date: Fri, 19 Sep 2025 20:43:13 +0800 Subject: [PATCH 052/105] =?UTF-8?q?update:=E5=AE=8C=E5=96=84Settingpage=20?= =?UTF-8?q?ui=E7=9A=84=E7=BF=BB=E8=AF=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- translations/spark-store_zh_CN.ts | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/translations/spark-store_zh_CN.ts b/translations/spark-store_zh_CN.ts index 21bf6777..157161ce 100644 --- a/translations/spark-store_zh_CN.ts +++ b/translations/spark-store_zh_CN.ts @@ -648,32 +648,34 @@ Log - + 导出日志 Export Logs:/tmp/spark-store - + 导出日志到:/tmp/spark-store + 导出日志到:/tmp/spark-store Export - + 导出 + 导出 Disable Safe Mode - + 禁用安全模式 Disable the webEngine sandbox feature. - + 禁用WebEngine沙箱功能。 Disable - + 禁用 -- Gitee From 3114d3b23d2cdf533b898b149aaaf278555e0441 Mon Sep 17 00:00:00 2001 From: momen Date: Sat, 20 Sep 2025 23:14:47 +0800 Subject: [PATCH 053/105] =?UTF-8?q?upadte:=E5=AE=8C=E6=88=90=E5=8B=BE?= =?UTF-8?q?=E9=80=89=E6=B2=99=E7=AE=B1=E5=BC=80=E5=85=B3=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/pages/settingspage.cpp | 14 ++++++++++++++ src/pages/settingspage.h | 4 +++- 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/src/pages/settingspage.cpp b/src/pages/settingspage.cpp index c380ea6c..467cab5f 100644 --- a/src/pages/settingspage.cpp +++ b/src/pages/settingspage.cpp @@ -98,8 +98,14 @@ void SettingsPage::initConfig() } configCanSave = true; //  防止触发保存配置信号 + // 在现有代码后添加初始化checkBox_disableSandbox的状态 needUncompatibleNotification = config.value("other/uncompatibleNotification", needUncompatibleNotification).toBool(); ui->checkBox->setChecked(needUncompatibleNotification); + + // 新增:从config.ini读取webengine/noSandbox配置并设置复选框状态 + bool disableSandbox = config.value("webengine/noSandbox", false).toBool(); + ui->checkBox_disableSandbox->setChecked(disableSandbox); + } SettingsPage::~SettingsPage() @@ -261,3 +267,11 @@ void SettingsPage::on_checkBox_clicked(bool checked) config.setValue("other/uncompatibleNotification", needUncompatibleNotification); config.sync(); } + +// 添加checkBox_disableSandbox的点击事件处理函数 +void SettingsPage::on_checkBox_disableSandbox_clicked(bool checked) +{ + QSettings config(QStandardPaths::writableLocation(QStandardPaths::AppConfigLocation) + "/config.ini", QSettings::IniFormat); + config.setValue("webengine/noSandbox", checked); + config.sync(); +} \ No newline at end of file diff --git a/src/pages/settingspage.h b/src/pages/settingspage.h index 6a82a651..7778d16c 100644 --- a/src/pages/settingspage.h +++ b/src/pages/settingspage.h @@ -32,6 +32,8 @@ private slots: void on_checkBox_clicked(bool checked); + void on_checkBox_disableSandbox_clicked(bool checked); + public: static bool needUncompatibleNotification; @@ -47,4 +49,4 @@ signals: void openUrl(QUrl spk); }; -#endif // SETTINGSPAGE_H +#endif // SETTINGSPAGE_H \ No newline at end of file -- Gitee From 93d443deeba45b5132d936f8f4a5737ed3c58421 Mon Sep 17 00:00:00 2001 From: momen Date: Sat, 20 Sep 2025 23:25:20 +0800 Subject: [PATCH 054/105] =?UTF-8?q?update:=E6=9B=B4=E6=96=B0changelog?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- debian/changelog | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/debian/changelog b/debian/changelog index c47c7cde..5df6527a 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,7 +1,9 @@ spark-store (4.8.2~test1) UNRELEASED; urgency=medium - * 增加导出日志功能。 - -- momen Tur, 18 Sep 2025 01:03:08 +0800 + * 添加WebEngine沙箱禁用选项,在设置页面新增复选框以允许用户在需要时关闭沙箱功能 + * 实现设置持久化,将沙箱禁用状态保存到配置文件并在应用启动时读取 + + -- momen spark-store (4.8.1-1) UNRELEASED; urgency=medium -- Gitee From 7132ae0b4200b781efb93675728ce0cc89e722f8 Mon Sep 17 00:00:00 2001 From: momen Date: Sat, 20 Sep 2025 23:25:36 +0800 Subject: [PATCH 055/105] =?UTF-8?q?update:=E5=90=8C=E6=AD=A5=E7=BF=BB?= =?UTF-8?q?=E8=AF=91=E6=96=87=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- translations/spark-store_en.ts | 6 +++--- translations/spark-store_es.ts | 6 +++--- translations/spark-store_fr.ts | 6 +++--- translations/spark-store_zh_CN.ts | 6 +++--- translations/spark-store_zh_TW.ts | 6 +++--- 5 files changed, 15 insertions(+), 15 deletions(-) diff --git a/translations/spark-store_en.ts b/translations/spark-store_en.ts index 0360d215..f628dee1 100644 --- a/translations/spark-store_en.ts +++ b/translations/spark-store_en.ts @@ -679,17 +679,17 @@ - + Updating, please wait... - + Spark Store - + Temporary cache was cleaned diff --git a/translations/spark-store_es.ts b/translations/spark-store_es.ts index 3f396f74..a1c15fb1 100644 --- a/translations/spark-store_es.ts +++ b/translations/spark-store_es.ts @@ -679,17 +679,17 @@ - + Updating, please wait... Se está actualizando, por favor Espere... - + Spark Store SPARK Store - + Temporary cache was cleaned Se ha limpiado la caché temporal diff --git a/translations/spark-store_fr.ts b/translations/spark-store_fr.ts index 64dc703b..31a3a963 100644 --- a/translations/spark-store_fr.ts +++ b/translations/spark-store_fr.ts @@ -679,17 +679,17 @@ - + Updating, please wait... Mise à jour en cours, veuillez patienter... - + Spark Store Le Spark store - + Temporary cache was cleaned Cache temporaire nettoyé diff --git a/translations/spark-store_zh_CN.ts b/translations/spark-store_zh_CN.ts index 157161ce..1cf2c9d3 100644 --- a/translations/spark-store_zh_CN.ts +++ b/translations/spark-store_zh_CN.ts @@ -688,17 +688,17 @@ <html><head/><body><p>我们的服务和软件免费供个人和非营利组织使用、交流和学习,但您在使用过程中必须遵守当地的法律法规,否则出现的任何问题与我们无关。</p><p>我们不从社区版本商店中获利,我们的大部分运营费用依靠社区的捐赠,我们很感激这让我们可以花更少的精力担心钱。但是,为了更好地提供持续的服务,Spark只对个人用户免费开放服务仓库,如果您或您的组织需要提供商业服务或者您的组织是营利性组织,请联系我们获取商业授权。</p><p>严禁用户或组织在使用本软件时从事任何形式的恶意行为,包括但不限于恶意攻击、滥用、破坏、批量抓取软件仓库等。恶意行为的定义由Spark社区判断,违规者将承担法律责任。Spark Community保留发布其生成的软件包的权利。</p><p>未经Spark Community明确授权,禁止任何个人或组织将Spark Community软件包用于商业目的或重新分发。该条款旨在确保开源精神,同时保护Spark社区的知识产权。除此之外,如果您使用Spark Store主程序或其部分代码,则必须遵守GPL v3的所有其他条款和要求。<span style=" font - family:宋体;" <span style=" font - family:宋体;color:#0082fa;">jifengshenmo@outlook.com</span></a>我们会尽快删除侵权内容。</p><p>如果你也想加入我们,无论你是参与开发、设计、推销还是提交作品,我们都欢迎你加入我们。<br/></span>我们的联系方法可以在<a href="https://blog.shenmo.tech/post/%E6%95%85%E9%9A%9C%E5%85%AC%E5%91%8A/"><span style=" text-decoration: underline; color:#0082fa;">找到</span></a></p></body></html> - + Updating, please wait... 正在更新,请稍候…… - + Spark Store 星火应用商店 - + Temporary cache was cleaned 缓存目录已清空 diff --git a/translations/spark-store_zh_TW.ts b/translations/spark-store_zh_TW.ts index 464f5a1b..4fcf0717 100644 --- a/translations/spark-store_zh_TW.ts +++ b/translations/spark-store_zh_TW.ts @@ -679,17 +679,17 @@ <html><head/><body><p>我们的服务和软件免费供个人和非营利组织使用、交流和学习,但您在使用过程中必须遵守当地的法律法规,否则出现的任何问题与我们无关。</p><p>我们不从社区版本商店中获利,我们的大部分运营费用依靠社区的捐赠,我们很感激这让我们可以花更少的精力担心钱。但是,为了更好地提供持续的服务,Spark只对个人用户免费开放服务仓库,如果您或您的组织需要提供商业服务或者您的组织是营利性组织,请联系我们获取商业授权。</p><p>严禁用户或组织在使用本软件时从事任何形式的恶意行为,包括但不限于恶意攻击、滥用、破坏、批量抓取软件仓库等。恶意行为的定义由Spark社区判断,违规者将承担法律责任。Spark Community保留发布其生成的软件包的权利。</p><p>未经Spark Community明确授权,禁止任何个人或组织将Spark Community软件包用于商业目的或重新分发。该条款旨在确保开源精神,同时保护Spark社区的知识产权。除此之外,如果您使用Spark Store主程序或其部分代码,则必须遵守GPL v3的所有其他条款和要求。<span style=" font - family:宋体;" <span style=" font - family:宋体;color:#0082fa;">jifengshenmo@outlook.com</span></a>我们会尽快删除侵权内容。</p><p>如果你也想加入我们,无论你是参与开发、设计、推销还是提交作品,我们都欢迎你加入我们。<br/></span>我们的联系方法可以在<a href="https://blog.shenmo.tech/post/%E6%95%85%E9%9A%9C%E5%85%AC%E5%91%8A/"><span style=" text-decoration: underline; color:#0082fa;">找到</span></a></p></body></html> - + Updating, please wait... 正在更新,请稍候…… - + Spark Store 星火应用商店 - + Temporary cache was cleaned 缓存目录已清空 -- Gitee From 4d00b0bec8f9e31e5d27af7f71d45219ecba5230 Mon Sep 17 00:00:00 2001 From: momen Date: Sun, 21 Sep 2025 22:45:12 +0800 Subject: [PATCH 056/105] =?UTF-8?q?update:=E6=B7=BB=E5=8A=A0=E6=A7=BD?= =?UTF-8?q?=E5=87=BD=E6=95=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/mainwindow.cpp | 16 +++++++++++++++- src/mainwindow.h | 9 +++++---- 2 files changed, 20 insertions(+), 5 deletions(-) diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index 2c43e9eb..b5ae7edd 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -266,7 +266,21 @@ void MainWindow::closeEvent(QCloseEvent *event) QMessageBox::StandardButton reply = QMessageBox::question(this, "确认关闭", "正在更新,是否确认关闭窗口?", QMessageBox::Yes | QMessageBox::No); } +void MainWindow::handleUpdateFinished(bool success) +{ + if (success) { + // 更新成功时的处理逻辑 + QMessageBox::information(this, "更新完成", "软件更新已成功完成!"); + } else { + // 更新失败时的处理逻辑 + QMessageBox::warning(this, "更新失败", "软件更新过程中出现错误,请稍后再试。"); + } + + // 刷新应用列表 + checkUpdates(); +} + MainWindow::~MainWindow() { delete ui; -} +} \ No newline at end of file diff --git a/src/mainwindow.h b/src/mainwindow.h index 41002cd9..8f1b0037 100644 --- a/src/mainwindow.h +++ b/src/mainwindow.h @@ -24,9 +24,7 @@ public: protected: void closeEvent(QCloseEvent *event) override; -private slots: - // ⬅️ 声明一个槽函数,它将接收来自Updater的信号 - void handleUpdateFinished(bool success); + private: Ui::MainWindow *ui; void checkUpdates(); @@ -37,5 +35,8 @@ private: QListView *listView; // 声明 QListView 指针 QJsonArray m_allApps; // 新增:保存所有应用数据 void filterAppsByKeyword(const QString &keyword); // 新增:搜索过滤函数声明 + +private slots: + void handleUpdateFinished(bool success); // 新增:处理更新完成的槽函数 }; -#endif // MAINWINDOW_H +#endif // MAINWINDOW_H \ No newline at end of file -- Gitee From 5c44ee722614075e6813844f41ea9ed285d748f8 Mon Sep 17 00:00:00 2001 From: momen Date: Mon, 22 Sep 2025 15:48:40 +0800 Subject: [PATCH 057/105] =?UTF-8?q?chore:=E6=B7=BB=E5=8A=A0=E5=AF=BC?= =?UTF-8?q?=E5=87=BA=E6=97=A5=E5=BF=97=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main.cpp | 13 ++++- src/pages/settingspage.cpp | 35 ++++++++++++- src/pages/settingspage.h | 3 ++ src/utils/utils.cpp | 104 +++++++++++++++++++++++++++++++++++++ src/utils/utils.h | 7 +++ 5 files changed, 160 insertions(+), 2 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index 776a3e7f..fe3bc334 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -108,7 +108,10 @@ int main(int argc, char *argv[]) { // 崩溃处理 signal(SIGSEGV, crashHandler); // 注册SIGSEGV处理函数 - + + // 初始化日志系统 + Utils::initLogger(); + Utils::writeLog("INFO", "Application starting..."); // // Get build time // static const QDate buildDate = QLocale(QLocale::English).toDate(QString(__DATE__).replace(" ", " 0"), "MMM dd yyyy"); @@ -117,6 +120,7 @@ int main(int argc, char *argv[]) //在cmakelist.txt中设置 buildDateTime QString buildDateTime = QString("%1-%2").arg(QString(BUILD_DATE)).arg(QString(BUILD_TIME)); + Utils::writeLog("INFO", QString("Build datetime: %1").arg(buildDateTime)); // NOTE: 提前设置组织名称和应用名称,避免配置文件位置错误 DApplication::setOrganizationName("spark-union"); @@ -130,9 +134,11 @@ int main(int argc, char *argv[]) DataCollectorAndUploader uploader; QObject::connect(&uploader, &DataCollectorAndUploader::uploadSuccessful, [](){ qDebug() << "Data uploaded successfully"; + Utils::writeLog("INFO", "Data uploaded successfully"); }); QObject::connect(&uploader, &DataCollectorAndUploader::uploadFailed, [](QString error){ qDebug() << "Upload failed with error: " << error; + Utils::writeLog("ERROR", QString("Upload failed with error: %1").arg(error)); }); uploader.collectAndUploadData(); @@ -202,5 +208,10 @@ int main(int argc, char *argv[]) } w.show(); + // 在程序结束前关闭日志文件 - 修复变量名并移到return前 + QObject::connect(&a, &QApplication::aboutToQuit, []() { + Utils::writeLog("INFO", "Application shutting down"); + }); + return a.exec(); } \ No newline at end of file diff --git a/src/pages/settingspage.cpp b/src/pages/settingspage.cpp index 467cab5f..df5e37de 100644 --- a/src/pages/settingspage.cpp +++ b/src/pages/settingspage.cpp @@ -6,6 +6,7 @@ #include #include #include +#include #define TMP_PATH "/tmp/spark-store" #define DEFAULT_SERVER_URL "https://cdn-d.spark-app.store/" @@ -22,6 +23,9 @@ SettingsPage::SettingsPage(QWidget *parent) configCanSave = false; initConfig(); + + // 连接导出日志按钮的点击信号 + connect(ui->pushButton_exportLog, &QPushButton::clicked, this, &SettingsPage::on_pushButton_exportLog_clicked); } void SettingsPage::setTheme(bool dark) @@ -32,7 +36,7 @@ void SettingsPage::setTheme(bool dark) } else { - // 亮色模式 + // ���色模式 this->setStyleSheet("#frame{background-color: #ffffff;border-radius:14px;border:1px solid rgb(229,229,229);}"); } } @@ -274,4 +278,33 @@ void SettingsPage::on_checkBox_disableSandbox_clicked(bool checked) QSettings config(QStandardPaths::writableLocation(QStandardPaths::AppConfigLocation) + "/config.ini", QSettings::IniFormat); config.setValue("webengine/noSandbox", checked); config.sync(); +} + +// 添加导出日志按钮的点击事件处理函数 +void SettingsPage::on_pushButton_exportLog_clicked() +{ + auto future = QtConcurrent::run([=]() { + // 禁用按钮防止重复点击 + QMetaObject::invokeMethod(ui->pushButton_exportLog, "setEnabled", Qt::QueuedConnection, Q_ARG(bool, false)); + + QString targetPath = QString::fromUtf8(TMP_PATH); + bool success = Utils::exportLogs(targetPath); + + // 显示导出结果通知 + QString message; + if (success) { + message = tr("Logs exported successfully to: %1").arg(targetPath); + Utils::writeLog("INFO", "User exported logs via settings page"); + } else { + message = tr("Failed to export logs"); + Utils::writeLog("ERROR", "User failed to export logs via settings page"); + } + + // 在主线程显示消息框 + QMetaObject::invokeMethod(this, [message, this]() { + QMessageBox::information(this, tr("Export Logs"), message); + // 重新启用按钮 + ui->pushButton_exportLog->setEnabled(true); + }, Qt::QueuedConnection); + }); } \ No newline at end of file diff --git a/src/pages/settingspage.h b/src/pages/settingspage.h index 7778d16c..c2b14fe3 100644 --- a/src/pages/settingspage.h +++ b/src/pages/settingspage.h @@ -33,6 +33,9 @@ private slots: void on_checkBox_clicked(bool checked); void on_checkBox_disableSandbox_clicked(bool checked); + + // 添加导出日志按钮的槽函数声明 + void on_pushButton_exportLog_clicked(); public: static bool needUncompatibleNotification; diff --git a/src/utils/utils.cpp b/src/utils/utils.cpp index c00d0a0d..bf0d8ad0 100644 --- a/src/utils/utils.cpp +++ b/src/utils/utils.cpp @@ -10,6 +10,10 @@ #include #include #include +#include +#include +#include +#include #define UOSDeveloperModeFile "/var/lib/deepin/developer-mode/enabled" @@ -275,4 +279,104 @@ bool Utils::shouldDisableWebEngineSandbox() // 如果配置存在且值为true,则返回true;否则返回false qDebug()<<"shaxiang"<open(QIODevice::WriteOnly | QIODevice::Append | QIODevice::Text)) { + qWarning() << "Failed to open log file:" << logFilePath; + delete logFile; + logFile = nullptr; + return; + } + + // 写入日志头信息 + writeLog("INFO", "Logger initialized"); + writeLog("INFO", QString("Application started at %1").arg( + QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss"))); +} + +// 写入日志 +void Utils::writeLog(const QString &level, const QString &message) +{ + if (!logFile || !logFile->isOpen()) { + return; + } + + QString timestamp = QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss.zzz"); + QString logEntry = QString("[%1] [%2] %3\n").arg(timestamp).arg(level).arg(message); + + QTextStream out(logFile); + out << logEntry; + logFile->flush(); + + // 同时输出到控制台,便于调试 + if (level == "ERROR") { + qCritical() << logEntry.trimmed(); + } else if (level == "WARNING") { + qWarning() << logEntry.trimmed(); + } else { + qDebug() << logEntry.trimmed(); + } +} + +// 导出日志 +bool Utils::exportLogs(const QString &targetPath) +{ + // 确保目标目录存在 + QDir dir; + if (!dir.exists(targetPath)) { + if (!dir.mkpath(targetPath)) { + writeLog("ERROR", QString("Failed to create target directory: %1").arg(targetPath)); + return false; + } + } + + // 关闭当前日志文件,便于复制 + if (logFile && logFile->isOpen()) { + logFile->close(); + } + + // 复制日志文件到目标位置 + QString targetLogPath = targetPath + QString("/spark-store_log_export_%1.log").arg( + QDateTime::currentDateTime().toString("yyyyMMdd_HHmmss")); + + bool success = QFile::copy(logFilePath, targetLogPath); + + if (success) { + writeLog("INFO", QString("Logs exported to: %1").arg(targetLogPath)); + } else { + writeLog("ERROR", QString("Failed to export logs to: %1").arg(targetLogPath)); + } + + // 重新打开日志文件继续记录 + if (logFile && !logFile->isOpen()) { + logFile->open(QIODevice::WriteOnly | QIODevice::Append | QIODevice::Text); + } + + return success; +} + +// 获取日志文件路径 +QString Utils::getLogFilePath() +{ + return logFilePath; } \ No newline at end of file diff --git a/src/utils/utils.h b/src/utils/utils.h index 60824482..6eda97c0 100644 --- a/src/utils/utils.h +++ b/src/utils/utils.h @@ -3,6 +3,7 @@ #include #include +#include class Utils { @@ -19,6 +20,12 @@ public: static void checkUOSDeveloperMode(); static QJsonObject parseFeatureJsonFile(); static bool shouldDisableWebEngineSandbox(); // 新增函数声明 + + // 日志相关函数 + static void initLogger(); // 初始化日志系统 + static void writeLog(const QString &level, const QString &message); // 写入日志 + static bool exportLogs(const QString &targetPath = "/tmp/spark-store"); // 导出日志 + static QString getLogFilePath(); // 获取日志文件路径 }; #endif // UTILS_H \ No newline at end of file -- Gitee From d8a37114ebeacb5200c02bb594fdfd5456f30fcc Mon Sep 17 00:00:00 2001 From: momen Date: Tue, 23 Sep 2025 13:42:55 +0800 Subject: [PATCH 058/105] =?UTF-8?q?fix:=E4=BF=AE=E5=A4=8D=E5=AF=BC?= =?UTF-8?q?=E5=87=BA=E6=88=90=E5=8A=9F=E4=BD=86=E6=98=BE=E7=A4=BA=E5=A4=B1?= =?UTF-8?q?=E8=B4=A5=E7=9A=84=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/utils/utils.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/utils/utils.cpp b/src/utils/utils.cpp index bf0d8ad0..d417f20c 100644 --- a/src/utils/utils.cpp +++ b/src/utils/utils.cpp @@ -361,6 +361,14 @@ bool Utils::exportLogs(const QString &targetPath) bool success = QFile::copy(logFilePath, targetLogPath); + // 额外检查:即使QFile::copy返回false,也要检查目标文件是否实际存在且大小合理 + if (!success) { + QFileInfo targetFileInfo(targetLogPath); + if (targetFileInfo.exists() && targetFileInfo.size() > 0) { + success = true; + } + } + if (success) { writeLog("INFO", QString("Logs exported to: %1").arg(targetLogPath)); } else { -- Gitee From 642f6582303e482afd35d2537d565bae23c0ffd8 Mon Sep 17 00:00:00 2001 From: momen Date: Wed, 24 Sep 2025 14:44:59 +0800 Subject: [PATCH 059/105] =?UTF-8?q?chore:=E6=94=B9=E4=B8=BA=E7=B3=BB?= =?UTF-8?q?=E7=BB=9F=E9=80=9A=E7=9F=A5=E5=AF=BC=E5=87=BA=E6=97=A5=E5=BF=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/pages/settingspage.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/pages/settingspage.cpp b/src/pages/settingspage.cpp index df5e37de..7a27ed4e 100644 --- a/src/pages/settingspage.cpp +++ b/src/pages/settingspage.cpp @@ -280,10 +280,10 @@ void SettingsPage::on_checkBox_disableSandbox_clicked(bool checked) config.sync(); } -// 添加导出日志按钮的点击事件处理函数 +// 修改导出日志按钮的点击事件处理函数 void SettingsPage::on_pushButton_exportLog_clicked() { - auto future = QtConcurrent::run([=]() { + auto future = QtConcurrent::run([=]() { // 禁用按钮防止重复点击 QMetaObject::invokeMethod(ui->pushButton_exportLog, "setEnabled", Qt::QueuedConnection, Q_ARG(bool, false)); @@ -302,7 +302,8 @@ void SettingsPage::on_pushButton_exportLog_clicked() // 在主线程显示消息框 QMetaObject::invokeMethod(this, [message, this]() { - QMessageBox::information(this, tr("Export Logs"), message); + // 使用系统通知代替QMessageBox弹窗,避免重复通知 + Utils::sendNotification("spark-store", tr("Export Logs"), message); // 重新启用按钮 ui->pushButton_exportLog->setEnabled(true); }, Qt::QueuedConnection); -- Gitee From 4951fc7dd1e4cc6e863826cd11ecaa11533b0949 Mon Sep 17 00:00:00 2001 From: momen Date: Thu, 25 Sep 2025 08:25:25 +0800 Subject: [PATCH 060/105] =?UTF-8?q?fix:=E4=BF=AE=E5=A4=8D=E5=BC=B9?= =?UTF-8?q?=E5=87=BA=E4=B8=A4=E6=AC=A1=E5=AF=BC=E5=87=BA=E9=80=9A=E7=9F=A5?= =?UTF-8?q?=E7=9A=84=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/pages/settingspage.cpp | 50 ++++++++++++++++++-------------------- 1 file changed, 23 insertions(+), 27 deletions(-) diff --git a/src/pages/settingspage.cpp b/src/pages/settingspage.cpp index 7a27ed4e..c40607ce 100644 --- a/src/pages/settingspage.cpp +++ b/src/pages/settingspage.cpp @@ -24,8 +24,8 @@ SettingsPage::SettingsPage(QWidget *parent) configCanSave = false; initConfig(); - // 连接导出日志按钮的点击信号 - connect(ui->pushButton_exportLog, &QPushButton::clicked, this, &SettingsPage::on_pushButton_exportLog_clicked); + // 移除了手动连接导出日志按钮的点击信号 + // connect(ui->pushButton_exportLog, &QPushButton::clicked, this, &SettingsPage::on_pushButton_exportLog_clicked); } void SettingsPage::setTheme(bool dark) @@ -283,29 +283,25 @@ void SettingsPage::on_checkBox_disableSandbox_clicked(bool checked) // 修改导出日志按钮的点击事件处理函数 void SettingsPage::on_pushButton_exportLog_clicked() { - auto future = QtConcurrent::run([=]() { - // 禁用按钮防止重复点击 - QMetaObject::invokeMethod(ui->pushButton_exportLog, "setEnabled", Qt::QueuedConnection, Q_ARG(bool, false)); - - QString targetPath = QString::fromUtf8(TMP_PATH); - bool success = Utils::exportLogs(targetPath); - - // 显示导出结果通知 - QString message; - if (success) { - message = tr("Logs exported successfully to: %1").arg(targetPath); - Utils::writeLog("INFO", "User exported logs via settings page"); - } else { - message = tr("Failed to export logs"); - Utils::writeLog("ERROR", "User failed to export logs via settings page"); - } - - // 在主线程显示消息框 - QMetaObject::invokeMethod(this, [message, this]() { - // 使用系统通知代替QMessageBox弹窗,避免重复通知 - Utils::sendNotification("spark-store", tr("Export Logs"), message); - // 重新启用按钮 - ui->pushButton_exportLog->setEnabled(true); - }, Qt::QueuedConnection); - }); + // 禁用按钮防止重复点击 + ui->pushButton_exportLog->setEnabled(false); + + QString targetPath = QString::fromUtf8(TMP_PATH); + bool success = Utils::exportLogs(targetPath); + + // 显示导出结果通知 + QString message; + if (success) { + message = tr("Logs exported successfully to: %1").arg(targetPath); + Utils::writeLog("INFO", "User exported logs via settings page"); + } else { + message = tr("Failed to export logs"); + Utils::writeLog("ERROR", "User failed to export logs via settings page"); + } + + // 只发送一次系统通知 + Utils::sendNotification("spark-store", tr("Export Logs"), message); + + // 重新启用按钮 + ui->pushButton_exportLog->setEnabled(true); } \ No newline at end of file -- Gitee From 7387f8af95bf5dbc8d67fd6ae60561390e903fbc Mon Sep 17 00:00:00 2001 From: momen Date: Fri, 26 Sep 2025 23:55:56 +0800 Subject: [PATCH 061/105] =?UTF-8?q?chore:=E6=9B=B4=E6=96=B0=E6=97=A5?= =?UTF-8?q?=E5=BF=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- debian/changelog | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/debian/changelog b/debian/changelog index b414feaa..46eb85d9 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,8 @@ +spark-update-tool (1.0.1) unstable; urgency=low + + * 修复窗口调整大小时的错误 + + -- momen Wed, 18 Jun 2025 00:00:00 +0000 spark-update-tool (1.0.0) unstable; urgency=low * Initial release. -- Gitee From b7bf70e402435ace2a1ebb71ff91cfd0e1a90b41 Mon Sep 17 00:00:00 2001 From: momen Date: Sat, 27 Sep 2025 11:28:30 +0800 Subject: [PATCH 062/105] =?UTF-8?q?feat:=E6=B7=BB=E5=8A=A0=E5=AF=BC?= =?UTF-8?q?=E5=87=BA=E6=97=A5=E5=BF=97=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/spark-store.pro | 6 ++-- src/utils/utils.cpp | 69 +++++++++++++++++++++++++++++++++++++++++---- src/utils/utils.h | 2 ++ 3 files changed, 68 insertions(+), 9 deletions(-) diff --git a/src/spark-store.pro b/src/spark-store.pro index e6ffa3e0..a2551689 100644 --- a/src/spark-store.pro +++ b/src/spark-store.pro @@ -27,8 +27,8 @@ VERSION = $$BUILD_VERSION isEmpty(VERSION): VERSION = 4.0.0 DEFINES += APP_VERSION=\\\"'$${VERSION}'\\\" DEFINES += APP_BRANCH=\\\"'$$system(git symbolic-ref --short -q HEAD)'\\\" -# Disable qWarning / qDebug output in Release -#CONFIG(release, debug | release): DEFINES += QT_NO_WARNING_OUTPUT QT_NO_DEBUG_OUTPUT +# Enable all log outputs in both Debug and Release modes +# We want to capture all logs (INFO, DEBUG, WARNING, ERROR) for export to /tmp/spark-store CONFIG += c++11 link_pkgconfig PKGCONFIG += dtkcore dtkgui dtkwidget @@ -107,4 +107,4 @@ qnx: target.path = /tmp/$${TARGET}/bin else: unix:!android: target.path = /opt/durapps/$${TARGET}/bin !isEmpty(target.path): INSTALLS += target -DISTFILES += +DISTFILES += \ No newline at end of file diff --git a/src/utils/utils.cpp b/src/utils/utils.cpp index d417f20c..e034a14f 100644 --- a/src/utils/utils.cpp +++ b/src/utils/utils.cpp @@ -285,6 +285,39 @@ bool Utils::shouldDisableWebEngineSandbox() static QFile *logFile = nullptr; static QString logFilePath; +// 自定义消息处理器,捕获所有Qt日志输出 +void customMessageHandler(QtMsgType type, const QMessageLogContext &context, const QString &msg) +{ + QByteArray localMsg = msg.toLocal8Bit(); + QString level; + + switch (type) { + case QtDebugMsg: + level = "DEBUG"; + fprintf(stderr, "DEBUG: %s (%s:%u, %s)\n", localMsg.constData(), context.file, context.line, context.function); + break; + case QtInfoMsg: + level = "INFO"; + fprintf(stderr, "INFO: %s (%s:%u, %s)\n", localMsg.constData(), context.file, context.line, context.function); + break; + case QtWarningMsg: + level = "WARNING"; + fprintf(stderr, "WARNING: %s (%s:%u, %s)\n", localMsg.constData(), context.file, context.line, context.function); + break; + case QtCriticalMsg: + level = "ERROR"; + fprintf(stderr, "ERROR: %s (%s:%u, %s)\n", localMsg.constData(), context.file, context.line, context.function); + break; + case QtFatalMsg: + level = "FATAL"; + fprintf(stderr, "FATAL: %s (%s:%u, %s)\n", localMsg.constData(), context.file, context.line, context.function); + abort(); + } + + // 写入到日志文件 + Utils::writeLog(level, msg); +} + // 初始化日志系统 void Utils::initLogger() { @@ -308,6 +341,9 @@ void Utils::initLogger() return; } + // 安装自定义消息处理器,捕获所有Qt日志输出 + qInstallMessageHandler(customMessageHandler); + // 写入日志头信息 writeLog("INFO", "Logger initialized"); writeLog("INFO", QString("Application started at %1").arg( @@ -341,11 +377,16 @@ void Utils::writeLog(const QString &level, const QString &message) // 导出日志 bool Utils::exportLogs(const QString &targetPath) { + QString exportPath = targetPath; + if (exportPath.isEmpty()) { + exportPath = "/tmp/spark-store"; + } + // 确保目标目录存在 QDir dir; - if (!dir.exists(targetPath)) { - if (!dir.mkpath(targetPath)) { - writeLog("ERROR", QString("Failed to create target directory: %1").arg(targetPath)); + if (!dir.exists(exportPath)) { + if (!dir.mkpath(exportPath)) { + writeLog("ERROR", QString("Failed to create target directory: %1").arg(exportPath)); return false; } } @@ -356,8 +397,8 @@ bool Utils::exportLogs(const QString &targetPath) } // 复制日志文件到目标位置 - QString targetLogPath = targetPath + QString("/spark-store_log_export_%1.log").arg( - QDateTime::currentDateTime().toString("yyyyMMdd_HHmmss")); + QString timestamp = QDateTime::currentDateTime().toString("yyyyMMdd_HHmmss"); + QString targetLogPath = exportPath + QString("/spark-store_full_log_%1.log").arg(timestamp); bool success = QFile::copy(logFilePath, targetLogPath); @@ -370,7 +411,23 @@ bool Utils::exportLogs(const QString &targetPath) } if (success) { - writeLog("INFO", QString("Logs exported to: %1").arg(targetLogPath)); + writeLog("INFO", QString("All logs (INFO, DEBUG, WARNING, ERROR) exported to: %1").arg(targetLogPath)); + + // 同时创建一个简单的导出报告 + QString reportPath = exportPath + QString("/export_report_%1.txt").arg(timestamp); + QFile reportFile(reportPath); + if (reportFile.open(QIODevice::WriteOnly | QIODevice::Text)) { + QTextStream out(&reportFile); + out << "Spark Store Log Export Report\n"; + out << "================================\n"; + out << "Export Time: " << QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss") << "\n"; + out << "Target Directory: " << exportPath << "\n"; + out << "Log File: " << targetLogPath << "\n"; + out << "Original Log: " << logFilePath << "\n"; + out << "Log Levels: INFO, DEBUG, WARNING, ERROR, FATAL\n"; + out << "Status: SUCCESS\n"; + reportFile.close(); + } } else { writeLog("ERROR", QString("Failed to export logs to: %1").arg(targetLogPath)); } diff --git a/src/utils/utils.h b/src/utils/utils.h index 6eda97c0..9d780b96 100644 --- a/src/utils/utils.h +++ b/src/utils/utils.h @@ -4,6 +4,8 @@ #include #include #include +#include +#include class Utils { -- Gitee From 975e3f6afbade409bf40722541bf5abe37ddb685 Mon Sep 17 00:00:00 2001 From: momen Date: Sun, 28 Sep 2025 14:32:26 +0800 Subject: [PATCH 063/105] =?UTF-8?q?update:=E6=9B=B4=E6=96=B0=E7=AA=97?= =?UTF-8?q?=E5=8F=A3=E5=A4=A7=E5=B0=8F=E6=94=B9=E4=B8=BA800*600?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/mainwindow.ui | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/mainwindow.ui b/src/mainwindow.ui index a53a4b88..8c2b025e 100644 --- a/src/mainwindow.ui +++ b/src/mainwindow.ui @@ -6,8 +6,8 @@ 0 0 - 1440 - 858 + 800 + 600 @@ -253,4 +253,4 @@ - + \ No newline at end of file -- Gitee From b461729fa587f4714450e4494d023c0857d530dc Mon Sep 17 00:00:00 2001 From: momen Date: Sun, 28 Sep 2025 15:22:24 +0800 Subject: [PATCH 064/105] =?UTF-8?q?feat:=E6=B7=BB=E5=8A=A0=E5=A4=8D?= =?UTF-8?q?=E9=80=89=E6=A1=86=E8=AE=A9=E7=94=A8=E6=88=B7=E9=80=89=E6=8B=A9?= =?UTF-8?q?=E6=8C=87=E5=AE=9A=E8=BD=AF=E4=BB=B6=E6=9B=B4=E6=96=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/appdelegate.cpp | 67 +++++++++++++++++++++++++++++++++++++++++++-- src/appdelegate.h | 9 ++++++ src/mainwindow.cpp | 30 ++++++++++++++++++-- src/mainwindow.h | 2 ++ 4 files changed, 104 insertions(+), 4 deletions(-) diff --git a/src/appdelegate.cpp b/src/appdelegate.cpp index 77209946..8a58a46f 100644 --- a/src/appdelegate.cpp +++ b/src/appdelegate.cpp @@ -51,6 +51,24 @@ void AppDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, c else painter->fillRect(option.rect, QColor("#F3F4F6")); + // 绘制复选框 + QString packageName = index.data(Qt::UserRole + 1).toString(); + bool isSelected = m_selectedPackages.contains(packageName); + + QRect checkboxRect(option.rect.left() + 10, option.rect.top() + (option.rect.height() - 20) / 2, 20, 20); + + // 绘制复选框边框 + painter->setPen(QColor("#888888")); + painter->setBrush(Qt::NoBrush); + painter->drawRect(checkboxRect); + + // 如果选中,绘制勾选标记 + if (isSelected) { + painter->setPen(QPen(QColor("#2563EB"), 2)); + painter->setBrush(QColor("#2563EB")); + painter->drawRect(checkboxRect.adjusted(4, 4, -4, -4)); + } + QFont boldFont = option.font; boldFont.setBold(true); QFont normalFont = option.font; @@ -65,7 +83,8 @@ void AppDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, c QRect rect = option.rect; int margin = 10, spacing = 6, iconSize = 40; - QRect iconRect(rect.left() + margin, rect.top() + (rect.height() - iconSize) / 2, iconSize, iconSize); + // 调整图标位置,为复选框留出空间 + QRect iconRect(rect.left() + 40, rect.top() + (rect.height() - iconSize) / 2, iconSize, iconSize); QIcon(iconPath).paint(painter, iconRect); int textX = iconRect.right() + margin; @@ -88,7 +107,6 @@ void AppDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, c painter->drawText(descRect, Qt::TextWordWrap, QString("包大小:%1 MB").arg(QString::number(size.toDouble() / (1024 * 1024), 'f', 2))); - QString packageName = index.data(Qt::UserRole + 1).toString(); bool isDownloading = m_downloads.contains(packageName) && m_downloads[packageName].isDownloading; int progress = m_downloads.value(packageName, DownloadInfo{0, false}).progress; bool isInstalled = m_downloads.value(packageName).isInstalled; @@ -162,6 +180,18 @@ bool AppDelegate::editorEvent(QEvent *event, QAbstractItemModel *model, QRect rect = option.rect; QString packageName = index.data(Qt::UserRole + 1).toString(); + // 检查是否点击了复选框 + QRect checkboxRect(rect.left() + 10, rect.top() + (rect.height() - 20) / 2, 20, 20); + if (checkboxRect.contains(mouseEvent->pos())) { + if (m_selectedPackages.contains(packageName)) { + m_selectedPackages.remove(packageName); + } else { + m_selectedPackages.insert(packageName); + } + emit updateDisplay(packageName); + return true; + } + if (m_downloads.contains(packageName) && m_downloads[packageName].isDownloading) { QRect cancelButtonRect(rect.right() - 70, rect.top() + (rect.height() - 20) / 2, 60, 20); if (cancelButtonRect.contains(mouseEvent->pos())) { @@ -320,4 +350,37 @@ void AppDelegate::startNextInstall() { void AppDelegate::updateSpinner() { m_spinnerAngle = (m_spinnerAngle + 10) % 360; // 每次增加10度 emit updateDisplay(m_installingPackage); // 仅刷新当前正在安装的项 +} + +// 新增:更新选中应用的方法 +void AppDelegate::startDownloadForSelected() { + if (!m_model) return; + for (int row = 0; row < m_model->rowCount(); ++row) { + QModelIndex index = m_model->index(row, 0); + QString packageName = index.data(Qt::UserRole + 1).toString(); + + // 只下载选中的应用 + if (m_selectedPackages.contains(packageName)) { + if (m_downloads.contains(packageName) && (m_downloads[packageName].isDownloading || m_downloads[packageName].isInstalled)) + continue; + QString downloadUrl = index.data(Qt::UserRole + 7).toString(); + QString outputPath = QString("%1/%2.metalink").arg(QDir::tempPath(), packageName); + m_downloads[packageName] = {0, true, false}; + m_downloadManager->startDownload(packageName, downloadUrl, outputPath); + emit updateDisplay(packageName); + } + } +} + +// 复选框相关方法实现 +void AppDelegate::setSelectedPackages(const QSet &selected) { + m_selectedPackages = selected; +} + +QSet AppDelegate::getSelectedPackages() const { + return m_selectedPackages; +} + +void AppDelegate::clearSelection() { + m_selectedPackages.clear(); } \ No newline at end of file diff --git a/src/appdelegate.h b/src/appdelegate.h index 579b8739..09d0ea63 100644 --- a/src/appdelegate.h +++ b/src/appdelegate.h @@ -28,6 +28,12 @@ public: bool editorEvent(QEvent *event, QAbstractItemModel *model, const QStyleOptionViewItem &option, const QModelIndex &index) override; void startDownloadForAll(); + void startDownloadForSelected(); + + // 复选框相关方法 + void setSelectedPackages(const QSet &selected); + QSet getSelectedPackages() const; + void clearSelection(); signals: void updateDisplay(const QString &packageName); @@ -40,6 +46,9 @@ private: DownloadManager *m_downloadManager; QHash m_downloads; QAbstractItemModel *m_model = nullptr; + + // 复选框相关成员变量 + QSet m_selectedPackages; QQueue m_installQueue; bool m_isInstalling = false; diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index b5ae7edd..ed12d2b7 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -55,9 +55,20 @@ MainWindow::MainWindow(QWidget *parent) // 新增:点击“更新全部”按钮批量下载 connect(ui->updatePushButton, &QPushButton::clicked, this, [=](){ - qDebug()<<"更新全部按钮被点击"; - m_delegate->startDownloadForAll(); + qDebug()<<"更新按钮被点击"; + if (m_delegate->getSelectedPackages().isEmpty()) { + // 没有选中任何应用,更新全部 + m_delegate->startDownloadForAll(); + } else { + // 有选中应用,更新选中 + m_delegate->startDownloadForSelected(); + m_delegate->clearSelection(); + updateButtonText(); + } }); + + // 新增:监听选择变化 + connect(m_delegate, &AppDelegate::updateDisplay, this, &MainWindow::handleSelectionChanged); checkUpdates(); // 新增:监听搜索框文本变化 @@ -283,4 +294,19 @@ void MainWindow::handleUpdateFinished(bool success) MainWindow::~MainWindow() { delete ui; +} + +// 新增:更新按钮文本 +void MainWindow::updateButtonText() { + int selectedCount = m_delegate->getSelectedPackages().size(); + if (selectedCount > 0) { + ui->updatePushButton->setText(QString("更新选中(%1)").arg(selectedCount)); + } else { + ui->updatePushButton->setText("更新全部"); + } +} + +// 新增:处理选择变化 +void MainWindow::handleSelectionChanged() { + updateButtonText(); } \ No newline at end of file diff --git a/src/mainwindow.h b/src/mainwindow.h index 8f1b0037..7a44f7a9 100644 --- a/src/mainwindow.h +++ b/src/mainwindow.h @@ -35,8 +35,10 @@ private: QListView *listView; // 声明 QListView 指针 QJsonArray m_allApps; // 新增:保存所有应用数据 void filterAppsByKeyword(const QString &keyword); // 新增:搜索过滤函数声明 + void updateButtonText(); // 新增:更新按钮文本 private slots: void handleUpdateFinished(bool success); // 新增:处理更新完成的槽函数 + void handleSelectionChanged(); // 新增:处理选择变化的槽函数 }; #endif // MAINWINDOW_H \ No newline at end of file -- Gitee From 0f82cc54d018e689f6b7afd259ddd823da80df5a Mon Sep 17 00:00:00 2001 From: momen Date: Mon, 29 Sep 2025 16:53:41 +0800 Subject: [PATCH 065/105] =?UTF-8?q?chore:=E6=9B=B4=E6=96=B0changelog?= =?UTF-8?q?=E4=B8=BA1.0.2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- debian/changelog | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/debian/changelog b/debian/changelog index 46eb85d9..9f4abb39 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,9 @@ +spark-update-tool (1.0.2) unstable; urgency=low + + * 添加复选框,选择多个包更新 + * 修复缩放问题 + + -- momen Mon, 29 Sep 2025 00:00:00 +0000 spark-update-tool (1.0.1) unstable; urgency=low * 修复窗口调整大小时的错误 -- Gitee From 7b26c6dd9c44e552ce518fc49cc179fe76582f1c Mon Sep 17 00:00:00 2001 From: momen Date: Tue, 30 Sep 2025 22:10:05 +0800 Subject: [PATCH 066/105] =?UTF-8?q?chore:=E6=B7=BB=E5=8A=A0=E5=BF=BD?= =?UTF-8?q?=E7=95=A5=E6=9B=B4=E6=96=B0=E9=85=8D=E7=BD=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CMakeLists.txt | 3 +- src/ignoreconfig.cpp | 102 +++++++++++++++++++++++++++++++++++++++++++ src/ignoreconfig.h | 39 +++++++++++++++++ 3 files changed, 143 insertions(+), 1 deletion(-) create mode 100644 src/ignoreconfig.cpp create mode 100644 src/ignoreconfig.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 6c624b41..ab9cd9c0 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -28,6 +28,7 @@ if(${QT_VERSION_MAJOR} GREATER_EQUAL 6) src/appdelegate.h src/appdelegate.cpp src/applistmodel.h src/applistmodel.cpp src/downloadmanager.h src/downloadmanager.cpp + src/ignoreconfig.h src/ignoreconfig.cpp ) # Define target properties for Android with Qt 6 as: # set_property(TARGET spark-update-tool APPEND PROPERTY QT_ANDROID_PACKAGE_SOURCE_DIR @@ -72,4 +73,4 @@ install(TARGETS spark-update-tool if(QT_VERSION_MAJOR EQUAL 6) qt_finalize_executable(spark-update-tool) -endif() +endif() \ No newline at end of file diff --git a/src/ignoreconfig.cpp b/src/ignoreconfig.cpp new file mode 100644 index 00000000..4bebe18d --- /dev/null +++ b/src/ignoreconfig.cpp @@ -0,0 +1,102 @@ +#include "ignoreconfig.h" +#include +#include +#include +#include +#include + +IgnoreConfig::IgnoreConfig(QObject *parent) + : QObject(parent) +{ + // 设置配置文件路径 + QString configDir = QStandardPaths::writableLocation(QStandardPaths::ConfigLocation); + QDir dir(configDir); + if (!dir.exists()) { + dir.mkpath("."); + } + m_configFilePath = dir.filePath("spark-update-tool/ignored_apps.conf"); + + // 确保目录存在 + QFileInfo fileInfo(m_configFilePath); + QDir configDirPath = fileInfo.dir(); + if (!configDirPath.exists()) { + configDirPath.mkpath("."); + } + + // 加载现有配置 + loadConfig(); +} + +void IgnoreConfig::addIgnoredApp(const QString &packageName, const QString &version) +{ + m_ignoredApps.insert(qMakePair(packageName, version)); + saveConfig(); +} + +void IgnoreConfig::removeIgnoredApp(const QString &packageName) +{ + // 移除所有该包名的版本 + auto it = m_ignoredApps.begin(); + while (it != m_ignoredApps.end()) { + if (it->first == packageName) { + it = m_ignoredApps.erase(it); + } else { + ++it; + } + } + saveConfig(); +} + +bool IgnoreConfig::isAppIgnored(const QString &packageName, const QString &version) const +{ + return m_ignoredApps.contains(qMakePair(packageName, version)); +} + +QSet> IgnoreConfig::getIgnoredApps() const +{ + return m_ignoredApps; +} + +bool IgnoreConfig::saveConfig() +{ + QFile file(m_configFilePath); + if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) { + qDebug() << "无法打开配置文件进行写入:" << m_configFilePath; + return false; + } + + QTextStream out(&file); + for (const auto &app : m_ignoredApps) { + out << app.first << "|" << app.second << "\n"; + } + file.close(); + return true; +} + +bool IgnoreConfig::loadConfig() +{ + QFile file(m_configFilePath); + if (!file.exists()) { + // 配置文件不存在,这是正常的,返回true表示没有错误 + return true; + } + + if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) { + qDebug() << "无法打开配置文件进行读取:" << m_configFilePath; + return false; + } + + m_ignoredApps.clear(); + QTextStream in(&file); + while (!in.atEnd()) { + QString line = in.readLine().trimmed(); + if (!line.isEmpty()) { + QStringList parts = line.split('|'); + if (parts.size() == 2) { + m_ignoredApps.insert(qMakePair(parts[0], parts[1])); + } + } + } + file.close(); + return true; +} \ No newline at end of file diff --git a/src/ignoreconfig.h b/src/ignoreconfig.h new file mode 100644 index 00000000..610fff59 --- /dev/null +++ b/src/ignoreconfig.h @@ -0,0 +1,39 @@ +#ifndef IGNORECONFIG_H +#define IGNORECONFIG_H + +#include +#include +#include +#include + +class IgnoreConfig : public QObject +{ + Q_OBJECT + +public: + explicit IgnoreConfig(QObject *parent = nullptr); + + // 添加忽略的应用(包名和版本号) + void addIgnoredApp(const QString &packageName, const QString &version); + + // 移除忽略的应用 + void removeIgnoredApp(const QString &packageName); + + // 检查应用是否被忽略 + bool isAppIgnored(const QString &packageName, const QString &version) const; + + // 获取所有被忽略的应用 + QSet> getIgnoredApps() const; + + // 保存配置到文件 + bool saveConfig(); + + // 从文件加载配置 + bool loadConfig(); + +private: + QSet> m_ignoredApps; + QString m_configFilePath; +}; + +#endif // IGNORECONFIG_H \ No newline at end of file -- Gitee From 2459224c7e68c2eb384aa104982635c98eb6a038 Mon Sep 17 00:00:00 2001 From: momen Date: Wed, 1 Oct 2025 22:18:56 +0800 Subject: [PATCH 067/105] =?UTF-8?q?chore:=E6=B7=BB=E5=8A=A0=E5=BF=BD?= =?UTF-8?q?=E7=95=A5=E6=8C=89=E9=92=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/appdelegate.cpp | 42 ++++++++++++++++++++++++++++++------------ src/appdelegate.h | 1 + src/mainwindow.cpp | 21 +++++++++++++++++++++ src/mainwindow.h | 3 +++ 4 files changed, 55 insertions(+), 12 deletions(-) diff --git a/src/appdelegate.cpp b/src/appdelegate.cpp index 8a58a46f..e29ee8da 100644 --- a/src/appdelegate.cpp +++ b/src/appdelegate.cpp @@ -123,14 +123,14 @@ void AppDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, c progressBarOption.textVisible = true; QApplication::style()->drawControl(QStyle::CE_ProgressBar, &progressBarOption, painter); - QRect buttonRect(rect.right() - 80, rect.top() + (rect.height() - 30) / 2, 70, 30); + QRect cancelButtonRect(rect.right() - 80, rect.top() + (rect.height() - 30) / 2, 70, 30); painter->setPen(Qt::NoPen); painter->setBrush(QColor("#ff4444")); - painter->drawRoundedRect(buttonRect, 4, 4); + painter->drawRoundedRect(cancelButtonRect, 4, 4); painter->setPen(Qt::white); painter->setFont(option.font); - painter->drawText(buttonRect, Qt::AlignCenter, "取消"); + painter->drawText(cancelButtonRect, Qt::AlignCenter, "取消"); } else if (isInstalling) { QRect spinnerRect(option.rect.right() - 80, option.rect.top() + (option.rect.height() - 30) / 2, 30, 30); @@ -146,23 +146,32 @@ void AppDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, c painter->setFont(option.font); painter->drawText(textRect, Qt::AlignLeft | Qt::AlignVCenter, "正在安装中"); } else { - QRect buttonRect(option.rect.right() - 80, option.rect.top() + (option.rect.height() - 30) / 2, 70, 30); + // 绘制忽略按钮 + QRect ignoreButtonRect(option.rect.right() - 160, option.rect.top() + (option.rect.height() - 30) / 2, 70, 30); + painter->setPen(Qt::NoPen); + painter->setBrush(QColor("#F3F4F6")); + painter->drawRoundedRect(ignoreButtonRect, 4, 4); + painter->setPen(QColor("#6B7280")); + painter->drawText(ignoreButtonRect, Qt::AlignCenter, "忽略"); + + // 绘制更新按钮 + QRect updateButtonRect(option.rect.right() - 80, option.rect.top() + (option.rect.height() - 30) / 2, 70, 30); painter->setPen(Qt::NoPen); if (isInstalled) { painter->setBrush(QColor("#10B981")); - painter->drawRoundedRect(buttonRect, 4, 4); + painter->drawRoundedRect(updateButtonRect, 4, 4); painter->setPen(Qt::white); - painter->drawText(buttonRect, Qt::AlignCenter, "已安装"); + painter->drawText(updateButtonRect, Qt::AlignCenter, "已安装"); } else if (m_downloads.contains(packageName) && !m_downloads[packageName].isDownloading) { painter->setBrush(QColor("#10B981")); - painter->drawRoundedRect(buttonRect, 4, 4); + painter->drawRoundedRect(updateButtonRect, 4, 4); painter->setPen(Qt::white); - painter->drawText(buttonRect, Qt::AlignCenter, "下载完成"); + painter->drawText(updateButtonRect, Qt::AlignCenter, "下载完成"); } else { painter->setBrush(QColor("#e9effd")); - painter->drawRoundedRect(buttonRect, 4, 4); + painter->drawRoundedRect(updateButtonRect, 4, 4); painter->setPen(QColor("#2563EB")); - painter->drawText(buttonRect, Qt::AlignCenter, "更新"); + painter->drawText(updateButtonRect, Qt::AlignCenter, "更新"); } } @@ -201,8 +210,17 @@ bool AppDelegate::editorEvent(QEvent *event, QAbstractItemModel *model, return true; } } else { - QRect buttonRect(rect.right() - 80, rect.top() + (rect.height() - 30) / 2, 70, 30); - if (buttonRect.contains(mouseEvent->pos())) { + // 检查是否点击了忽略按钮 + QRect ignoreButtonRect(rect.right() - 160, rect.top() + (rect.height() - 30) / 2, 70, 30); + if (ignoreButtonRect.contains(mouseEvent->pos())) { + QString currentVersion = index.data(Qt::UserRole + 2).toString(); + emit ignoreApp(packageName, currentVersion); + return true; + } + + // 检查是否点击了更新按钮 + QRect updateButtonRect(rect.right() - 80, rect.top() + (rect.height() - 30) / 2, 70, 30); + if (updateButtonRect.contains(mouseEvent->pos())) { if (m_downloads.contains(packageName) && !m_downloads[packageName].isDownloading) { return false; } diff --git a/src/appdelegate.h b/src/appdelegate.h index 09d0ea63..15972c10 100644 --- a/src/appdelegate.h +++ b/src/appdelegate.h @@ -38,6 +38,7 @@ public: signals: void updateDisplay(const QString &packageName); void updateFinished(bool success); //传递是否完成更新 + void ignoreApp(const QString &packageName, const QString &version); // 新增:忽略应用信号 private slots: void updateSpinner(); // 新增槽函数 diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index ed12d2b7..aa3fa03d 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -12,6 +12,7 @@ MainWindow::MainWindow(QWidget *parent) , ui(new Ui::MainWindow) , m_model(new AppListModel(this)) , m_delegate(new AppDelegate(this)) + , m_ignoreConfig(new IgnoreConfig(this)) { QIcon icon(":/resources/128*128/spark-update-tool.png"); setWindowIcon(icon); @@ -53,6 +54,9 @@ MainWindow::MainWindow(QWidget *parent) } }); + // 连接忽略应用信号 + connect(m_delegate, &AppDelegate::ignoreApp, this, &MainWindow::onIgnoreApp); + // 新增:点击“更新全部”按钮批量下载 connect(ui->updatePushButton, &QPushButton::clicked, this, [=](){ qDebug()<<"更新按钮被点击"; @@ -309,4 +313,21 @@ void MainWindow::updateButtonText() { // 新增:处理选择变化 void MainWindow::handleSelectionChanged() { updateButtonText(); +} + +// 新增:处理忽略应用的槽函数 +void MainWindow::onIgnoreApp(const QString &packageName, const QString &version) { + // 将应用添加到忽略配置中 + m_ignoreConfig->addIgnoredApp(packageName, version); + + // 从模型中移除被忽略的应用 + QJsonArray filteredApps; + for (const auto &item : m_allApps) { + QJsonObject obj = item.toObject(); + if (obj["package"].toString() != packageName) { + filteredApps.append(item); + } + } + m_allApps = filteredApps; + m_model->setUpdateData(filteredApps); } \ No newline at end of file diff --git a/src/mainwindow.h b/src/mainwindow.h index 7a44f7a9..c00714b7 100644 --- a/src/mainwindow.h +++ b/src/mainwindow.h @@ -5,6 +5,7 @@ #include "aptssupdater.h" #include "applistmodel.h" #include "appdelegate.h" +#include "ignoreconfig.h" #include #include // 添加头文件 #include @@ -32,6 +33,7 @@ private: void runAptssUpgrade(); AppListModel *m_model; AppDelegate *m_delegate; + IgnoreConfig *m_ignoreConfig; // 新增:忽略配置管理 QListView *listView; // 声明 QListView 指针 QJsonArray m_allApps; // 新增:保存所有应用数据 void filterAppsByKeyword(const QString &keyword); // 新增:搜索过滤函数声明 @@ -40,5 +42,6 @@ private: private slots: void handleUpdateFinished(bool success); // 新增:处理更新完成的槽函数 void handleSelectionChanged(); // 新增:处理选择变化的槽函数 + void onIgnoreApp(const QString &packageName, const QString &version); // 新增:处理忽略应用的槽函数 }; #endif // MAINWINDOW_H \ No newline at end of file -- Gitee From 3036749c693be7d18a62ae96842bd0b892366ba7 Mon Sep 17 00:00:00 2001 From: momen Date: Thu, 2 Oct 2025 23:57:10 +0800 Subject: [PATCH 068/105] =?UTF-8?q?chore:=E6=9B=B4=E6=96=B0changelog?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- debian/changelog | 1 + 1 file changed, 1 insertion(+) diff --git a/debian/changelog b/debian/changelog index 9f4abb39..170f5ef4 100644 --- a/debian/changelog +++ b/debian/changelog @@ -2,6 +2,7 @@ spark-update-tool (1.0.2) unstable; urgency=low * 添加复选框,选择多个包更新 * 修复缩放问题 + * 添加忽略应用功能 -- momen Mon, 29 Sep 2025 00:00:00 +0000 spark-update-tool (1.0.1) unstable; urgency=low -- Gitee From bd2a0ba7266280d88a59fff578842452d1655604 Mon Sep 17 00:00:00 2001 From: momen Date: Fri, 3 Oct 2025 23:50:52 +0800 Subject: [PATCH 069/105] =?UTF-8?q?chore:=E8=AF=BB=E5=8F=96=E5=BF=BD?= =?UTF-8?q?=E7=95=A5=E7=9A=84=E5=BA=94=E7=94=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/ignoreconfig.cpp | 31 ++++++++++++++++++++++++++++++- src/ignoreconfig.h | 3 +++ 2 files changed, 33 insertions(+), 1 deletion(-) diff --git a/src/ignoreconfig.cpp b/src/ignoreconfig.cpp index 4bebe18d..53d0c75d 100644 --- a/src/ignoreconfig.cpp +++ b/src/ignoreconfig.cpp @@ -4,12 +4,23 @@ #include #include #include +#include // for geteuid IgnoreConfig::IgnoreConfig(QObject *parent) : QObject(parent) { // 设置配置文件路径 - QString configDir = QStandardPaths::writableLocation(QStandardPaths::ConfigLocation); + QString configDir; + + // 检查是否以 root 权限运行 + if (geteuid() == 0) { + // 以 root 权限运行,使用 root 的配置目录 + configDir = "/root/.config"; + } else { + // 普通用户,使用标准配置目录 + configDir = QStandardPaths::writableLocation(QStandardPaths::ConfigLocation); + } + QDir dir(configDir); if (!dir.exists()) { dir.mkpath("."); @@ -25,6 +36,9 @@ IgnoreConfig::IgnoreConfig(QObject *parent) // 加载现有配置 loadConfig(); + + // 输出忽略列表到 qDebug + printIgnoredApps(); } void IgnoreConfig::addIgnoredApp(const QString &packageName, const QString &version) @@ -57,6 +71,21 @@ QSet> IgnoreConfig::getIgnoredApps() const return m_ignoredApps; } +void IgnoreConfig::printIgnoredApps() const +{ + qDebug() << "=== 忽略的应用列表 ==="; + qDebug() << "配置文件路径:" << m_configFilePath; + + if (m_ignoredApps.isEmpty()) { + qDebug() << "没有忽略的应用"; + } else { + for (const auto &app : m_ignoredApps) { + qDebug() << "忽略的应用:" << app.first << "版本:" << app.second; + } + } + qDebug() << "===================="; +} + bool IgnoreConfig::saveConfig() { QFile file(m_configFilePath); diff --git a/src/ignoreconfig.h b/src/ignoreconfig.h index 610fff59..2952eca2 100644 --- a/src/ignoreconfig.h +++ b/src/ignoreconfig.h @@ -25,6 +25,9 @@ public: // 获取所有被忽略的应用 QSet> getIgnoredApps() const; + // 输出所有被忽略的应用到 qDebug + void printIgnoredApps() const; + // 保存配置到文件 bool saveConfig(); -- Gitee From a285c02cc9c49eb2bd3af7e68d272426c60b5be0 Mon Sep 17 00:00:00 2001 From: momen Date: Sat, 4 Oct 2025 23:49:32 +0800 Subject: [PATCH 070/105] =?UTF-8?q?chore:=E8=BE=93=E5=87=BA=E6=97=A5?= =?UTF-8?q?=E5=BF=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/aptssupdater.cpp | 26 +++++++++++++++++--------- src/mainwindow.cpp | 9 ++++++++- 2 files changed, 25 insertions(+), 10 deletions(-) diff --git a/src/aptssupdater.cpp b/src/aptssupdater.cpp index c4bd9060..60e697a7 100644 --- a/src/aptssupdater.cpp +++ b/src/aptssupdater.cpp @@ -18,8 +18,9 @@ QStringList aptssUpdater::getUpdateablePackages() QString command = R"(env LANGUAGE=en_US /usr/bin/apt -c /opt/durapps/spark-store/bin/apt-fast-conf/aptss-apt.conf list --upgradable -o Dir::Etc::sourcelist="/opt/durapps/spark-store/bin/apt-fast-conf/sources.list.d/sparkstore.list" -o Dir::Etc::sourceparts="/dev/null" -o APT::Get::List-Cleanup="0" | awk 'NR>1')"; process.start("bash", QStringList() << "-c" << command); - if (!process.waitForFinished()) { - qWarning() << "Process failed to finish."; + if (!process.waitForFinished(30000)) { // 30秒超时 + qWarning() << "Process failed to finish within 30 seconds."; + process.kill(); return packageDetails; } @@ -83,8 +84,9 @@ QStringList aptssUpdater::getPackageSizes() "-o Dir::Etc::sourceparts=\"/dev/null\"").arg(packageName); process.start("bash", QStringList() << "-c" << command); - if (!process.waitForFinished()) { - qWarning() << "获取包信息失败:" << packageName; + if (!process.waitForFinished(30000)) { // 30秒超时 + qWarning() << "获取包信息失败:" << packageName << "(超时)"; + process.kill(); continue; } @@ -130,7 +132,11 @@ QStringList aptssUpdater::getDesktopAppNames() // 获取包文件列表 dpkgProcess.start("dpkg", QStringList() << "-L" << packageName); - dpkgProcess.waitForFinished(); + if (!dpkgProcess.waitForFinished(30000)) { // 30秒超时 + qWarning() << "获取包文件列表失败:" << packageName << "(超时)"; + dpkgProcess.kill(); + continue; + } QStringList files = QString(dpkgProcess.readAllStandardOutput()).split('\n', Qt::SkipEmptyParts); // 先检查常规应用目录 @@ -236,7 +242,11 @@ QStringList aptssUpdater::getPackageIcons() // 获取包文件列表 dpkgProcess.start("dpkg", QStringList() << "-L" << packageName); - dpkgProcess.waitForFinished(); + if (!dpkgProcess.waitForFinished(30000)) { // 30秒超时 + qWarning() << "获取包文件列表失败:" << packageName << "(超时)"; + dpkgProcess.kill(); + continue; + } QStringList files = QString(dpkgProcess.readAllStandardOutput()).split('\n', Qt::SkipEmptyParts); // 查找.desktop文件 @@ -393,6 +403,4 @@ QJsonArray aptssUpdater::getUpdateInfoAsJson() } qDebug()< Date: Sun, 5 Oct 2025 02:34:30 +0800 Subject: [PATCH 071/105] =?UTF-8?q?fix:root=E8=B4=A6=E6=88=B7=E6=9B=B4?= =?UTF-8?q?=E6=96=B0=E5=8D=A1=E6=AD=BB=E7=9A=84=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/aptssupdater.cpp | 9 ++++++--- src/mainwindow.cpp | 18 +++++++++++++----- 2 files changed, 19 insertions(+), 8 deletions(-) diff --git a/src/aptssupdater.cpp b/src/aptssupdater.cpp index 60e697a7..2ba3f338 100644 --- a/src/aptssupdater.cpp +++ b/src/aptssupdater.cpp @@ -69,7 +69,6 @@ QStringList aptssUpdater::getUpdateablePackages() QStringList aptssUpdater::getPackageSizes() { QStringList packageDetails; - QProcess process; // 获取可更新包名列表 QStringList updateablePackages; @@ -78,6 +77,8 @@ QStringList aptssUpdater::getPackageSizes() } foreach (const QString &packageName, updateablePackages) { + QProcess process; // 在循环内部创建新的QProcess实例 + // 构建新命令(包含包名参数) QString command = QString("apt download %1 --print-uris -c /opt/durapps/spark-store/bin/apt-fast-conf/aptss-apt.conf " "-o Dir::Etc::sourcelist=\"/opt/durapps/spark-store/bin/apt-fast-conf/sources.list.d/sparkstore.list\" " @@ -118,7 +119,6 @@ QStringList aptssUpdater::getPackageSizes() QStringList aptssUpdater::getDesktopAppNames() { QStringList appNames; - QProcess dpkgProcess; // 获取当前系统语言环境 QString lang = QLocale().name().replace("_", "-"); @@ -127,6 +127,8 @@ QStringList aptssUpdater::getDesktopAppNames() QStringList packages = packageName; foreach (const QString &package, packages) { + QProcess dpkgProcess; // 在循环内部创建新的QProcess实例 + QString packageName = package.split(":")[0]; QString finalName = packageName; // 默认使用包名 @@ -231,12 +233,13 @@ bool aptssUpdater::checkDesktopFiles(const QStringList &desktopFiles, QString &a QStringList aptssUpdater::getPackageIcons() { QStringList packageIcons; - QProcess dpkgProcess; // 遍历所有可更新包 QStringList packages = packageName; foreach (const QString &package, packages) { + QProcess dpkgProcess; // 在循环内部创建新的QProcess实例 + QString packageName = package.split(":")[0]; QString iconPath = ":/resources/default_icon.svg"; // 默认图标 diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index 1b333ff7..e2801acf 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -7,6 +7,7 @@ #include // 新增 #include #include +#include // for geteuid MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) , ui(new Ui::MainWindow) @@ -262,11 +263,18 @@ void MainWindow::filterAppsByKeyword(const QString &keyword) void MainWindow::runAptssUpgrade() { QProcess process; - QStringList args; - args << "sudo" <<"aptss" << "ssupdate"; - process.start("sudo", args); + + // 检查是否已经是root用户,如果是则直接执行命令,否则使用sudo + if (geteuid() == 0) { + // root用户直接执行 + process.start("aptss", QStringList() << "ssupdate"); + } else { + // 非root用户使用sudo + process.start("sudo", QStringList() << "aptss" << "ssupdate"); + } + if (!process.waitForStarted(5000)) { - QMessageBox::warning(this, "升级失败", "无法启动 sudo aptss ssupdate"); + QMessageBox::warning(this, "升级失败", "无法启动 aptss ssupdate"); return; } process.write("n\n"); @@ -280,7 +288,7 @@ void MainWindow::runAptssUpgrade() } if (process.exitCode() != 0) { - QMessageBox::warning(this, "升级失败", "执行 sudo aptss ssupdate 失败,请检查系统环境或稍后再试。"); + QMessageBox::warning(this, "升级失败", "执行 aptss ssupdate 失败,请检查系统环境或稍后再试。"); } } void MainWindow::closeEvent(QCloseEvent *event) -- Gitee From 207d42153f38725dbd0a88fdc98ce6208ff934e6 Mon Sep 17 00:00:00 2001 From: momen Date: Sun, 5 Oct 2025 02:40:17 +0800 Subject: [PATCH 072/105] =?UTF-8?q?fix:root=E8=B4=A6=E6=88=B7=E4=B8=8B?= =?UTF-8?q?=E6=97=A0=E6=B3=95=E6=AD=A3=E7=A1=AE=E8=8E=B7=E5=BE=97=E5=8C=85?= =?UTF-8?q?=E5=A4=A7=E5=B0=8F=E7=9A=84=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/aptssupdater.cpp | 51 +++++++++++++++++++++++++++++++++----------- 1 file changed, 38 insertions(+), 13 deletions(-) diff --git a/src/aptssupdater.cpp b/src/aptssupdater.cpp index 2ba3f338..c6ddd7d6 100644 --- a/src/aptssupdater.cpp +++ b/src/aptssupdater.cpp @@ -79,8 +79,14 @@ QStringList aptssUpdater::getPackageSizes() foreach (const QString &packageName, updateablePackages) { QProcess process; // 在循环内部创建新的QProcess实例 - // 构建新命令(包含包名参数) - QString command = QString("apt download %1 --print-uris -c /opt/durapps/spark-store/bin/apt-fast-conf/aptss-apt.conf " + // 设置环境变量确保在root权限下也能正确执行 + QProcessEnvironment env = QProcessEnvironment::systemEnvironment(); + env.insert("HOME", "/tmp"); // 设置HOME环境变量 + env.insert("LANGUAGE", "en_US"); // 设置语言环境 + process.setProcessEnvironment(env); + + // 使用apt-cache show获取包信息,包括大小 + QString command = QString("apt-cache show %1 -c /opt/durapps/spark-store/bin/apt-fast-conf/aptss-apt.conf " "-o Dir::Etc::sourcelist=\"/opt/durapps/spark-store/bin/apt-fast-conf/sources.list.d/sparkstore.list\" " "-o Dir::Etc::sourceparts=\"/dev/null\"").arg(packageName); @@ -92,19 +98,38 @@ QStringList aptssUpdater::getPackageSizes() } QString output = process.readAllStandardOutput(); - // 使用正则匹配所有信息 - // 调整正则表达式匹配分组 - QRegularExpression regex(R"('([^']+)'\s+(\S+)\s+(\d+)\s+SHA512:([^\s]+))"); // 分组1:URL 分组2:文件名 分组3:大小 分组4:SHA512 - QRegularExpressionMatch match = regex.match(output); - - if (match.hasMatch()) { - QString url = match.captured(1); - QString fileName = match.captured(2); - QString size = match.captured(3); - QString sha512 = match.captured(4); - + QString errorOutput = process.readAllStandardError(); + + // 如果有错误输出,打印出来以便调试 + if (!errorOutput.isEmpty()) { + qWarning() << "apt-cache show命令错误输出:" << errorOutput; + } + + // 解析apt-cache show的输出获取包大小 + QStringList lines = output.split('\n'); + QString size; + QString filename; + QString sha512; + + for (const QString &line : lines) { + if (line.startsWith("Size:")) { + size = line.mid(6).trimmed(); // 跳过"Size:"前缀 + } else if (line.startsWith("Filename:")) { + filename = line.mid(10).trimmed(); // 跳过"Filename:"前缀 + } else if (line.startsWith("SHA512:")) { + sha512 = line.mid(8).trimmed(); // 跳过"SHA512:"前缀 + } + } + + // 构造下载URL + QString url = "http://sucdn.jerrywang.top/sparkstore/" + filename; + + // 如果获取到大小信息,则添加到结果中 + if (!size.isEmpty()) { // 调整字段顺序:包名 | 大小 | URL | SHA512 packageDetails << QString("%1: %2|%3|%4").arg(packageName, size, url, sha512); + } else { + qWarning() << "无法获取包大小信息:" << packageName; } } -- Gitee From c6b1bcf4a8fd6a677d153a37efa3b0f449962b45 Mon Sep 17 00:00:00 2001 From: momen Date: Mon, 6 Oct 2025 14:59:13 +0800 Subject: [PATCH 073/105] =?UTF-8?q?chore:=E6=99=AE=E9=80=9A=E7=94=A8?= =?UTF-8?q?=E6=88=B7=E6=8F=90=E6=9D=83=E5=90=8E=E7=9A=84=E5=BF=BD=E7=95=A5?= =?UTF-8?q?=E6=96=87=E4=BB=B6=E5=AD=98=E6=94=BE=E5=88=B0=E7=94=A8=E6=88=B7?= =?UTF-8?q?=E7=9B=AE=E5=BD=95=E4=B8=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/ignoreconfig.cpp | 21 +++++++++++++++++++-- src/main.cpp | 2 ++ 2 files changed, 21 insertions(+), 2 deletions(-) diff --git a/src/ignoreconfig.cpp b/src/ignoreconfig.cpp index 53d0c75d..32089cd5 100644 --- a/src/ignoreconfig.cpp +++ b/src/ignoreconfig.cpp @@ -14,8 +14,25 @@ IgnoreConfig::IgnoreConfig(QObject *parent) // 检查是否以 root 权限运行 if (geteuid() == 0) { - // 以 root 权限运行,使用 root 的配置目录 - configDir = "/root/.config"; + // 首先检查是否有 SUDO_USER_HOME 环境变量(表示是通过 pkexec 提权的普通用户) + QByteArray sudoUserHomeEnv = qgetenv("SUDO_USER_HOME"); + if (!sudoUserHomeEnv.isEmpty()) { + // 通过 pkexec 提权的普通用户,使用原用户的配置目录 + QString sudoUserHomePath = QString::fromLocal8Bit(sudoUserHomeEnv); + configDir = sudoUserHomePath + "/.config"; + } else { + // 获取实际的 HOME 目录来判断是真正的 root 用户还是其他方式提权的用户 + QByteArray homeEnv = qgetenv("HOME"); + QString homePath = QString::fromLocal8Bit(homeEnv); + + if (homePath == "/root") { + // 真正的 root 用户,使用 /root/.config + configDir = "/root/.config"; + } else { + // 其他方式提权的用户,使用 HOME 目录下的配置 + configDir = homePath + "/.config"; + } + } } else { // 普通用户,使用标准配置目录 configDir = QStandardPaths::writableLocation(QStandardPaths::ConfigLocation); diff --git a/src/main.cpp b/src/main.cpp index a3df5a43..f70a913e 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -16,11 +16,13 @@ bool elevateToRoot() { QByteArray display = qgetenv("DISPLAY"); QByteArray xauthority = qgetenv("XAUTHORITY"); + QByteArray home = qgetenv("HOME"); // 获取原始用户的 HOME 目境变量 QStringList args; args << "env" << "DISPLAY=" + display << "XAUTHORITY=" + xauthority + << "SUDO_USER_HOME=" + home // 传递原始用户的 HOME 路径 << program; QProcess process; -- Gitee From 01d2a2f1d83e73c301a0d75efdb70385d68e0907 Mon Sep 17 00:00:00 2001 From: momen Date: Tue, 7 Oct 2025 16:52:56 +0800 Subject: [PATCH 074/105] =?UTF-8?q?update:=E5=85=81=E8=AE=B8=E7=94=A8?= =?UTF-8?q?=E6=88=B7=E5=BF=BD=E7=95=A5=E5=BA=94=E7=94=A8=E6=9B=B4=E6=96=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/appdelegate.cpp | 61 +++++++++++++++++++++++--- src/appdelegate.h | 1 + src/applistmodel.cpp | 14 +++++- src/applistmodel.h | 5 ++- src/mainwindow.cpp | 102 +++++++++++++++++++++++++++++++++++++------ src/mainwindow.h | 1 + 6 files changed, 161 insertions(+), 23 deletions(-) diff --git a/src/appdelegate.cpp b/src/appdelegate.cpp index e29ee8da..e51bff88 100644 --- a/src/appdelegate.cpp +++ b/src/appdelegate.cpp @@ -46,6 +46,9 @@ void AppDelegate::setModel(QAbstractItemModel *model) { void AppDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const { painter->save(); + // 检查是否为忽略状态 + bool isIgnored = index.data(Qt::UserRole + 8).toBool(); + if (option.state & QStyle::State_Selected) painter->fillRect(option.rect, option.palette.highlight()); else @@ -58,12 +61,13 @@ void AppDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, c QRect checkboxRect(option.rect.left() + 10, option.rect.top() + (option.rect.height() - 20) / 2, 20, 20); // 绘制复选框边框 - painter->setPen(QColor("#888888")); + QColor checkboxColor = isIgnored ? QColor("#CCCCCC") : QColor("#888888"); + painter->setPen(checkboxColor); painter->setBrush(Qt::NoBrush); painter->drawRect(checkboxRect); // 如果选中,绘制勾选标记 - if (isSelected) { + if (isSelected && !isIgnored) { painter->setPen(QPen(QColor("#2563EB"), 2)); painter->setBrush(QColor("#2563EB")); painter->drawRect(checkboxRect.adjusted(4, 4, -4, -4)); @@ -85,25 +89,42 @@ void AppDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, c // 调整图标位置,为复选框留出空间 QRect iconRect(rect.left() + 40, rect.top() + (rect.height() - iconSize) / 2, iconSize, iconSize); - QIcon(iconPath).paint(painter, iconRect); + + // 如果是忽略状态,绘制灰色图标 + if (isIgnored) { + // 创建灰度效果 + QPixmap originalPixmap = QIcon(iconPath).pixmap(iconSize, iconSize); + QPixmap grayPixmap(originalPixmap.size()); + grayPixmap.fill(Qt::transparent); + QPainter grayPainter(&grayPixmap); + grayPainter.setOpacity(0.3); // 设置透明度使其变灰 + grayPainter.drawPixmap(0, 0, originalPixmap); + grayPainter.end(); + painter->drawPixmap(iconRect, grayPixmap); + } else { + QIcon(iconPath).paint(painter, iconRect); + } int textX = iconRect.right() + margin; int textWidth = rect.width() - textX - 100; QRect nameRect(textX, rect.top() + margin, textWidth, 20); painter->setFont(boldFont); - painter->setPen(QColor("#333333")); + QColor nameColor = isIgnored ? QColor("#999999") : QColor("#333333"); + painter->setPen(nameColor); painter->drawText(nameRect, Qt::AlignLeft | Qt::AlignVCenter, name); QRect versionRect(textX, nameRect.bottom() + spacing, textWidth, 20); painter->setFont(normalFont); - painter->setPen(QColor("#888888")); + QColor versionColor = isIgnored ? QColor("#AAAAAA") : QColor("#888888"); + painter->setPen(versionColor); painter->drawText(versionRect, Qt::AlignLeft | Qt::AlignVCenter, QString("当前版本: %1 → 新版本: %2").arg(currentVersion, newVersion)); QRect descRect(textX, versionRect.bottom() + spacing, textWidth, 40); painter->setFont(normalFont); - painter->setPen(QColor("#AAAAAA")); + QColor descColor = isIgnored ? QColor("#CCCCCC") : QColor("#AAAAAA"); + painter->setPen(descColor); painter->drawText(descRect, Qt::TextWordWrap, QString("包大小:%1 MB").arg(QString::number(size.toDouble() / (1024 * 1024), 'f', 2))); @@ -112,7 +133,21 @@ void AppDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, c bool isInstalled = m_downloads.value(packageName).isInstalled; bool isInstalling = m_downloads.value(packageName).isInstalling; - if (isDownloading) { + // 如果是忽略状态,显示"已忽略"文本和"取消忽略"按钮 + if (isIgnored) { + QRect ignoredTextRect(rect.right() - 170, rect.top() + (rect.height() - 30) / 2, 80, 30); + painter->setPen(QColor("#999999")); + painter->setFont(option.font); + painter->drawText(ignoredTextRect, Qt::AlignCenter, "已忽略"); + + // 绘制取消忽略按钮 + QRect unignoreButtonRect(rect.right() - 80, rect.top() + (rect.height() - 30) / 2, 70, 30); + painter->setPen(Qt::NoPen); + painter->setBrush(QColor("#F3F4F6")); + painter->drawRoundedRect(unignoreButtonRect, 4, 4); + painter->setPen(QColor("#6B7280")); + painter->drawText(unignoreButtonRect, Qt::AlignCenter, "取消忽略"); + } else if (isDownloading) { QRect progressRect(rect.right() - 270, rect.top() + (rect.height() - 20) / 2, 150, 20); QStyleOptionProgressBar progressBarOption; progressBarOption.rect = progressRect; @@ -188,6 +223,18 @@ bool AppDelegate::editorEvent(QEvent *event, QAbstractItemModel *model, QMouseEvent *mouseEvent = static_cast(event); QRect rect = option.rect; QString packageName = index.data(Qt::UserRole + 1).toString(); + + // 检查是否为忽略状态,如果是则只允许取消忽略按钮的交互 + bool isIgnored = index.data(Qt::UserRole + 8).toBool(); + if (isIgnored) { + QRect unignoreButtonRect(option.rect.right() - 80, option.rect.top() + (option.rect.height() - 30) / 2, 70, 30); + if (unignoreButtonRect.contains(mouseEvent->pos())) { + // 发送取消忽略信号 + emit unignoreApp(packageName); + return true; + } + return true; // 消耗其他事件,不允许其他交互 + } // 检查是否点击了复选框 QRect checkboxRect(rect.left() + 10, rect.top() + (rect.height() - 20) / 2, 20, 20); diff --git a/src/appdelegate.h b/src/appdelegate.h index 15972c10..9385a334 100644 --- a/src/appdelegate.h +++ b/src/appdelegate.h @@ -39,6 +39,7 @@ signals: void updateDisplay(const QString &packageName); void updateFinished(bool success); //传递是否完成更新 void ignoreApp(const QString &packageName, const QString &version); // 新增:忽略应用信号 + void unignoreApp(const QString &packageName); // 新增:取消忽略应用信号 private slots: void updateSpinner(); // 新增槽函数 diff --git a/src/applistmodel.cpp b/src/applistmodel.cpp index 31e244a9..9d7c83df 100644 --- a/src/applistmodel.cpp +++ b/src/applistmodel.cpp @@ -32,6 +32,8 @@ QVariant AppListModel::data(const QModelIndex &index, int role) const return map.value("description"); case Qt::UserRole + 7: // 下载 URL return map.value("download_url"); // 返回下载 URL + case Qt::UserRole + 8: // 忽略状态 + return map.value("ignored"); default: return QVariant(); } @@ -52,11 +54,21 @@ void AppListModel::setUpdateData(const QJsonArray &updateInfo) map["icon"] = obj["icon"].toString(); map["size"] = obj["size"].toString(); map["download_url"] = obj["download_url"].toString(); // 确保设置下载 URL + map["ignored"] = obj["ignored"].toBool(); // 设置忽略状态 m_data.append(map); // 添加到 QList - qDebug() << "设置到模型的包名:" << map["package"].toString(); + qDebug() << "设置到模型的包名:" << map["package"].toString() << "忽略状态:" << map["ignored"].toBool(); qDebug() << "设置到模型的下载 URL:" << map["download_url"].toString(); // 检查设置的数据 } endResetModel(); } + +bool AppListModel::isAppIgnored(const QModelIndex &index) const +{ + if (!index.isValid() || index.row() >= m_data.size()) + return false; + + const QVariantMap &map = m_data.at(index.row()); + return map.value("ignored").toBool(); +} \ No newline at end of file diff --git a/src/applistmodel.h b/src/applistmodel.h index 9e5e79ab..d3f304da 100644 --- a/src/applistmodel.h +++ b/src/applistmodel.h @@ -18,9 +18,12 @@ public: // 设置更新数据 void setUpdateData(const QJsonArray &data); + + // 获取忽略状态 + bool isAppIgnored(const QModelIndex &index) const; private: QList m_data; // 修改类型为 QList }; -#endif // APPLISTMODEL_H +#endif // APPLISTMODEL_H \ No newline at end of file diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index e2801acf..4e763712 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -55,8 +55,9 @@ MainWindow::MainWindow(QWidget *parent) } }); - // 连接忽略应用信号 - connect(m_delegate, &AppDelegate::ignoreApp, this, &MainWindow::onIgnoreApp); + // 连接应用委托的信号 + connect(m_delegate, &AppDelegate::ignoreApp, this, &MainWindow::onIgnoreApp); + connect(m_delegate, &AppDelegate::unignoreApp, this, &MainWindow::onUnignoreApp); // 新增:点击“更新全部”按钮批量下载 connect(ui->updatePushButton, &QPushButton::clicked, this, [=](){ @@ -229,12 +230,42 @@ void MainWindow::checkUpdates() { aptssUpdater updater; QJsonArray updateInfo = updater.getUpdateInfoAsJson(); - m_allApps = updateInfo; // 保存所有应用数据 - m_model->setUpdateData(updateInfo); - + + // 分离正常应用和忽略应用 + QJsonArray normalApps; + QJsonArray ignoredApps; + for (const auto &item : updateInfo) { QJsonObject obj = item.toObject(); - qDebug() << "模型设置的包名:" << obj["package"].toString(); + QString packageName = obj["package"].toString(); + QString currentVersion = obj["current_version"].toString(); + + // 检查应用是否被忽略 + if (m_ignoreConfig->isAppIgnored(packageName, currentVersion)) { + // 标记为忽略状态 + obj["ignored"] = true; + ignoredApps.append(obj); + } else { + obj["ignored"] = false; + normalApps.append(obj); + } + } + + // 合并数组:正常应用在前,忽略应用在后 + QJsonArray finalApps; + for (const auto &item : normalApps) { + finalApps.append(item); + } + for (const auto &item : ignoredApps) { + finalApps.append(item); + } + + m_allApps = finalApps; // 保存所有应用数据 + m_model->setUpdateData(finalApps); + + for (const auto &item : finalApps) { + QJsonObject obj = item.toObject(); + qDebug() << "模型设置的包名:" << obj["package"].toString() << "忽略状态:" << obj["ignored"].toBool(); qDebug() << "模型设置的下载 URL:" << obj["download_url"].toString(); // 检查模型数据 } } @@ -246,7 +277,11 @@ void MainWindow::filterAppsByKeyword(const QString &keyword) m_model->setUpdateData(m_allApps); return; } - QJsonArray filtered; + + // 分离正常应用和忽略应用 + QJsonArray normalApps; + QJsonArray ignoredApps; + for (const auto &item : m_allApps) { QJsonObject obj = item.toObject(); // 可根据需要匹配更多字段 @@ -254,9 +289,25 @@ void MainWindow::filterAppsByKeyword(const QString &keyword) QString package = obj.value("package").toString(); if (name.contains(keyword, Qt::CaseInsensitive) || package.contains(keyword, Qt::CaseInsensitive)) { - filtered.append(item); + + // 检查是否为忽略状态 + if (obj.value("ignored").toBool()) { + ignoredApps.append(item); + } else { + normalApps.append(item); + } } } + + // 合并数组:正常应用在前,忽略应用在后 + QJsonArray filtered; + for (const auto &item : normalApps) { + filtered.append(item); + } + for (const auto &item : ignoredApps) { + filtered.append(item); + } + m_model->setUpdateData(filtered); } @@ -335,14 +386,37 @@ void MainWindow::onIgnoreApp(const QString &packageName, const QString &version) // 将应用添加到忽略配置中 m_ignoreConfig->addIgnoredApp(packageName, version); - // 从模型中移除被忽略的应用 - QJsonArray filteredApps; + // 更新模型中应用的状态,而不是移除 + QJsonArray updatedApps; + for (const auto &item : m_allApps) { + QJsonObject obj = item.toObject(); + if (obj["package"].toString() == packageName) { + obj["ignored"] = true; // 标记为忽略状态 + } + updatedApps.append(obj); + } + m_allApps = updatedApps; + + // 重新排序:正常应用在前,忽略应用在后 + checkUpdates(); +} + +// 新增:处理取消忽略应用的槽函数 +void MainWindow::onUnignoreApp(const QString &packageName) { + // 从忽略配置中移除应用 + m_ignoreConfig->removeIgnoredApp(packageName); + + // 更新模型中应用的状态 + QJsonArray updatedApps; for (const auto &item : m_allApps) { QJsonObject obj = item.toObject(); - if (obj["package"].toString() != packageName) { - filteredApps.append(item); + if (obj["package"].toString() == packageName) { + obj["ignored"] = false; // 标记为非忽略状态 } + updatedApps.append(obj); } - m_allApps = filteredApps; - m_model->setUpdateData(filteredApps); + m_allApps = updatedApps; + + // 重新排序:正常应用在前,忽略应用在后 + checkUpdates(); } \ No newline at end of file diff --git a/src/mainwindow.h b/src/mainwindow.h index c00714b7..5bf2f0a5 100644 --- a/src/mainwindow.h +++ b/src/mainwindow.h @@ -43,5 +43,6 @@ private slots: void handleUpdateFinished(bool success); // 新增:处理更新完成的槽函数 void handleSelectionChanged(); // 新增:处理选择变化的槽函数 void onIgnoreApp(const QString &packageName, const QString &version); // 新增:处理忽略应用的槽函数 + void onUnignoreApp(const QString &packageName); // 新增:处理取消忽略应用 }; #endif // MAINWINDOW_H \ No newline at end of file -- Gitee From 47dea9b3886f96cfffc7a5efd3204676b933f98c Mon Sep 17 00:00:00 2001 From: momen Date: Thu, 9 Oct 2025 16:06:16 +0800 Subject: [PATCH 075/105] =?UTF-8?q?chore:=E5=9B=9E=E9=80=80=E8=8E=B7?= =?UTF-8?q?=E5=8F=96=E5=9C=B0=E5=9D=80=E4=BB=A3=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/aptssupdater.cpp | 51 +++++++++++--------------------------------- 1 file changed, 13 insertions(+), 38 deletions(-) diff --git a/src/aptssupdater.cpp b/src/aptssupdater.cpp index c6ddd7d6..2ba3f338 100644 --- a/src/aptssupdater.cpp +++ b/src/aptssupdater.cpp @@ -79,14 +79,8 @@ QStringList aptssUpdater::getPackageSizes() foreach (const QString &packageName, updateablePackages) { QProcess process; // 在循环内部创建新的QProcess实例 - // 设置环境变量确保在root权限下也能正确执行 - QProcessEnvironment env = QProcessEnvironment::systemEnvironment(); - env.insert("HOME", "/tmp"); // 设置HOME环境变量 - env.insert("LANGUAGE", "en_US"); // 设置语言环境 - process.setProcessEnvironment(env); - - // 使用apt-cache show获取包信息,包括大小 - QString command = QString("apt-cache show %1 -c /opt/durapps/spark-store/bin/apt-fast-conf/aptss-apt.conf " + // 构建新命令(包含包名参数) + QString command = QString("apt download %1 --print-uris -c /opt/durapps/spark-store/bin/apt-fast-conf/aptss-apt.conf " "-o Dir::Etc::sourcelist=\"/opt/durapps/spark-store/bin/apt-fast-conf/sources.list.d/sparkstore.list\" " "-o Dir::Etc::sourceparts=\"/dev/null\"").arg(packageName); @@ -98,38 +92,19 @@ QStringList aptssUpdater::getPackageSizes() } QString output = process.readAllStandardOutput(); - QString errorOutput = process.readAllStandardError(); - - // 如果有错误输出,打印出来以便调试 - if (!errorOutput.isEmpty()) { - qWarning() << "apt-cache show命令错误输出:" << errorOutput; - } - - // 解析apt-cache show的输出获取包大小 - QStringList lines = output.split('\n'); - QString size; - QString filename; - QString sha512; - - for (const QString &line : lines) { - if (line.startsWith("Size:")) { - size = line.mid(6).trimmed(); // 跳过"Size:"前缀 - } else if (line.startsWith("Filename:")) { - filename = line.mid(10).trimmed(); // 跳过"Filename:"前缀 - } else if (line.startsWith("SHA512:")) { - sha512 = line.mid(8).trimmed(); // 跳过"SHA512:"前缀 - } - } - - // 构造下载URL - QString url = "http://sucdn.jerrywang.top/sparkstore/" + filename; - - // 如果获取到大小信息,则添加到结果中 - if (!size.isEmpty()) { + // 使用正则匹配所有信息 + // 调整正则表达式匹配分组 + QRegularExpression regex(R"('([^']+)'\s+(\S+)\s+(\d+)\s+SHA512:([^\s]+))"); // 分组1:URL 分组2:文件名 分组3:大小 分组4:SHA512 + QRegularExpressionMatch match = regex.match(output); + + if (match.hasMatch()) { + QString url = match.captured(1); + QString fileName = match.captured(2); + QString size = match.captured(3); + QString sha512 = match.captured(4); + // 调整字段顺序:包名 | 大小 | URL | SHA512 packageDetails << QString("%1: %2|%3|%4").arg(packageName, size, url, sha512); - } else { - qWarning() << "无法获取包大小信息:" << packageName; } } -- Gitee From 89fb73ae0cafa323406bca22cb3b0f6f95083713 Mon Sep 17 00:00:00 2001 From: momen Date: Fri, 10 Oct 2025 11:03:21 +0800 Subject: [PATCH 076/105] =?UTF-8?q?update:=E6=9B=B4=E6=96=B0=E6=9E=84?= =?UTF-8?q?=E5=BB=BA=E5=8C=85=E4=BF=A1=E6=81=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CMakeLists.txt | 17 +++++++++++------ debian/compat | 2 +- debian/rules | 22 +++++++++++++++++++++- src/appdelegate.h | 3 ++- 4 files changed, 35 insertions(+), 9 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index ab9cd9c0..cb948700 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -17,18 +17,23 @@ set(PROJECT_SOURCES src/mainwindow.cpp src/mainwindow.h src/mainwindow.ui + src/aptssupdater.h + src/aptssupdater.cpp + src/icons.qrc + src/appdelegate.h + src/appdelegate.cpp + src/applistmodel.h + src/applistmodel.cpp + src/downloadmanager.h + src/downloadmanager.cpp + src/ignoreconfig.h + src/ignoreconfig.cpp ) if(${QT_VERSION_MAJOR} GREATER_EQUAL 6) qt_add_executable(spark-update-tool MANUAL_FINALIZATION ${PROJECT_SOURCES} - src/aptssupdater.h src/aptssupdater.cpp - src/icons.qrc - src/appdelegate.h src/appdelegate.cpp - src/applistmodel.h src/applistmodel.cpp - src/downloadmanager.h src/downloadmanager.cpp - src/ignoreconfig.h src/ignoreconfig.cpp ) # Define target properties for Android with Qt 6 as: # set_property(TARGET spark-update-tool APPEND PROPERTY QT_ANDROID_PACKAGE_SOURCE_DIR diff --git a/debian/compat b/debian/compat index f11c82a4..ca7bf83a 100644 --- a/debian/compat +++ b/debian/compat @@ -1 +1 @@ -9 \ No newline at end of file +13 \ No newline at end of file diff --git a/debian/rules b/debian/rules index 1159ac4f..d9cedc76 100755 --- a/debian/rules +++ b/debian/rules @@ -1,7 +1,27 @@ #!/usr/bin/make -f +# 声明兼容性级别 +export DH_VERBOSE=1 + %: - dh $@ + dh $@ --buildsystem=cmake +# 确保使用CMake进行配置 override_dh_auto_configure: dh_auto_configure -- -DCMAKE_INSTALL_PREFIX=/usr + +# 确保使用CMake进行构建 +override_dh_auto_build: + dh_auto_build + +# 确保使用CMake进行安装 +override_dh_auto_install: + dh_auto_install + +# 确保使用CMake进行清理 +override_dh_auto_clean: + dh_auto_clean + +# 确保使用CMake进行依赖解析 +override_dh_shlibdeps: + dh_shlibdeps --dpkg-shlibdeps-params=--ignore-missing-info \ No newline at end of file diff --git a/src/appdelegate.h b/src/appdelegate.h index 9385a334..bedd6456 100644 --- a/src/appdelegate.h +++ b/src/appdelegate.h @@ -5,7 +5,8 @@ #include #include #include -#include +#include +#include #include "downloadmanager.h" -- Gitee From 8f240db798ebb6a94f888b355aed484a8480b280 Mon Sep 17 00:00:00 2001 From: momen Date: Sat, 11 Oct 2025 16:57:39 +0800 Subject: [PATCH 077/105] =?UTF-8?q?fix:=E4=BF=AE=E5=A4=8D=E5=85=B3?= =?UTF-8?q?=E9=97=AD=E6=8F=90=E7=A4=BA=E5=BC=B9=E7=AA=97=E6=97=B6=E6=9C=BA?= =?UTF-8?q?=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/appdelegate.cpp | 5 +++++ src/appdelegate.h | 4 ++++ src/mainwindow.cpp | 27 +++++++++++++++++++++++++-- 3 files changed, 34 insertions(+), 2 deletions(-) diff --git a/src/appdelegate.cpp b/src/appdelegate.cpp index e51bff88..c9e45406 100644 --- a/src/appdelegate.cpp +++ b/src/appdelegate.cpp @@ -448,4 +448,9 @@ QSet AppDelegate::getSelectedPackages() const { void AppDelegate::clearSelection() { m_selectedPackages.clear(); +} + +// 实现获取下载状态信息的方法 +const QHash& AppDelegate::getDownloads() const { + return m_downloads; } \ No newline at end of file diff --git a/src/appdelegate.h b/src/appdelegate.h index bedd6456..25ea3373 100644 --- a/src/appdelegate.h +++ b/src/appdelegate.h @@ -35,6 +35,10 @@ public: void setSelectedPackages(const QSet &selected); QSet getSelectedPackages() const; void clearSelection(); + + // 获取下载状态信息 + const QHash& getDownloads() const; + signals: void updateDisplay(const QString &packageName); diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index 4e763712..c93f09a7 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -344,8 +344,31 @@ void MainWindow::runAptssUpgrade() } void MainWindow::closeEvent(QCloseEvent *event) { - - QMessageBox::StandardButton reply = QMessageBox::question(this, "确认关闭", "正在更新,是否确认关闭窗口?", QMessageBox::Yes | QMessageBox::No); + // 检查是否正在进行更新 + bool isUpdating = false; + + // 通过AppDelegate检查是否有正在下载或安装的应用 + const QHash& downloads = m_delegate->getDownloads(); + for (auto it = downloads.constBegin(); it != downloads.constEnd(); ++it) { + if (it.value().isDownloading || it.value().isInstalling) { + isUpdating = true; + break; + } + } + + // 如果正在更新,才显示确认对话框 + if (isUpdating) { + QMessageBox::StandardButton reply = QMessageBox::question(this, "确认关闭", "正在更新,是否确认关闭窗口?", QMessageBox::Yes | QMessageBox::No); + + if (reply == QMessageBox::Yes) { + event->accept(); + } else { + event->ignore(); + } + } else { + // 如果没有更新,直接关闭窗口 + event->accept(); + } } void MainWindow::handleUpdateFinished(bool success) { -- Gitee From 35f34dd46992ed14a961ad1d638bb9d43ce42be9 Mon Sep 17 00:00:00 2001 From: momen Date: Sun, 12 Oct 2025 11:05:33 +0800 Subject: [PATCH 078/105] fix: Can't do app upgrade in mint by shenmo --- src/aptssupdater.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/aptssupdater.cpp b/src/aptssupdater.cpp index 2ba3f338..44b31105 100644 --- a/src/aptssupdater.cpp +++ b/src/aptssupdater.cpp @@ -80,7 +80,7 @@ QStringList aptssUpdater::getPackageSizes() QProcess process; // 在循环内部创建新的QProcess实例 // 构建新命令(包含包名参数) - QString command = QString("apt download %1 --print-uris -c /opt/durapps/spark-store/bin/apt-fast-conf/aptss-apt.conf " + QString command = QString("/usr/bin/apt download %1 --print-uris -c /opt/durapps/spark-store/bin/apt-fast-conf/aptss-apt.conf " "-o Dir::Etc::sourcelist=\"/opt/durapps/spark-store/bin/apt-fast-conf/sources.list.d/sparkstore.list\" " "-o Dir::Etc::sourceparts=\"/dev/null\"").arg(packageName); -- Gitee From b157f134d4ca45a43ac047ff510769b97147071e Mon Sep 17 00:00:00 2001 From: momen Date: Mon, 13 Oct 2025 16:58:00 +0800 Subject: [PATCH 079/105] =?UTF-8?q?chore:=E6=9B=B4=E6=96=B0=E8=BD=AF?= =?UTF-8?q?=E4=BB=B6=E5=90=8E=EF=BC=8C=E5=88=A0=E9=99=A4deb=E5=8C=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/appdelegate.cpp | 34 +++++++++++++++++++++++++++++++--- 1 file changed, 31 insertions(+), 3 deletions(-) diff --git a/src/appdelegate.cpp b/src/appdelegate.cpp index c9e45406..c9f851eb 100644 --- a/src/appdelegate.cpp +++ b/src/appdelegate.cpp @@ -369,11 +369,20 @@ void AppDelegate::startNextInstall() { qDebug().noquote() << QString::fromLocal8Bit(err); }); connect(m_installProcess, QOverload::of(&QProcess::finished), - this, [this, packageName, logFile](int exitCode, QProcess::ExitStatus status) { + this, [this, packageName, logFile, debPath](int exitCode, QProcess::ExitStatus status) { if (logFile) logFile->close(); m_downloads[packageName].isInstalling = false; if (exitCode == 0) { m_downloads[packageName].isInstalled = true; + + // 安装成功后删除deb包 + if (QFile::exists(debPath)) { + if (QFile::remove(debPath)) { + qDebug() << "已删除deb包:" << debPath; + } else { + qWarning() << "删除deb包失败:" << debPath; + } + } } emit updateDisplay(packageName); m_installProcess->deleteLater(); @@ -382,13 +391,23 @@ void AppDelegate::startNextInstall() { startNextInstall(); }); } else { - connect(m_installProcess, &QProcess::readyReadStandardOutput, this, [this, packageName]() { + connect(m_installProcess, &QProcess::readyReadStandardOutput, this, [this, packageName, debPath]() { QByteArray out = m_installProcess->readAllStandardOutput(); QString text = QString::fromLocal8Bit(out); qDebug().noquote() << text; if (text.contains(QStringLiteral("软件包已安装"))) { m_downloads[packageName].isInstalling = false; m_downloads[packageName].isInstalled = true; + + // 安装成功后删除deb包 + if (QFile::exists(debPath)) { + if (QFile::remove(debPath)) { + qDebug() << "已删除deb包:" << debPath; + } else { + qWarning() << "删除deb包失败:" << debPath; + } + } + emit updateDisplay(packageName); } }); @@ -397,7 +416,16 @@ void AppDelegate::startNextInstall() { qDebug().noquote() << QString::fromLocal8Bit(err); }); connect(m_installProcess, QOverload::of(&QProcess::finished), - this, [this, packageName](int /*exitCode*/, QProcess::ExitStatus /*status*/) { + this, [this, packageName, debPath](int exitCode, QProcess::ExitStatus /*status*/) { + // 如果通过退出码判断安装成功,也删除deb包 + if (exitCode == 0 && QFile::exists(debPath)) { + if (QFile::remove(debPath)) { + qDebug() << "已删除deb包:" << debPath; + } else { + qWarning() << "删除deb包失败:" << debPath; + } + } + emit updateDisplay(packageName); m_installProcess->deleteLater(); m_installProcess = nullptr; -- Gitee From 5754b3cfc2113d2490b5f0502891e377f3a18581 Mon Sep 17 00:00:00 2001 From: momen Date: Tue, 14 Oct 2025 11:57:40 +0800 Subject: [PATCH 080/105] =?UTF-8?q?fix:=E6=97=A0icon=E5=BA=94=E7=94=A8?= =?UTF-8?q?=E5=8A=A0=E8=BD=BD=E9=BB=98=E8=AE=A4=E5=9B=BE=E6=A0=87=E5=A4=B1?= =?UTF-8?q?=E8=B4=A5=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/appdelegate.cpp | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/appdelegate.cpp b/src/appdelegate.cpp index c9f851eb..fcaf2ace 100644 --- a/src/appdelegate.cpp +++ b/src/appdelegate.cpp @@ -90,10 +90,16 @@ void AppDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, c // 调整图标位置,为复选框留出空间 QRect iconRect(rect.left() + 40, rect.top() + (rect.height() - iconSize) / 2, iconSize, iconSize); + // 检查图标路径是否存在,如果不存在则使用默认图标 + QString finalIconPath = iconPath; + if (iconPath.isEmpty() || !QFile::exists(iconPath)) { + finalIconPath = ":/resources/default_icon.svg"; + } + // 如果是忽略状态,绘制灰色图标 if (isIgnored) { // 创建灰度效果 - QPixmap originalPixmap = QIcon(iconPath).pixmap(iconSize, iconSize); + QPixmap originalPixmap = QIcon(finalIconPath).pixmap(iconSize, iconSize); QPixmap grayPixmap(originalPixmap.size()); grayPixmap.fill(Qt::transparent); QPainter grayPainter(&grayPixmap); @@ -102,7 +108,7 @@ void AppDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, c grayPainter.end(); painter->drawPixmap(iconRect, grayPixmap); } else { - QIcon(iconPath).paint(painter, iconRect); + QIcon(finalIconPath).paint(painter, iconRect); } int textX = iconRect.right() + margin; -- Gitee From e8ea4ed1a99dbe2791dd010d57ed3b9973d88ddf Mon Sep 17 00:00:00 2001 From: momen Date: Wed, 15 Oct 2025 17:03:55 +0800 Subject: [PATCH 081/105] =?UTF-8?q?feat:=E5=BD=93/tmp=E8=B7=AF=E5=BE=84?= =?UTF-8?q?=E4=B8=8B=E5=AD=98=E5=9C=A8=E5=8C=85=E6=97=B6=EF=BC=8C=E7=9B=B4?= =?UTF-8?q?=E6=8E=A5=E5=AE=89=E8=A3=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/appdelegate.cpp | 31 ++++++++++++++++++++++++++----- 1 file changed, 26 insertions(+), 5 deletions(-) diff --git a/src/appdelegate.cpp b/src/appdelegate.cpp index fcaf2ace..61f91360 100644 --- a/src/appdelegate.cpp +++ b/src/appdelegate.cpp @@ -277,12 +277,33 @@ bool AppDelegate::editorEvent(QEvent *event, QAbstractItemModel *model, if (m_downloads.contains(packageName) && !m_downloads[packageName].isDownloading) { return false; } - QString downloadUrl = index.data(Qt::UserRole + 7).toString(); - QString outputPath = QString("%1/%2.metalink").arg(QDir::tempPath(), packageName); + + // 检查/tmp目录下是否已经存在deb包 + QDir tempDir(QDir::tempPath()); + QStringList debs = tempDir.entryList(QStringList() << QString("%1_*.deb").arg(packageName), QDir::Files); + QString debPath; + if (!debs.isEmpty()) { + debPath = tempDir.absoluteFilePath(debs.first()); + } else { + debs = tempDir.entryList(QStringList() << QString("%1*.deb").arg(packageName), QDir::Files); + if (!debs.isEmpty()) { + debPath = tempDir.absoluteFilePath(debs.first()); + } + } + + // 如果存在deb包,直接进行安装 + if (!debPath.isEmpty() && QFile::exists(debPath)) { + qDebug() << "发现已存在的deb包,直接进行安装:" << debPath; + enqueueInstall(packageName); + } else { + // 否则触发下载流程 + QString downloadUrl = index.data(Qt::UserRole + 7).toString(); + QString outputPath = QString("%1/%2.metalink").arg(QDir::tempPath(), packageName); - m_downloads[packageName] = {0, true}; - m_downloadManager->startDownload(packageName, downloadUrl, outputPath); - emit updateDisplay(packageName); + m_downloads[packageName] = {0, true}; + m_downloadManager->startDownload(packageName, downloadUrl, outputPath); + emit updateDisplay(packageName); + } return true; } } -- Gitee From 585d0582b88bca8e1cefc740ac40217382933953 Mon Sep 17 00:00:00 2001 From: momen Date: Thu, 16 Oct 2025 17:00:42 +0800 Subject: [PATCH 082/105] =?UTF-8?q?fix:=E4=BF=AE=E5=A4=8D=E6=97=A0icon?= =?UTF-8?q?=E6=97=B6=EF=BC=8C=E5=8A=A0=E8=BD=BD=E9=BB=98=E8=AE=A4=E5=9B=BE?= =?UTF-8?q?=E6=A0=87=E5=A4=B1=E6=95=88=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/appdelegate.cpp | 10 ++++++++++ src/aptssupdater.cpp | 7 +++++++ 2 files changed, 17 insertions(+) diff --git a/src/appdelegate.cpp b/src/appdelegate.cpp index 61f91360..83649e83 100644 --- a/src/appdelegate.cpp +++ b/src/appdelegate.cpp @@ -92,8 +92,18 @@ void AppDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, c // 检查图标路径是否存在,如果不存在则使用默认图标 QString finalIconPath = iconPath; + qDebug() << "原始图标路径:" << iconPath; if (iconPath.isEmpty() || !QFile::exists(iconPath)) { finalIconPath = ":/resources/default_icon.svg"; + qDebug() << "图标文件不存在,使用默认图标:" << finalIconPath; + } else { + qDebug() << "使用图标文件:" << finalIconPath; + } + + // 额外检查资源文件是否存在 + if (finalIconPath.startsWith(":/") && QIcon(finalIconPath).isNull()) { + qDebug() << "资源图标无法加载,使用备用默认图标"; + finalIconPath = ":/resources/default_icon.svg"; } // 如果是忽略状态,绘制灰色图标 diff --git a/src/aptssupdater.cpp b/src/aptssupdater.cpp index 44b31105..3a5b5bbe 100644 --- a/src/aptssupdater.cpp +++ b/src/aptssupdater.cpp @@ -248,6 +248,7 @@ QStringList aptssUpdater::getPackageIcons() if (!dpkgProcess.waitForFinished(30000)) { // 30秒超时 qWarning() << "获取包文件列表失败:" << packageName << "(超时)"; dpkgProcess.kill(); + packageIcons << QString("%1: %2").arg(packageName, iconPath); continue; } QStringList files = QString(dpkgProcess.readAllStandardOutput()).split('\n', Qt::SkipEmptyParts); @@ -278,6 +279,7 @@ QStringList aptssUpdater::getPackageIcons() foreach (const QString &path, iconPaths) { if (QFile::exists(path)) { iconPath = path; + qDebug() << "找到图标文件:" << path; break; } } @@ -285,6 +287,7 @@ QStringList aptssUpdater::getPackageIcons() // 已经是绝对路径 if (QFile::exists(iconName)) { iconPath = iconName; + qDebug() << "使用绝对路径图标文件:" << iconName; } } break; @@ -296,9 +299,13 @@ QStringList aptssUpdater::getPackageIcons() // 如果.desktop中没有找到图标,尝试直接查找包中的图标文件 if (iconPath == ":/resources/default_icon.svg") { + qDebug() << "未在.desktop文件中找到图标,尝试直接查找包中的图标文件"; QStringList iconFiles = files.filter(QRegularExpression("/(usr/share/pixmaps|usr/share/icons|opt/apps/.*/entries/icons)/.*\\.(png|svg)$")); if (!iconFiles.isEmpty()) { iconPath = iconFiles.first(); + qDebug() << "从包中找到图标文件:" << iconPath; + } else { + qDebug() << "未在包中找到图标文件,使用默认图标"; } } -- Gitee From 8004cea8be01fa63545e5952ab80eca25304432c Mon Sep 17 00:00:00 2001 From: momen Date: Fri, 17 Oct 2025 12:25:11 +0000 Subject: [PATCH 083/105] update debian/changelog. Signed-off-by: momen --- debian/changelog | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/debian/changelog b/debian/changelog index 170f5ef4..01eb32de 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,9 @@ +spark-update-tool (1.0.3) unstable; urgency=low + + * 修复默认图标加载失败的问题 + * 修复更新器在安装阶段强制关闭窗口后再次更新无法安装软件包的问题。 + + -- momen Fri, 17 Oct 2025 00:00:00 +0000 spark-update-tool (1.0.2) unstable; urgency=low * 添加复选框,选择多个包更新 -- Gitee From 1b722e78a5d81ed17ca48ddda4c8f914d9c0ef16 Mon Sep 17 00:00:00 2001 From: momen Date: Mon, 10 Nov 2025 10:49:56 +0800 Subject: [PATCH 084/105] =?UTF-8?q?update:=E6=B7=BB=E5=8A=A0png=E9=BB=98?= =?UTF-8?q?=E8=AE=A4=E5=9B=BE=E7=89=87?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- resources/default_icon.png | Bin 0 -> 100127 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 resources/default_icon.png diff --git a/resources/default_icon.png b/resources/default_icon.png new file mode 100644 index 0000000000000000000000000000000000000000..bffa3792fe5a1fa3ac39f465d2e3ca18732ede1d GIT binary patch literal 100127 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 literal 0 HcmV?d00001 -- Gitee From c3cd29bb66fefba0a59832a18a3878f8d3f32fc9 Mon Sep 17 00:00:00 2001 From: momen Date: Mon, 10 Nov 2025 10:55:44 +0800 Subject: [PATCH 085/105] =?UTF-8?q?update:=E4=BF=AE=E5=A4=8D=E8=B0=83?= =?UTF-8?q?=E7=94=A8=E9=BB=98=E8=AE=A4svg=E5=87=BA=E9=94=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/appdelegate.cpp | 4 ++-- src/aptssupdater.cpp | 4 ++-- src/icons.qrc | 1 + 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/src/appdelegate.cpp b/src/appdelegate.cpp index 83649e83..d4b70f0f 100644 --- a/src/appdelegate.cpp +++ b/src/appdelegate.cpp @@ -94,7 +94,7 @@ void AppDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, c QString finalIconPath = iconPath; qDebug() << "原始图标路径:" << iconPath; if (iconPath.isEmpty() || !QFile::exists(iconPath)) { - finalIconPath = ":/resources/default_icon.svg"; + finalIconPath = ":/resources/default_icon.png"; qDebug() << "图标文件不存在,使用默认图标:" << finalIconPath; } else { qDebug() << "使用图标文件:" << finalIconPath; @@ -103,7 +103,7 @@ void AppDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, c // 额外检查资源文件是否存在 if (finalIconPath.startsWith(":/") && QIcon(finalIconPath).isNull()) { qDebug() << "资源图标无法加载,使用备用默认图标"; - finalIconPath = ":/resources/default_icon.svg"; + finalIconPath = ":/resources/default_icon.png"; } // 如果是忽略状态,绘制灰色图标 diff --git a/src/aptssupdater.cpp b/src/aptssupdater.cpp index 3a5b5bbe..8dcde539 100644 --- a/src/aptssupdater.cpp +++ b/src/aptssupdater.cpp @@ -241,7 +241,7 @@ QStringList aptssUpdater::getPackageIcons() QProcess dpkgProcess; // 在循环内部创建新的QProcess实例 QString packageName = package.split(":")[0]; - QString iconPath = ":/resources/default_icon.svg"; // 默认图标 + QString iconPath = ":/resources/default_icon.png"; // 默认图标 // 获取包文件列表 dpkgProcess.start("dpkg", QStringList() << "-L" << packageName); @@ -298,7 +298,7 @@ QStringList aptssUpdater::getPackageIcons() } // 如果.desktop中没有找到图标,尝试直接查找包中的图标文件 - if (iconPath == ":/resources/default_icon.svg") { + if (iconPath == ":/resources/default_icon.png") { qDebug() << "未在.desktop文件中找到图标,尝试直接查找包中的图标文件"; QStringList iconFiles = files.filter(QRegularExpression("/(usr/share/pixmaps|usr/share/icons|opt/apps/.*/entries/icons)/.*\\.(png|svg)$")); if (!iconFiles.isEmpty()) { diff --git a/src/icons.qrc b/src/icons.qrc index f81e1f88..9bbc9d3c 100644 --- a/src/icons.qrc +++ b/src/icons.qrc @@ -4,5 +4,6 @@ ../resources/default_icon.svg ../resources/spark-update-tool.svg ../resources/128*128/spark-update-tool.png + ../resources/default_icon.png -- Gitee From 4f73289602742a7d0ed7a54f50dfef9d538dccb5 Mon Sep 17 00:00:00 2001 From: momen Date: Mon, 10 Nov 2025 11:03:12 +0800 Subject: [PATCH 086/105] =?UTF-8?q?update:=E6=9B=B4=E6=AD=A3=E4=B9=8B?= =?UTF-8?q?=E5=89=8D=E6=96=B0=E5=A2=9E=E7=9A=84=E5=8A=A0=E8=BD=BD=E9=BB=98?= =?UTF-8?q?=E8=AE=A4=E5=9B=BE=E6=A0=87=E4=BB=A3=E7=A0=81=EF=BC=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/appdelegate.cpp | 19 ++----------------- 1 file changed, 2 insertions(+), 17 deletions(-) diff --git a/src/appdelegate.cpp b/src/appdelegate.cpp index d4b70f0f..f80ed05a 100644 --- a/src/appdelegate.cpp +++ b/src/appdelegate.cpp @@ -90,26 +90,11 @@ void AppDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, c // 调整图标位置,为复选框留出空间 QRect iconRect(rect.left() + 40, rect.top() + (rect.height() - iconSize) / 2, iconSize, iconSize); - // 检查图标路径是否存在,如果不存在则使用默认图标 - QString finalIconPath = iconPath; - qDebug() << "原始图标路径:" << iconPath; - if (iconPath.isEmpty() || !QFile::exists(iconPath)) { - finalIconPath = ":/resources/default_icon.png"; - qDebug() << "图标文件不存在,使用默认图标:" << finalIconPath; - } else { - qDebug() << "使用图标文件:" << finalIconPath; - } - - // 额外检查资源文件是否存在 - if (finalIconPath.startsWith(":/") && QIcon(finalIconPath).isNull()) { - qDebug() << "资源图标无法加载,使用备用默认图标"; - finalIconPath = ":/resources/default_icon.png"; - } // 如果是忽略状态,绘制灰色图标 if (isIgnored) { // 创建灰度效果 - QPixmap originalPixmap = QIcon(finalIconPath).pixmap(iconSize, iconSize); + QPixmap originalPixmap = QIcon(iconPath).pixmap(iconSize, iconSize); QPixmap grayPixmap(originalPixmap.size()); grayPixmap.fill(Qt::transparent); QPainter grayPainter(&grayPixmap); @@ -118,7 +103,7 @@ void AppDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, c grayPainter.end(); painter->drawPixmap(iconRect, grayPixmap); } else { - QIcon(finalIconPath).paint(painter, iconRect); + QIcon(iconPath).paint(painter, iconRect); } int textX = iconRect.right() + margin; -- Gitee From 6afabe9eb6dfa2cfe1638191c7f74b64e1801ff9 Mon Sep 17 00:00:00 2001 From: momen Date: Sat, 30 Aug 2025 08:39:51 +0000 Subject: [PATCH 087/105] =?UTF-8?q?!356=20fix:=E4=BF=AE=E5=A4=8D=E4=BA=86?= =?UTF-8?q?=E6=9B=B4=E6=96=B0=E5=99=A8=E5=AE=89=E8=A3=85=E5=AE=8C=E6=88=90?= =?UTF-8?q?=E5=90=8E=E6=98=BE=E7=A4=BA=E4=B8=8B=E8=BD=BD=E5=AE=8C=E6=88=90?= =?UTF-8?q?=E7=9A=84bug=20Merge=20pull=20request=20!356=20from=20momen/Thu?= =?UTF-8?q?nder?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main.cpp b/src/main.cpp index fe3bc334..3e4e9774 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -214,4 +214,4 @@ int main(int argc, char *argv[]) }); return a.exec(); -} \ No newline at end of file +} -- Gitee From bda5b7ca7ae747680717a5cfd2e2a5207c256283 Mon Sep 17 00:00:00 2001 From: shenmo Date: Fri, 5 Sep 2025 13:48:52 +0000 Subject: [PATCH 088/105] =?UTF-8?q?aptss=E6=94=AF=E6=8C=81=E5=9C=A8?= =?UTF-8?q?=E5=AE=89=E8=A3=85=E8=BD=AF=E4=BB=B6=E7=9A=84=E5=90=8C=E6=97=B6?= =?UTF-8?q?=E4=BD=BF=E7=94=A8download=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- tool/apt-fast/ss-apt-fast | 60 +++++++++++++++++++-------------------- 1 file changed, 30 insertions(+), 30 deletions(-) diff --git a/tool/apt-fast/ss-apt-fast b/tool/apt-fast/ss-apt-fast index 2832d5bd..f1a07464 100755 --- a/tool/apt-fast/ss-apt-fast +++ b/tool/apt-fast/ss-apt-fast @@ -55,36 +55,6 @@ msg_already_running() # exit 1 #fi -# Move download file away so missing permissions won't stop usage. -CLEANUP_STATE=0 -cleanup_dllist() -{ - if [ -f "$DLLIST" ] - then - if ! mv -- "$DLLIST{,.old}" 2>/dev/null - then - if ! rm -fr -- "${LISTTEMP}" 2>/dev/null - then - msg "Could not clean up download list file." "warning" - msg "无法清除下载列表文件." "warning" - CLEANUP_STATE=1 - fi - fi - fi -} - -cleanup_aptfast() -{ - local last_exit_code=$? - [ "$CLEANUP_STATE" -eq 0 ] && CLEANUP_STATE=$last_exit_code - cleanup_dllist - _remove_lock -} - -exit_cleanup_state() -{ - exit $CLEANUP_STATE -} LCK_FD=99 # create the lock file and lock it, die on failure _create_lock() @@ -319,6 +289,36 @@ fi +# Move download file away so missing permissions won't stop usage. +CLEANUP_STATE=0 +cleanup_dllist() +{ + if [ -f "$DLLIST" ] + then + if ! mv -- "$DLLIST{,.old}" 2>/dev/null + then + if ! rm -fr -- "${LISTTEMP}" 2>/dev/null + then + msg "Could not clean up download list file." "warning" + msg "无法清除下载列表文件." "warning" + CLEANUP_STATE=1 + fi + fi + fi +} + +cleanup_aptfast() +{ + local last_exit_code=$? + [ "$CLEANUP_STATE" -eq 0 ] && CLEANUP_STATE=$last_exit_code + cleanup_dllist + _remove_lock +} + +exit_cleanup_state() +{ + exit $CLEANUP_STATE +} # decode url string # translates %xx but must not convert '+' in spaces -- Gitee From 7175bf4e4d02770680f73a502e5662d5a88b6878 Mon Sep 17 00:00:00 2001 From: shenmo Date: Sat, 6 Sep 2025 14:57:24 +0000 Subject: [PATCH 089/105] =?UTF-8?q?aptss=E9=97=AE=E9=A2=98=E4=BF=AE?= =?UTF-8?q?=E5=A4=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: shenmo --- tool/apt-fast/ss-apt-fast | 60 +++++++++++++++++++-------------------- 1 file changed, 30 insertions(+), 30 deletions(-) diff --git a/tool/apt-fast/ss-apt-fast b/tool/apt-fast/ss-apt-fast index f1a07464..2832d5bd 100755 --- a/tool/apt-fast/ss-apt-fast +++ b/tool/apt-fast/ss-apt-fast @@ -55,6 +55,36 @@ msg_already_running() # exit 1 #fi +# Move download file away so missing permissions won't stop usage. +CLEANUP_STATE=0 +cleanup_dllist() +{ + if [ -f "$DLLIST" ] + then + if ! mv -- "$DLLIST{,.old}" 2>/dev/null + then + if ! rm -fr -- "${LISTTEMP}" 2>/dev/null + then + msg "Could not clean up download list file." "warning" + msg "无法清除下载列表文件." "warning" + CLEANUP_STATE=1 + fi + fi + fi +} + +cleanup_aptfast() +{ + local last_exit_code=$? + [ "$CLEANUP_STATE" -eq 0 ] && CLEANUP_STATE=$last_exit_code + cleanup_dllist + _remove_lock +} + +exit_cleanup_state() +{ + exit $CLEANUP_STATE +} LCK_FD=99 # create the lock file and lock it, die on failure _create_lock() @@ -289,36 +319,6 @@ fi -# Move download file away so missing permissions won't stop usage. -CLEANUP_STATE=0 -cleanup_dllist() -{ - if [ -f "$DLLIST" ] - then - if ! mv -- "$DLLIST{,.old}" 2>/dev/null - then - if ! rm -fr -- "${LISTTEMP}" 2>/dev/null - then - msg "Could not clean up download list file." "warning" - msg "无法清除下载列表文件." "warning" - CLEANUP_STATE=1 - fi - fi - fi -} - -cleanup_aptfast() -{ - local last_exit_code=$? - [ "$CLEANUP_STATE" -eq 0 ] && CLEANUP_STATE=$last_exit_code - cleanup_dllist - _remove_lock -} - -exit_cleanup_state() -{ - exit $CLEANUP_STATE -} # decode url string # translates %xx but must not convert '+' in spaces -- Gitee From 2b06f84583747731198171ac6a2a221a11ca5380 Mon Sep 17 00:00:00 2001 From: MeowVing Date: Sat, 13 Sep 2025 08:39:56 +0000 Subject: [PATCH 090/105] =?UTF-8?q?!362=20=E4=BC=98=E5=8C=96=E5=9B=BE?= =?UTF-8?q?=E6=A0=87=E8=AE=BE=E8=AE=A1=E4=B8=8E=E5=B0=BA=E5=AF=B8=20*=20?= =?UTF-8?q?=E4=BC=98=E5=8C=96=E5=9B=BE=E6=A0=87=E8=AE=BE=E8=AE=A1=E4=B8=8E?= =?UTF-8?q?=E5=B0=BA=E5=AF=B8=20*=20=E5=88=A0=E9=99=A4=E6=96=87=E4=BB=B6?= =?UTF-8?q?=20pkg/usr/share/icons/hicolor/scalable/apps/spark-store.svg=20?= =?UTF-8?q?*=20=E4=BC=98=E5=8C=96=E5=9B=BE=E6=A0=87=E8=AE=BE=E8=AE=A1?= =?UTF-8?q?=E4=B8=8E=E5=B0=BA=E5=AF=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../hicolor/scalable/apps/spark-store.svg | 2 +- .../scalable/apps/spark-store_128px.svg | 302 ++++++++++++++++++ .../scalable/apps/spark-store_16px.svg | 302 ++++++++++++++++++ .../scalable/apps/spark-store_256px.svg | 302 ++++++++++++++++++ .../scalable/apps/spark-store_32px.svg | 302 ++++++++++++++++++ .../scalable/apps/spark-store_512px.svg | 302 ++++++++++++++++++ .../scalable/apps/spark-store_64px.svg | 302 ++++++++++++++++++ 7 files changed, 1813 insertions(+), 1 deletion(-) create mode 100644 pkg/usr/share/icons/hicolor/scalable/apps/spark-store_128px.svg create mode 100644 pkg/usr/share/icons/hicolor/scalable/apps/spark-store_16px.svg create mode 100644 pkg/usr/share/icons/hicolor/scalable/apps/spark-store_256px.svg create mode 100644 pkg/usr/share/icons/hicolor/scalable/apps/spark-store_32px.svg create mode 100644 pkg/usr/share/icons/hicolor/scalable/apps/spark-store_512px.svg create mode 100644 pkg/usr/share/icons/hicolor/scalable/apps/spark-store_64px.svg diff --git a/pkg/usr/share/icons/hicolor/scalable/apps/spark-store.svg b/pkg/usr/share/icons/hicolor/scalable/apps/spark-store.svg index a84891b7..087543ac 100644 --- a/pkg/usr/share/icons/hicolor/scalable/apps/spark-store.svg +++ b/pkg/usr/share/icons/hicolor/scalable/apps/spark-store.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/pkg/usr/share/icons/hicolor/scalable/apps/spark-store_128px.svg b/pkg/usr/share/icons/hicolor/scalable/apps/spark-store_128px.svg new file mode 100644 index 00000000..4e76e857 --- /dev/null +++ b/pkg/usr/share/icons/hicolor/scalable/apps/spark-store_128px.svg @@ -0,0 +1,302 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/pkg/usr/share/icons/hicolor/scalable/apps/spark-store_16px.svg b/pkg/usr/share/icons/hicolor/scalable/apps/spark-store_16px.svg new file mode 100644 index 00000000..1fb38831 --- /dev/null +++ b/pkg/usr/share/icons/hicolor/scalable/apps/spark-store_16px.svg @@ -0,0 +1,302 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/pkg/usr/share/icons/hicolor/scalable/apps/spark-store_256px.svg b/pkg/usr/share/icons/hicolor/scalable/apps/spark-store_256px.svg new file mode 100644 index 00000000..12e81075 --- /dev/null +++ b/pkg/usr/share/icons/hicolor/scalable/apps/spark-store_256px.svg @@ -0,0 +1,302 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/pkg/usr/share/icons/hicolor/scalable/apps/spark-store_32px.svg b/pkg/usr/share/icons/hicolor/scalable/apps/spark-store_32px.svg new file mode 100644 index 00000000..6d092a7b --- /dev/null +++ b/pkg/usr/share/icons/hicolor/scalable/apps/spark-store_32px.svg @@ -0,0 +1,302 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/pkg/usr/share/icons/hicolor/scalable/apps/spark-store_512px.svg b/pkg/usr/share/icons/hicolor/scalable/apps/spark-store_512px.svg new file mode 100644 index 00000000..726a1f9f --- /dev/null +++ b/pkg/usr/share/icons/hicolor/scalable/apps/spark-store_512px.svg @@ -0,0 +1,302 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/pkg/usr/share/icons/hicolor/scalable/apps/spark-store_64px.svg b/pkg/usr/share/icons/hicolor/scalable/apps/spark-store_64px.svg new file mode 100644 index 00000000..e5b21d02 --- /dev/null +++ b/pkg/usr/share/icons/hicolor/scalable/apps/spark-store_64px.svg @@ -0,0 +1,302 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + -- Gitee From c2764636e435d090472abb315e401ba9168c8ebe Mon Sep 17 00:00:00 2001 From: shenmo Date: Wed, 17 Sep 2025 12:48:23 +0000 Subject: [PATCH 091/105] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=EF=BC=9A=E4=BD=BF?= =?UTF-8?q?=E7=94=A8aptss=E5=90=8E=E5=9C=A8/tmp=E4=B8=8B=E7=95=99=E4=B8=8B?= =?UTF-8?q?=E5=9E=83=E5=9C=BE=E7=9A=84=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- tool/apt-fast/ss-apt-fast | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/tool/apt-fast/ss-apt-fast b/tool/apt-fast/ss-apt-fast index 2832d5bd..57e10fa8 100755 --- a/tool/apt-fast/ss-apt-fast +++ b/tool/apt-fast/ss-apt-fast @@ -79,12 +79,17 @@ cleanup_aptfast() [ "$CLEANUP_STATE" -eq 0 ] && CLEANUP_STATE=$last_exit_code cleanup_dllist _remove_lock + # 添加删除临时目录的逻辑 + if [ -n "$LISTTEMP" ] && [ -d "$LISTTEMP" ]; then + rm -rf "$LISTTEMP" + fi } - exit_cleanup_state() { + cleanup_aptfast exit $CLEANUP_STATE } + LCK_FD=99 # create the lock file and lock it, die on failure _create_lock() -- Gitee From 318cc780e11641ebd27db70fff22b4957ab569a2 Mon Sep 17 00:00:00 2001 From: shenmo Date: Wed, 17 Sep 2025 14:49:29 +0000 Subject: [PATCH 092/105] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=EF=BC=9A=E9=83=A8?= =?UTF-8?q?=E5=88=86=E6=83=85=E5=86=B5=E4=B8=8B=E6=97=A0=E6=B3=95=E6=AD=A3?= =?UTF-8?q?=E7=A1=AE=E9=85=8D=E7=BD=AEaptss=E7=9A=84=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- tool/ssaudit | 1 + tool/ssinstall | 1 + 2 files changed, 2 insertions(+) diff --git a/tool/ssaudit b/tool/ssaudit index 2afffe64..ad5610ee 100755 --- a/tool/ssaudit +++ b/tool/ssaudit @@ -178,6 +178,7 @@ function hash_check() { # 确保aptss存在 function ensure_aptss_exist() { if ! command -v aptss &>/dev/null; then + apt update local deb_file="/tmp/spark-store-console-in-container_latest_all.deb" if ! wget -O "$deb_file" "https://amber-ce-resource.spark-app.store/store/depends/spark-store-console-in-container_latest_all.deb"; then diff --git a/tool/ssinstall b/tool/ssinstall index e7be0059..a1e44b6b 100755 --- a/tool/ssinstall +++ b/tool/ssinstall @@ -178,6 +178,7 @@ function hash_check() { # 确保aptss存在 function ensure_aptss_exist() { if ! command -v aptss &>/dev/null; then + apt update local deb_file="/tmp/spark-store-console-in-container_latest_all.deb" if ! wget -O "$deb_file" "https://amber-ce-resource.spark-app.store/store/depends/spark-store-console-in-container_latest_all.deb"; then -- Gitee From 5b21b49e745b6d690daed6065f1718df6a78350c Mon Sep 17 00:00:00 2001 From: shenmo Date: Sat, 20 Sep 2025 03:57:23 +0000 Subject: [PATCH 093/105] =?UTF-8?q?=E5=AE=89=E8=A3=85=E5=90=8E=E5=88=A0?= =?UTF-8?q?=E9=99=A4=E8=BD=AF=E4=BB=B6=E5=8C=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- spark-update-tool/src/appdelegate.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spark-update-tool/src/appdelegate.cpp b/spark-update-tool/src/appdelegate.cpp index 0c930657..3ec12fed 100644 --- a/spark-update-tool/src/appdelegate.cpp +++ b/spark-update-tool/src/appdelegate.cpp @@ -317,6 +317,6 @@ void AppDelegate::startNextInstall() { // 注意参数顺序:deb路径在前,--no-create-desktop-entry在后 QStringList args; - args << debPath << "--no-create-desktop-entry"; + args << debPath << "--no-create-desktop-entry" << "--delete-after-install"; m_installProcess->start("ssinstall", args); } -- Gitee From 9ad6620681eeab2cd309ff67cc4d5fce7d7bc7ef Mon Sep 17 00:00:00 2001 From: MeowVing Date: Tue, 23 Sep 2025 12:31:46 +0000 Subject: [PATCH 094/105] =?UTF-8?q?!364=20=E5=B0=9D=E8=AF=95=E4=BF=AE?= =?UTF-8?q?=E5=A4=8D=E5=9B=BE=E6=A0=87=E8=BE=B9=E7=BC=98=E8=A2=AB=E8=A3=81?= =?UTF-8?q?=E5=88=87=E9=97=AE=E9=A2=98=20*=20=E5=B0=9D=E8=AF=95=E4=BF=AE?= =?UTF-8?q?=E5=A4=8D=E5=9B=BE=E6=A0=87=E8=BE=B9=E7=BC=98=E8=A2=AB=E8=A3=81?= =?UTF-8?q?=E5=88=87=E9=97=AE=E9=A2=98=20*=20=E5=88=A0=E9=99=A4=E6=96=87?= =?UTF-8?q?=E4=BB=B6=20pkg/usr/share/icons/hicolor/scalable/apps/spark-sto?= =?UTF-8?q?re.svg=20*=20=E5=B0=9D=E8=AF=95=E4=BF=AE=E5=A4=8D=E5=9B=BE?= =?UTF-8?q?=E6=A0=87=E8=BE=B9=E7=BC=98=E8=A2=AB=E8=A3=81=E5=88=87=E9=97=AE?= =?UTF-8?q?=E9=A2=98=20*=20=E5=88=A0=E9=99=A4=E6=96=87=E4=BB=B6=20pkg/usr/?= =?UTF-8?q?share/icons/hicolor/scalable/apps/spark-store=5F64px.svg=20*=20?= =?UTF-8?q?=E5=88=A0=E9=99=A4=E6=96=87=E4=BB=B6=20pkg/usr/share/icons/hico?= =?UTF-8?q?lor/scalable/apps/spark-store=5F512px.svg=20*=20=E5=88=A0?= =?UTF-8?q?=E9=99=A4=E6=96=87=E4=BB=B6=20pkg/usr/share/icons/hicolor/scala?= =?UTF-8?q?ble/apps/spark-store=5F32px.svg=20*=20=E5=88=A0=E9=99=A4?= =?UTF-8?q?=E6=96=87=E4=BB=B6=20pkg/usr/share/icons/hicolor/scalable/apps/?= =?UTF-8?q?spark-store=5F256px.svg=20*=20=E5=88=A0=E9=99=A4=E6=96=87?= =?UTF-8?q?=E4=BB=B6=20pkg/usr/share/icons/hicolor/scalable/apps/spark-sto?= =?UTF-8?q?re=5F16px.svg=20*=20=E5=88=A0=E9=99=A4=E6=96=87=E4=BB=B6=20pkg/?= =?UTF-8?q?usr/share/icons/hicolor/scalable/apps/spark-store=5F128px.svg?= =?UTF-8?q?=20*=20=E6=9B=B4=E6=96=B0=E5=9B=BE=E6=A0=87=20*=20=E5=88=A0?= =?UTF-8?q?=E9=99=A4=E6=96=87=E4=BB=B6=20src/assets/icon/spark-store.svg?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../hicolor/scalable/apps/spark-store.svg | 2 +- .../scalable/apps/spark-store_128px.svg | 100 ++++++++++-------- .../scalable/apps/spark-store_16px.svg | 100 ++++++++++-------- .../scalable/apps/spark-store_256px.svg | 100 ++++++++++-------- .../scalable/apps/spark-store_32px.svg | 100 ++++++++++-------- .../scalable/apps/spark-store_512px.svg | 100 ++++++++++-------- .../scalable/apps/spark-store_64px.svg | 100 ++++++++++-------- src/assets/icon/spark-store.svg | 2 +- 8 files changed, 332 insertions(+), 272 deletions(-) diff --git a/pkg/usr/share/icons/hicolor/scalable/apps/spark-store.svg b/pkg/usr/share/icons/hicolor/scalable/apps/spark-store.svg index 087543ac..a1f93964 100644 --- a/pkg/usr/share/icons/hicolor/scalable/apps/spark-store.svg +++ b/pkg/usr/share/icons/hicolor/scalable/apps/spark-store.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/pkg/usr/share/icons/hicolor/scalable/apps/spark-store_128px.svg b/pkg/usr/share/icons/hicolor/scalable/apps/spark-store_128px.svg index 4e76e857..2607b311 100644 --- a/pkg/usr/share/icons/hicolor/scalable/apps/spark-store_128px.svg +++ b/pkg/usr/share/icons/hicolor/scalable/apps/spark-store_128px.svg @@ -2,12 +2,15 @@ - + - + - + + + + @@ -62,16 +65,19 @@ - - + + + + + - + - + @@ -83,16 +89,16 @@ - + - + - - + + @@ -104,7 +110,7 @@ - + @@ -116,7 +122,7 @@ - + @@ -164,7 +170,7 @@ - + @@ -180,7 +186,7 @@ - + @@ -200,7 +206,7 @@ - + @@ -208,7 +214,7 @@ - + @@ -224,7 +230,7 @@ - + @@ -232,71 +238,75 @@ - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + + - - - - - - - - - + + + + + + + + + + + + diff --git a/pkg/usr/share/icons/hicolor/scalable/apps/spark-store_16px.svg b/pkg/usr/share/icons/hicolor/scalable/apps/spark-store_16px.svg index 1fb38831..3cc08a08 100644 --- a/pkg/usr/share/icons/hicolor/scalable/apps/spark-store_16px.svg +++ b/pkg/usr/share/icons/hicolor/scalable/apps/spark-store_16px.svg @@ -2,12 +2,15 @@ - + - + - + + + + @@ -62,16 +65,19 @@ - - + + + + + - + - + @@ -83,16 +89,16 @@ - + - + - - + + @@ -104,7 +110,7 @@ - + @@ -116,7 +122,7 @@ - + @@ -164,7 +170,7 @@ - + @@ -180,7 +186,7 @@ - + @@ -200,7 +206,7 @@ - + @@ -208,7 +214,7 @@ - + @@ -224,7 +230,7 @@ - + @@ -232,71 +238,75 @@ - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + + - - - - - - - - - + + + + + + + + + + + + diff --git a/pkg/usr/share/icons/hicolor/scalable/apps/spark-store_256px.svg b/pkg/usr/share/icons/hicolor/scalable/apps/spark-store_256px.svg index 12e81075..2b5178bb 100644 --- a/pkg/usr/share/icons/hicolor/scalable/apps/spark-store_256px.svg +++ b/pkg/usr/share/icons/hicolor/scalable/apps/spark-store_256px.svg @@ -2,12 +2,15 @@ - + - + - + + + + @@ -62,16 +65,19 @@ - - + + + + + - + - + @@ -83,16 +89,16 @@ - + - + - - + + @@ -104,7 +110,7 @@ - + @@ -116,7 +122,7 @@ - + @@ -164,7 +170,7 @@ - + @@ -180,7 +186,7 @@ - + @@ -200,7 +206,7 @@ - + @@ -208,7 +214,7 @@ - + @@ -224,7 +230,7 @@ - + @@ -232,71 +238,75 @@ - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + + - - - - - - - - - + + + + + + + + + + + + diff --git a/pkg/usr/share/icons/hicolor/scalable/apps/spark-store_32px.svg b/pkg/usr/share/icons/hicolor/scalable/apps/spark-store_32px.svg index 6d092a7b..87bfa668 100644 --- a/pkg/usr/share/icons/hicolor/scalable/apps/spark-store_32px.svg +++ b/pkg/usr/share/icons/hicolor/scalable/apps/spark-store_32px.svg @@ -2,12 +2,15 @@ - + - + - + + + + @@ -62,16 +65,19 @@ - - + + + + + - + - + @@ -83,16 +89,16 @@ - + - + - - + + @@ -104,7 +110,7 @@ - + @@ -116,7 +122,7 @@ - + @@ -164,7 +170,7 @@ - + @@ -180,7 +186,7 @@ - + @@ -200,7 +206,7 @@ - + @@ -208,7 +214,7 @@ - + @@ -224,7 +230,7 @@ - + @@ -232,71 +238,75 @@ - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + + - - - - - - - - - + + + + + + + + + + + + diff --git a/pkg/usr/share/icons/hicolor/scalable/apps/spark-store_512px.svg b/pkg/usr/share/icons/hicolor/scalable/apps/spark-store_512px.svg index 726a1f9f..35f5e2ab 100644 --- a/pkg/usr/share/icons/hicolor/scalable/apps/spark-store_512px.svg +++ b/pkg/usr/share/icons/hicolor/scalable/apps/spark-store_512px.svg @@ -2,12 +2,15 @@ - + - + - + + + + @@ -62,16 +65,19 @@ - - + + + + + - + - + @@ -83,16 +89,16 @@ - + - + - - + + @@ -104,7 +110,7 @@ - + @@ -116,7 +122,7 @@ - + @@ -164,7 +170,7 @@ - + @@ -180,7 +186,7 @@ - + @@ -200,7 +206,7 @@ - + @@ -208,7 +214,7 @@ - + @@ -224,7 +230,7 @@ - + @@ -232,71 +238,75 @@ - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + + - - - - - - - - - + + + + + + + + + + + + diff --git a/pkg/usr/share/icons/hicolor/scalable/apps/spark-store_64px.svg b/pkg/usr/share/icons/hicolor/scalable/apps/spark-store_64px.svg index e5b21d02..d064c5bb 100644 --- a/pkg/usr/share/icons/hicolor/scalable/apps/spark-store_64px.svg +++ b/pkg/usr/share/icons/hicolor/scalable/apps/spark-store_64px.svg @@ -2,12 +2,15 @@ - + - + - + + + + @@ -62,16 +65,19 @@ - - + + + + + - + - + @@ -83,16 +89,16 @@ - + - + - - + + @@ -104,7 +110,7 @@ - + @@ -116,7 +122,7 @@ - + @@ -164,7 +170,7 @@ - + @@ -180,7 +186,7 @@ - + @@ -200,7 +206,7 @@ - + @@ -208,7 +214,7 @@ - + @@ -224,7 +230,7 @@ - + @@ -232,71 +238,75 @@ - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + + - - - - - - - - - + + + + + + + + + + + + diff --git a/src/assets/icon/spark-store.svg b/src/assets/icon/spark-store.svg index a84891b7..a1f93964 100644 --- a/src/assets/icon/spark-store.svg +++ b/src/assets/icon/spark-store.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file -- Gitee From fc91419895e668a7ef00db5deb8e6c10f0c6bcb3 Mon Sep 17 00:00:00 2001 From: MeowVing Date: Wed, 24 Sep 2025 13:04:18 +0000 Subject: [PATCH 095/105] =?UTF-8?q?!367=20=E6=9B=B4=E6=96=B0=E8=BD=AF?= =?UTF-8?q?=E4=BB=B6=E4=B8=BB=E5=9B=BE=E6=A0=87=20*=20=E5=88=A0=E9=99=A4?= =?UTF-8?q?=E6=96=87=E4=BB=B6=20pkg/usr/share/icons/hicolor/scalable/apps/?= =?UTF-8?q?spark-store=5F64px.svg=20*=20=E5=88=A0=E9=99=A4=E6=96=87?= =?UTF-8?q?=E4=BB=B6=20pkg/usr/share/icons/hicolor/scalable/apps/spark-sto?= =?UTF-8?q?re=5F512px.svg=20*=20=E5=88=A0=E9=99=A4=E6=96=87=E4=BB=B6=20pkg?= =?UTF-8?q?/usr/share/icons/hicolor/scalable/apps/spark-store=5F32px.svg?= =?UTF-8?q?=20*=20=E5=88=A0=E9=99=A4=E6=96=87=E4=BB=B6=20pkg/usr/share/ico?= =?UTF-8?q?ns/hicolor/scalable/apps/spark-store=5F256px.svg=20*=20?= =?UTF-8?q?=E5=88=A0=E9=99=A4=E6=96=87=E4=BB=B6=20pkg/usr/share/icons/hico?= =?UTF-8?q?lor/scalable/apps/spark-store=5F16px.svg=20*=20=E5=88=A0?= =?UTF-8?q?=E9=99=A4=E6=96=87=E4=BB=B6=20pkg/usr/share/icons/hicolor/scala?= =?UTF-8?q?ble/apps/spark-store=5F128px.svg=20*=20=E5=88=A0=E9=99=A4?= =?UTF-8?q?=E6=96=87=E4=BB=B6=20pkg/usr/share/icons/hicolor/scalable/apps/?= =?UTF-8?q?spark-store.svg=20*=20=E6=9B=B4=E6=96=B0=E8=BD=AF=E4=BB=B6?= =?UTF-8?q?=E4=B8=BB=E5=9B=BE=E6=A0=87?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../hicolor/scalable/apps/spark-store.png | Bin 0 -> 390586 bytes .../hicolor/scalable/apps/spark-store.svg | 1 - .../scalable/apps/spark-store_128px.svg | 312 ------------------ .../scalable/apps/spark-store_16px.svg | 312 ------------------ .../scalable/apps/spark-store_256px.svg | 312 ------------------ .../scalable/apps/spark-store_32px.svg | 312 ------------------ .../scalable/apps/spark-store_512px.svg | 312 ------------------ .../scalable/apps/spark-store_64px.svg | 312 ------------------ 8 files changed, 1873 deletions(-) create mode 100644 pkg/usr/share/icons/hicolor/scalable/apps/spark-store.png delete mode 100644 pkg/usr/share/icons/hicolor/scalable/apps/spark-store.svg delete mode 100644 pkg/usr/share/icons/hicolor/scalable/apps/spark-store_128px.svg delete mode 100644 pkg/usr/share/icons/hicolor/scalable/apps/spark-store_16px.svg delete mode 100644 pkg/usr/share/icons/hicolor/scalable/apps/spark-store_256px.svg delete mode 100644 pkg/usr/share/icons/hicolor/scalable/apps/spark-store_32px.svg delete mode 100644 pkg/usr/share/icons/hicolor/scalable/apps/spark-store_512px.svg delete mode 100644 pkg/usr/share/icons/hicolor/scalable/apps/spark-store_64px.svg diff --git a/pkg/usr/share/icons/hicolor/scalable/apps/spark-store.png b/pkg/usr/share/icons/hicolor/scalable/apps/spark-store.png new file mode 100644 index 0000000000000000000000000000000000000000..bc47ff0be4b5ec4d0c5a5907a2a63190d4bd2572 GIT binary patch literal 390586 zcmd43d0Z3c+CS`Cw+b$`sO$n#YX!k7OAM$Wpdi#0TMeiQ24!Roi4qpqqGbmaCzH@R5T{SKMzW%%v$GC6$6AD%sK+-lpy{(I>@UM#(RUd#i&RAafY)L8ET zgKF%)a?|on{&rs82b@9zy|#w9Zlj0z(5)E8wl>pOAGU@!ION6Jt9SSi;u~arm})%s zzSi(>@?leBcv2u^zx5V-hhLupzfq07SuB5RQ&SFyW5QWs;upv?HM6p^GF@(NYHq#^ zp0O+1zrOWa7Ax?; zzTe;7H^^k~*dxK@OH5$Vrh6Gdre-F~$*-lSxBC6_t=BSw$Y0-o$X2g_v0vW*h8!6C zB>%mEL0;RA_N^(XVe}7wEN@<;AcuUv9o~*>bC8=3lNh{U85D ze#Spuu>LS>1H)$dz7=1Z@1^fswwJ!jYuT5}EzFi#TA8g{wrVeZ`3lCWm5f!(_y7Jz z?_ct-Z?nxWnC?w}H5>EapZAZ)#-6*{l)PHVf%l6X`{mbF{{D*hm*D*q|LHP+_@!si zf4}Vh!GXxwEoIP6y%4WMUcM~yqMQAC(HV4W)&Umc^^Z%w7GeGCC5OFajqLShQjHHU zV|eY~8;r1wZPwbY*IT^zkUvGwVK3~BAi9^Y*RKz_AAo-@(=#*sgO&dJ=BrKr>2v?a zI{p7?_mcZ-EQrXR1^)qyT=DB7;Wz8G!7OjTK$}foew-Z#e3`4sr~LLH?C7!k@RzPN zgxv2J`(M7p;l2LTUFL0ZmA7W#-*O$FlkKsqB+OKsCaNMxWeEm1;^@4-E z0;${AI@p^#Y(4Phem}i^fqQ)!)OF+|PUdz24r}#TUWfb<*xc0BrvLLj|8O1emj)3J zv2Xf&hJasw&oN%`3C4ktLCUD^b>qhAjoVT;us^M2!ai5&%RyEcDEtMa-UF?7*1Y>00f zvHxe=Bze)hkK;2hzpQ1N`VI<`ZEZ`d%@l{v?yG*;arE6Chwu@;txkWXX-DtuT3yk{ zeWuuUPr3 zPNjt)EM>-l(rJCU>B>H3X!eW2W#RpcG=3V{UZ~!?wkcA1yVquDaD3~MBjGc0W4Cmw zdz|7fj#MtBD;;fHJ19n;6W<0~%I(5f%EC-}MA*+u27~oV$9GV#Mzmk7j%eq%a_K*} zRw;LvjPLWS4ID|+Fjfp&ED%yQ=5@T?bfNTef*(yG%nDZ$p)G4eOd>~9{bIKCe0Qh! zW|UBM^I>LYD<%4I%$E9&mho@#{B)J#zI0IWvbtKuaj*@tit5AU;|6Il?@Z!bg;if~ zkX#C5tq3i-o*Q{<^vn6*GcW+t44-@?(Fz6!1m?P*G-wD9aqeUSCY zrvzE4D&~ozQ+2(WnKNH~>L!V>(P{o#>tmTskNPWJ#YY?sVWm>%_LSZ@wOHNNEelug z4Do;GKRBFJdEFv&S?*}to+HD$>N_k(M&49Zc=iv=Yu?<~@C+q?Jl4gBf6m;O))4;v z&DMdX2=Tgg51u z=Nr4?#wE)BheBhviCllU#p3ACR(n`(ej_srtAmmk)D3Rth4@WKjqUL(qb7Bwj9giM zZL9py1q05M2P~Hkp+q#1_2SiqjM%PFH@BX%6Dv49`+u-m*uXrMzzcoS>AD)LvN4G6 z=^Rg|^w-X&T9ozDi!ZuOY_}$VYZx>OJG<4XT6#$KQ%)gko15th{tT-#tnh8s!4JX? zADO$aBXC0ZyZDhGmfzUw8~CpG<PiMT zQ>h1St6BEdalfp<((hivxwF)mBvYomA)#$LSxjk-0h0SYKE8ZSOW>olb zRJVK6=;ZV7p6T8aDMzeumBI&6Jr*L}_1Q@8j7klIp{T5T?^ZYDcySk>+DxO2KTcbZ zGHcIzmnP`qW*2E2iw)YXH}aG1(WtL2v7Chs>o3v_@nZqf)BceT>}g#Y`c3zL)^A>4 zOVeuziznL8#t@6Td^hr)tJr4uYG@8K#SqA3;I3&&$>iL$D~*u_emhAwt{%PQ2)P-w@eYDcW0pBMQv)WAb zoAS~>tq9g&2veSQni$}l=IAxu7PIGGq?s3AuVTOK^q56{z%Pa2SCXdlsYXqe456W0 z(6re^2t(*p*qc>sQ8hc_MMq#32poNIJ~lOjBKW z!&`@D8%K9D_%w$?A05kUbVCaJBL?@?t zimAOESf`J#r$w8<^;aW5@c1f+H2;pR0sIJ^wt(W4X_vGJOms59Y}VueZVBkoXk?#$5n;>I2G!qRuUhQ+5!TQZB4f*vo0S*zyS->!1@n?_#p z=p>)vXY#yZ&ge6wgWzD2?lg@{L;k;%gjij(bt~~aG1m}xESQi$G<+duPwvvWCV=f} zQG=Bj>NhQYiCE}2M>2#r1yt>NZ7bZ1L3xE(EW&)AA*H%J!jLaIBT*b#qq+5(K>JC> z**2uIitQ;;^eudeMCf*QT{VGNfOn+U%~*tMzCtu;#GNc!Pasp3KO4)4?YK|DnW+!3 z@Z*VuU`@6azLqcgg2{DQu{Bl@cC>HCagiZY)f<~c9IWLTH@swUb$c}ILQES5cYoCp zA6u&O_V0s2G0^t9ATGIKbg<@alWFC6oA(huFyTl~x$Veo_Ae(&%hg&&si^X%{1&gF z0eiLdL`V66zrCmMd&s*doD^DEY}dXoPqQ`okfJ@A`xz?dIegl>VigO0Sj9G$uqX1V zR9y!5N-y2og0Ha_ZK%ae44P-KQ0FsjU5Uc|n8!r{)v?&(Ef{U7+kn6!dW%4 zhnQrriD!k^%}7Twk6D}ZE$+d>DAt@ytPDco=Xy)rc@cgti<^{A z9N=^z4f^;Q3H$PO=??;`Ma7g(q|%8am#}y7wHGxT*>m?w*d9xRX1MYN(v#kiedYx( z7x0LAaAli`#W{*4d$wgh)oTiFCUVk=j~JBazNTfEiEhJo33~#j!y~Q=sBXnRiG;UF zw7^1gKS0r;qocd*#%itA9>OsreI;Rghgw+8bQg9a4K)>?Y(N{z zFyA%&6Uv3zX+Itnh@AMM1PQxJ>f4Q2SnXm8mzPii(511fOEm1!ZcALuge~!ad_|Uo zjTOcgH67u@VyC1NpSW}PGANHRS585965#-g62qcqvQXx3Vh&UIpe?5jX$UHy1frUW z#Oqy;7!j}9z8-CPTbC8-BmWqZXA;4Rc%by1{p%9f+CEJkaYp2#R;F92Rb|GVT4s0o z+IJh-UwO`}2tIUC`ZKu$a~C8MOYY_9HQNQF>Z&>G$Y_R#A($KVG0(Pqb5z3CETh$7 zCb6;wkzDI*Y1Yk4JCW+>UuJUP1);F7NA(W=C}Hnmn3iKU?ED$+#imT*G|b}&lk#O* zc2;qt(IxIx3EKebNaGm>x12{BeF3b8#F^0h>9<}Hs%DW|%j zj!faBdXrHbLtMjDtoZQ@EJIPg+4fQY{Q#ZEru`p9T@R{!m=^acR zX_U!~L*+WZg=*(mS$ujkqDoQHFA^AgS~I${0;rEyZdjN^=v(8n6Qw_4u8W)eUQ{Zs zS>yU+!TH+P*qhGc5nIBd*PyCEG zh5BtK^%ZA3k?c--Cvj{j1YtS;Om3`qLm=8~$Yr5v);QOQfrEN`qpEJ0+4;9@fJ7PXACtPrRtr%abR1Wy-xOk}Et zI}zgqViOCkp4gPKg-0A+b>(Bo(&XLGZupF;Qmt`w49;_QQhvoFQlayMtTV@5_z1H( zWRGUIA9*8De0?Pl&Ah-+eevXggdLBVKEyI=9-VDRboGXh?}?MJjTyq*0&Pwqoxyd} z!m|a#{zJ37TX(s}>f9`~+KIiJ2Q?;4zU0@9YZ2b_j8Y1lRy7$Neyz5vRAO#G3Hg-4 zwZ0f-5PB}1Xg3?SUSWWHCdLzUYNgp^j{!MUGoI*z#%2Yep`rxQRKDmuY&3tkhbP`$)uRCGirBIc+%VS5hn5R^1ZhK^3*IM-s2Uz8e;XhgqIr??oLih?o={bS)DB{>mmhPABu$Nu+@GJqX3*oq;TcO5g(OMyK5nr(@kBkVr zHpi+A*p|JWH%bc?dv3jZQPBAOdE8Ko=lhI&{S7^`H*?QT<;Vb{@}WE+?;3y!=x!g9 z-)rJYp$3y;Q3CmAEm;GhB|hd2yU7aEIV;d!*t*HJyxznb56(CHM#kRi&OOH?J~E^n z&J8F|oojC_sgDvVAdeizBz?fw96AiuQi zfEU6eR-Gi1?#wQa%}nn8lYWJQu*MF!14C0bI|ri^4Y&&=io7h^{01mKo2nEKDEJSv zZM5s}o9L4nK{ElWxvL@EGVR4p<0C09`DqCRbk6G^M=!%%gV4-1&@`*;2PN!BZ5hVo z(>Qz$0`dIfE*8E4)s1xmG~(vS&Q}-7)ps<+o?jK7Nyx&>lpb^6=c!XV_~Nk;Z8nS0wL zN6tMgXA^4o%>s9ZaKlC?_FN_dYkcN3&X23E*fS~Xb=z@F=W|T07!R(3WS2aP zIAw*8=Sv&O{qnHSd@9)@&SRr^5^+l?J?oua*hHh?2Xfern2mcO;Ea49EBr_zw62?Y z1l3c*HrpI2+{IMsKPMa8Egm1sr9ZIu2ORRfmH$Q==0|y-p(p!fy;c@5_4igJTcgRJ6nWG7_$7B;6C?#00d z7Mdkfd``9=wBA4lcXB#W6eVF(n3UzkyD0dkX5wyV4&0xLU}K45VFJP60Kow}W2}C= zq0W3LQ}*NvHn~<~uC~Pj-t&J~Xw%vd&IUB{+!;EWc%nF`LG&(3rqCXXuqUJlB1~w_oRVi}q&)y^2<2ufZM?U2aJ&iIVf7{u(`evm;cYe~)1AHp(7jHXE}6(oZnPnHOTCdp7w)4iugf46l0Px8f_^I#}*c zlj0YXfm*7C_4A0($g%tj1$sp|V)}qwXZLeN*Cj*`w~FLKN4!qC9-Sgb8j4t~%;Ku@ zqL<8JN6l8NmL^qPn0(#){c3gi2Dc--@t!g#k4PilU6rLE8gsRzx&B$!7CAn~wk6&1 z#FMGHc6>XA@VGZz2FQ}rFH#{-cK>7&mB&Yi{9U2o5z)k66JM7**_T#m}!ie@kO;`NLsI1WQiBO z0i3Ru2%I6s4V_^Rjp;+N;zBy{WWYCYVGbKUEGwoaumHf`zs0V5SkS7^Xcx|93ZGZC zbJsGULE(i$n+DA^)Zy1ia!hy1b%4g3PP6Y~(CBM8pmpg4i^JXU@33nFj%C<#$@s=C zae;DvRaE!KK_O?$(`eR&ZPVebf}+v75@pu=2I`YIqk@rX_;8cXu86%~UMw9K{kqF) z5ndNSYdUgq_;aAM&#+5`i#`y+LNwCWq3&WVV?mpy42thyCz3p}_Gjpa?^bzyD+ufH zhCBoraxP!=7BK$FfAqu-4DQBTbHxz1k!RR<+hmD|X$xj@a6ckue=iuG^xDe`H-5lD z>1xW=Wba& z-f!Z7xUhjr+cLEh)gpYTtmc0F$b=a0f&jF`i8JHRS5~qas^@K2?<~E zJq6dVB`F(6lziX}Nxy*@zzx~gV1&;*2~Q<~JCmtutTBNLF+B0SF}`wx(i#dSy?7?3 zW`*|}Qlunm8rNm>qaJ?WOtgo|T^tpNMqN_bXCS$Jf#?%{*!0mIT&B3X8TFljBN#h=-g?_^(8afty7W6-6Z?fT2yQFu7GP9=^R%;I2F$NviP=mHW-$DY1Nq(x8M@$Dc-pa{l*N{~@#3Rj>f`!M)yt|JInqJt zL2N+@+7OLo9uGE)<^3m!>u~@;Xq#^bQcY=gY#;i>7BxMF?b?}X)zUb)zIE63u?Y6k zbuJl=Ym_{mWQffOLf@-a!_zIU1+^Em-?o!fQOqyah7ht#PqVd|!r4GxG}&>`trfwr zxb*AV2F=0b7IPeHm*;o+y5vVfds+p(w9u@^?vx1K`L}tk{fJ9x*E}h%8r?$E3E`KOTLe z^qof{BKOqFMER&X(&3}}`l3`HgDWOn_9ysb?;`vVbU=yJZA{^Kv095yy6=?<62&61 z!U5W54rnRT7e{LVFPlWmUDJv04C3UI69{Vw`|a1zn*kLZ-*Z(!Ta`o4VP}B+(lnk) zxnJ)wpM-jKQX)2;xNtq}bLX3mBsCTFhu~ID;*_#@6zefueV*~$#bd{KHriR zbLmu)P%1Au8BcOgKviwD0-8|aZh12rR`spFx)?Kg?e#ec-To?<%tFiUDbM_&^Vg6g z8Y@?zB!3=0p`Q;r$x8}u776GMQd+avBVQ1fH;D-hlaDokK2`af6j=*a!dQ!%-eU-t zqjA0OIFU0ndqwAn(Vvt#@7Mc?&J&kP*rjg<0>6TU0)6A(sKugrj)}xd4r+G^ ziY+%5F@*} z@wG$kpw@_8;jI{yHN|e9SFxX987FL0tA(d~74({*uFl-?ueh2D#mtigL(5n}Ry^}L0W3dOl#)Y}uBJY-k z)mBo~q9qd6IZ$gYtXz#DH@{*CEtnMZYrCxQGbdGxT2BS=Tu{3lw!4IV6j5*aH=Odw zD)Sp#r*drO8EZ-*^ZVGNNmAl{GfftJ=o-Z4>BKCuxv;RJGAYAaR``low%K?Mh+Md5 zwpXsF6ZBrz}&u_)c8pCUnGnM719uKyk zlX|`tofvCB<|!JVaw9T`(%xl?7ZqQh_lElkDRy3s2@tD=Cd7{>ucni%>!e~e%%*tW zX{2=j26X8dD{MX{-5O1+@mK;KVjIXZkhHq4dH~zukRRFk=jGij0hNLV83NHoksSos zXY+8IL^1a)k~!J>F&QDyQm^ZXRjore|WuamC7Bgv#P4Qx|EI+NHvQz>nIjgDZYUeTn5#~^Qg7$6=*+~kpl03 zEXO6lt%kbC_sqgFGC({CIhI7M_{z~i0cE)EjTDq6&CY@aSK|&G7liGb;53)79f*3y z_6$kbCFK&u*3(Glmn_sLUS|Fu;jnuXmJw74Vnwf-a$hyWY}|}J!KuL0hleG*mpcjHP3fjM@2C4qLQP{*Iw8L>dhGQ z40XkTPg|QGDMPZOyGuZ+bEh~Ib|(^x+G690AFOb*T4{=RZmIx&g7)e$2g}itroBMi zNXAkPb7i4RX@nY&C^FM|QaQjz>6e6@v3mHMR+M|LXtFWr((Cf=LQ?U!(GqB*r#Sw3 zRJ>GX{zU@5a(T^ca}i9 zJbzSU18Px=sTJY#7(f{N2L4K3aX|FHpHQhhUPYF~!7pInSdlLSc~!H)%pLGIY>K16 zT^%%yM!>hwC1X2E*fsST0flLWO+Y#W$M6TF^Z%;LAq>iwC2%hqgEgLN6#L+#$K=Cf zH`;A*zUqa#;DkK%+#wHJp6|G3)j=;O_Xz zZHO+V3E)LC==4bL9U$x5>NeAQ=G2mH445_M^w{&M*7)9w+Wv(ao6vGK&Q_-IYHFSl zegMM!Do|XRpS6O3(%j2{?AGq8xX2@-j37p4gV3CzkLku%vXl~q(F}grkN$ko3Q?i~ zp0xR`XoWC@U066+@hURSR>pN3lYJ-Z`bdYek?!8g)CBl=ZY--n?;j-BT%sXW8&0(0JCvfU>`6`H8lN!CD!j3qVuGQdn=MsQ}4AmK59vo5H^83s7{ zfIX!ZxQ>#gP71R1F3C1#gX>}Khe^MnGk~WmUIu14U^xU(waV-M zWS~3qwQC;~f^wPo>>zY7NoN$AgL$HBBz7dJu3~&z(|j6JxJ}m}o+wEtyyA)NY_x-A z285usJ$J2yZC>M{!Q^g4g)CHaj%>>zmopOfcO>sc-Nx5u6#%t1W+;Qse9uJHALgF|h8FJn-NM=62 z&_!LPcQZ;>-dmOP!chUG^6HL{p8OS3n)8yx7N8j?ARLmTXFqX-GoS*4${mQNrDq6u;m~L=a1^G@ zITT&n293vUHVXcNf6{?}r>B>UX%8zpydA69Yjo`v<6sQxWvIM7b}wT11@ww;rrxye z;&RBHy->09?L9xi&1##6bBW1T_|4PoV~AU2@Bz1AGxro=ZWlcXt^#N38is16Gwef> zUk2_QdTrAUr^#k}(^REC1~wEo$NrD3aNRXo!YO}A494;qNrZx(6b_eMT{0fc@6r@LFQ~8q zXhD`IgL@eYXQYrPpvwK#8^OUP`;p`xjh$>m2N>TT;y~((BX97*p~ic{hQ?PhD^k20 z^za#=5sf)M{~mS*t~p~t-KNtdw``O^Jg5O1pfk0S1|OTKp+3u9{oF7(=90Q)nvHExYBF%(YZ16d1weRNU#J3*8u3;0f=A=@IwDZ`dVnf6m}l0wrmd80#d%^GbXp9-Xs9Mt|eP2VN*F= z5sw%YkgyBvYKkRPKDEPliX)o}eN-#h5Wr;rHhopr`uN83~pxs z!t>)l)&QRyq}4w4i=Pst^mXXZVCLL2g5i6>2La2oqRgThv+3ytyVmfDtCy|uV*kHkk3lh7u9o*q$OAVaQX@rV)cNM$xAXse{H|4IN@Oj3~b!P8Pl)Yba^+7=T z+yw=Nki^73;N+Ob0?}my$=-wO2s|BN{d@)amqm&<38cwmEnGy{v#s+CxmU93)~$7O zg(g5VHHU%9Sf#KAn^7z~5ByoWw^n008;TpiSGl0>P!+oh%P_{e$gDoaNx1>U$D;!3 zuxN|M*0aEgN{!z#NYlaPcw*~7K@*7Re3}-x1bEN9fy@71qHxWb(gToI@n&jn8_A-C z=I|w=7*Tn>@o0j4*aYg<^}AyZ2$i4Y<*44Z@tA91!3>5FB|D7VvT3n0cd*eqEp7h} zvDk3@Iw&?D;MRhkbxk3dr-Dx_j;9lhi)8*eivU+?Vc2}RY5u&Lkxy;--4Gx{^MPLb zO3Z#D1#`%69uT#7q5?RyMB0_)wNB7{14~+#PQ+iA-WKp)9Rx8h=oAp>_QLZ5o-r&H zT9uYwP-y1{7Yc(>-A|t(@>P$pmIO<@Ut4AgKBv{inGu;ZN;kD>=wo_MR*CWsiN2mx zsGP#8EO{Xxg1^We60gvEJ| zSKw-=aBtB z3|@=&k$WXFhgupw>wuD6YHy=#*!I4nHKS0kcKcXlFTF^E1{74Pt+Yq;_B)`ZQ(4;l zFxJvpSoq^aP=Ux;^kQ&U?lMyI0I+Df2E1I(fhaxVv+WQ6j|(@@ zfo^%Wr@sMbQ9xnCeat4MZw(rxri8FQC5u9G^TEgLUl4?LXv@Zv=>l{yQwio;1oT4K ztsEu@`=Xc>w#m4viv1xo|U2v*C7Z6>4!9T0a{y3v>?Y>7^0T4NeSm1!BliuQ}pg(qWsdjx_PZDW=g6syq zq!}}*dsImB!^CN!Xev_}x*KGjX(ZfQ$|EFVHhA!Z^EJ8=Im9%iE=ZBRKel_jTjJy0 zDV;znDZ0RP`}lSTma)s08d}&7LS;Ca(a*$bOGdY&s@o?%uGcv(pfMThPye);YZsGp ziotPu@9OJ$CaUP#4?M7GBI0*R01Or&v&B=QW#35HdqZLWxN98=eb2upRgW1lq2`0% zk{_TQbQ`8Jrq!rf;!AQAWmO=@@?^f87v$)`f=FR(7OfgH3BC>F_rRZk*ialmD0?!{ z^7Uc<;lj{?X|0q!B-8&3T|A|1;=srD8iP=8Pv0@BDl*KWU780}FfMsg~ zkWC$%-1xsK-!f?bKVFDI%~)R>w#W^2$1soSn9Zq(>msP<`27U9G}B_)lQFm^@)sd@ zC15zzjr#?vK+29Q=N7a!?BukGA4zz;%wI(670|B6>WpbyPnntG%HWCo{{jgPa>Oxz zP>#E2k(f?wPY!G>!N9@k>s07`+wAj;!^=V$4Z-NvF$?DpiNpmV4P2sAIY7Rq2( zWZ?$KuDe*mUd}u@d*lvBXLV7jVx%cV}lVuB>?sD5rZ3IQ>Ad}sATyvOd( zOAlECY=$><;JFh-_9XM>N3w>bue^0$h0+|{BPy`xf6f|~Jqxp0a6v$0 z-G=_?U#6RKA)-4=KvaZwRgFVoa$DMTV8)=w+pV&1c{+iqfr&b~S=z}?W{2NX#?FTZ zW{HlEXmp9<#lod$5mSQp|Nh z1K^0D9Coxn*ksn1!DORd5Xo(u)j<3m;rnl1NdL_X0QTuWmaAL$U0vnS@aK@XVoN$9 z0EPY!W}P-Ng+YAYYs68TxNnUM!F!_57fB?F(AU5kO4xVn)vN)ogngrjFN2F=rc?Xy zhJfKa+~Emf& z4oe`;1p;Z(lk5M@0+{2P+2*l=NwLlW8f76Uuv1(8nW|gWfW`pHp9j~c14&APEqQqk z?0sppX|V{5-#jN$%5%w|sHS`!Pt;k#%xQid*|vP3i%cpKgo%$Mo}Z^9 z@@Q$#N2C)Rb|dJC4e2C29ey@gou$<;IdSv8Nd42%O|2Aq=$n-zd5WKMGpK`o2QnB9 zhUDJ;8#*?150ml~tmpq{5L^eKzF|`^%tCe9BpBn@dl1u8NM>1SJ&>9767yMg^-T^TL7G`E@5-|wCZ|D zSsl|kXa`yEC~hFs3x5=dI>7p|__aT$8?gnCe#@a0fye;jmC_u*r@clp&yTtLA-6U# zEhIpgN0cjNkn3VXqKS8taIUK4=LYD~wd)^@`>R&7ahMJWJd5y^rjDrlT`U9U9swpz z%z}xZ;X{m_;DZnS+;vqkbde3G5n~~Uq@?~u;`+mUTA~*uriMhYi_MFA8zt|jR~{12Y9S6T$jTX)i{Nbmv^bWt#LTI#PPvH5-JGjM(nljMw{emapIsufG71o3-m0*i+6!VrQw>lO`+( zbkD?DWTdCflG*X4PvJGMfnRXUH^_k<6>e*dZy3Ysy)ZQe;@5?kCFNicCZ&?Dl@G8H zny&mbx9>=vu0@WJ=nyqRb-R= z+#f^;AmzSmd2HECv&J>;Q8$e?#B-DR4?bI zz+k&V!=D`K`+GLC%0AMc@5lwa>c7lRMa#XwDMR{E$k}(8iv+$i1R8>_$*ySi8tnyG z+A|O%I55U>=tArM3pQ8a4bDu{+eC6|;a2=^An#y5yXo`8_%LMjb6c$CpR3>CfQC({ zUZ|;HjBMcE`gw#CCQk$uCag?6Gs>eD1)Mi(f;sX35@`;xmWWht=|W7;AnviUO)wb; z{sL&cjji!>If{b$*T@l$j*7!;$cYRvh_~oke;ZBL8qw`NONXoj-b_C_~Kf?S1h}jjUB6a)Z)+NXI8)l!Lw6UX)9n#1u-Z zbZ!Ww=aDH>Ii?b}FX{6?LBe855;1}7Py+c>7-9ReBrW~h>oDcm?M=@go0^&~mc_s4 zXRv$Rn7YT??qVK>7@6OemyqKbYV)Pwq$wMK);!1Z?Ep*$LV`8U92?O9vsx_BSnbxY z4#L}N$3q<`hFtJuZ_Ip2sD|}%e>Y;(N za&+>KUEv`1w}|_X@?e|V=(JHOq+X{^8poNwUltc=pe5B~?rBfB^IkgLUyN8O`fiI> z*T8s(aS=Y5Ps2$$fSkfoE`>^~Qz=r*dFe_ytV5lY|aP<1i7nl@Eb0jrUJJNZ)3!+BHy>16}S14L-wu z0;>rO{eFm1d}a{JF_f^wA}Ow@GmoePhm|!+Eo*Q)?mgY1e50rglcxaR_Kq&4l-^~R zG;bYhf?SaG&4M+$bIH`$yh(DFoLB)HSnPF(p-r)MVvzT&FqpxKjeZSE^`f?tD$d^B z#z`c-57W!wgaL0EtDvJw0YYmKm|fT~wa)@yRcXw}-Jg{4-0q7Vz|8UilUR;Gr)AMx z&Lq*g#s+Xnh(I1|pBo_>s!Vg(BPkQ4j`R}DOM!eG;wIYImudFrr=_R zs_&zC%`Z}0dvtU1!^O&s1)ibzY}ki84@T!fv^nB?{#+DEq(aWGh5^B!woRQylpqn`VBr4(*19<{~Z5ADE0k z8hj2Yqy(dIc*}bEel3{^oY}Al&xQfr-1D!H22LRy=1|_;QQC^FCTvBYl?k9Y4^ zw#noJEfzpWq*NxVk4(nzOa~S$fjDK28;u=B6n;vxz9@i38GJ)>UVnBn8vG`pDZ#9Y zJ$C~`7|8NV6i^Ac9f0e>-ov_GdjBhOS_BRrfnC^2j#Gmp6|7bAbWyx{fpED`PNK-Ln2`kJs7|n`R?BfyA31HqN zM`yS;ARA9-Ql1^00uTnXSr$*uXKoFQNY}_xwUtY4--?1NG%}TyiM!l0)!Vm2Df~Ow zTk%yo@#Fqi$B^CXkNz*Jw{OTFc1(Rz`A^|+~!awU6pXZ8lDtt+quCWGektmEC#GRRaA`tLr0D9ZUZ&fNyIY2)=kEw+JeLlq99dvxC_2-oHin zn8`)i_Y>$#OQ*u@2szCLtPsqL_bg_prhMUs`XtJN{ZVEGOOurUJ2tS3$qsCMZP*qV z5dvq30r*=!RP~l)WL7=F0TZnvY=iDd^O5{s?N${t^vyX%<4A!luRmh@>i>r3P1-JJ z%RZGTrWF67CoTHBvGdM=H28$HwQ#R8D4o6y(3kug*;A_6bTFujP3j)%83Kv~lm;H1 z544Q`Z_eBu$7IJ54T0bmwVd?ZF8i`%U^=&a6f7vMyA1~aexU|z1+40S%amp;tZkE3 zlVUosVtIeMN(;fBEl3yzbD>?kYUBv2f$H)(jq0kF_3csBgLG9~cp?!N#&JQT#qewg!){)d|Ceet42$zL>w#jnsuhhVnJYLKAl!X^>q8jb2(iA>OCE*+Jv%`B zzI5o~KkPU#^4Jn>Hk!GPp<+ygQ(mrYXBrHaWYa_DOB6_M3XpCXK=|RVhnh)5 zUGhoQ{pz$Yic0&xjFr8qf1Wo|Tg{i|YMpjBI_dHL<#4d! zW#1m8!x2S)%0=#%E}(Y*j|0Iz9A+==L9#C`!%X(S-J`l7xZU3oCcg~g(7T<=8qfU{ zPwQ*Ze^cq6(uPDV%YA|b*v^zmaZvO}Dqv?;djTnpIsL}jeb2nA6_o!Ii*tXCA9JQQga^pWo1 zIkh7X^qO~)^mOg@TsJnF3APqEh{)PdwKRQ41=s@Y3L73_v9aBN4*u3LCR{MO9srXQ zxPF|JV&~&vXPvuJBk zn0uoXfkH;pYpOK3!z8UaFslTo-uwXP7^z!=6|^wUQK`bk_iFEDDnwb(uD#7WaoP4U zyY#8asSgF*of5^l)R*z2`sVbezEU#xu}{gZ8`g$wIC61tc+!K| zUqtON>{f-IaEbT0>=N%P{Qn&KtihC-vR-^18n|I7E zmwlzS)#Gb5lMnT3eN_sFHd7uMTyi&|yl(Lm2+G@xdT!K(glCKI-Pi81EoE}KJ($dd za)e(VYk@ZI@k*L`e$~#1fS7*W8~hfj*VD9Ji>z?rA0YlFiGp9nPGLnlD2?s1RkGUJ z+R`?z8*INmGqiVZPgg_cjtWwIzxLv{vsY*&wN9(72N*Y*f;W^rYE1IW7>yeiMiXx4 z=bM>5{{8QCk7vYw>+G#%vEbpfBi9DCDP2l~OIzPg?b>dWoOMJyCz7>M5igOhc%f|M zATI7<7CIfY*#4{p3KjW8qm-UKa^p5v}iTY7Z;hlSnIQ zFq<1<`?RZh=IH3!o3qnZ!{c5b8ulncgx!sYZ5KDpqN-qMK0Zx4R1nqvo%3A7^Oy z2-jLg1?LdXOV|oxa(mi%$U<-%k6HOc-sXl#I49t{z>IxRbM~IE``U zBzfj#es}cqqs@yle)9s%bGin&3uv*1>u0H#x(!z)x?6b}3O^UNWiRRSUHN_T+4Tvs zr#b9A_a(TKh4|7(sd~J`WtS+A=9c@Wt5v?Ki0?*I^|YPZ-;~6#^nC1c@cp}}&+&sk zUnNQxoiJ)RB*?OD@?mP|w+j6m9tm6n*OuoZc`d{B&%}S=10Y)*1~xW+BIxz!lqn@} z7OL$}YAw7Q|E{@#vt|A6JZP*_ZyX$bb!T9Tvcq7N~~ zBCW^W{?w=*eOmjCX~FJY`?QQ>U!IEZ%E|Rfph5PqcFJZ<>Dpd`dcbSWi6^;1hkpT* z1}|WD&rIv+-5i^@#)CJgMLFCbY}RCFx9Th zFvR;0+Myq)c7PYhfOI!CM9UI_X#JwkCG2`qWx?jh2G>WJy!fdiu3<@5-h za%|^@T;8Bum1mbai(8dCi*j~ZuLpf+7{3o!DI*%bq^yp$S9G+T}S(WdoaJw1r)+`fVzI+d~D7Z<1(FckO0MQ@vO$ z)2CPo9F4rO_FwdbgO0+JNanXK&a}G9#(mTlYzE3iD*%Zo|iLI+I4FOiP@D+ZF$R)V+CJ zlXuoP+;(cM8>rNxvK0}i8>m16hCmes6#*++w6cg`*uo}|03lE-vWS9!iV~J82;#yP z36PLb0Y%gVStNvzL>AeTuqHqR-xIn_J2UsRow=X)`8;hL5_ za!-AHDo*X7pKARx$!%3(UaoA~Jb(SLHaJZQCOS>WoKoG(wFRKf_3WxsI8*<%G_-sF z`v=?JJHzOVui#1Um5JLqYVWdE56)l`tBQ`(HzARAdaE+M~tW6c#nr zTo2eqO{EK>ev1-ez{B?C$Kuu!XOq72c>3ie{^b{xu#0Z!S-RG`$`$0Dz0}R9I=@t> ziiC|Q%eyCcb%yN6f7z&j8gZ9xLVX)vL&bly^b2mF2aQpyrpvvaIW8U~{cphH{snYc$Ok&%`v$CTg;ev9%-18~pOJDKV2W#4z7!(SGRw zR`DWibmV#<#;cdraljV!67+=Q!^Fr4amm>0>5_SRb)clT#p4J0SR?PEeCv`6Y=e_8 zG7llcqVDPuHg%k$#xG`$aquVW5(e1ae1rXvr`Qg;(4}FrPOAH|8 zKu^5+N>*aq&#L2?9S&YI=o~gq7Z$qp&|%*ZSg4wu5Snzvc&K!w2AKOby7e$(BhAlh zCyGJX_*?e@&;ZGpYtw);Q|zNOQnwJITBLd^E-N&w`=Szkt0Nx#)_?ddAV58a&pn)z zJoipx`l5Weva_ZaLvQ4>_oK0X7g_NazCI7<8oa7sn<3*5dgQcu# zmqt7lfIb|(G-0VAmDjml2$l7v^SRtz9Zz6xG>CpsPDEn9dO$n4uA%U`-?Z03>dDJ} z+GoDbrIp=x8aehH(QLD`07_h5-U<_S#VYx=fmJ);{p;*s+#FivujQ1&ZwL}_zDb&< zbgaMXUjFPpErj*4J<(p zY(LAJd6wNvmh@6ZWy!YtOSAGW2VZ`$ywZ=LmP>mXobfr~+`8oe0G!~z^qMaW|BWti zt>+R(0$jCr$=5Di3TERd)~X^+NOq^FjTq!K&6#qS(S|RTz_wZMp8L~oiv=>AmwZK? z8cf6OgQ1Qs>LvKX&vDCXwo7};ACjF8EnVVLOy-%=Mjo|btSsKX z%rqkY4|anliaT`xZv@(vtgGcDL)tOD`Q34k@%IF?#8eP>^ zC^8XHKI^^W8$XkcaLmnJ+I~GDHw>ca-R&^z8$#I6Mvfeo#6yv}=#+1%$vwQ_fWKNr7aQ*YIP=i+MJx~vb- znv%N0g#Ok+{s!Ea1#T7Xa+I%OZ$+C{TmK~KLgB1JqTrtRSQTPSn({9i`=BwbP~8ac zY5PXnyUbFQf`_;~>{cwyr5Y5k(YDI{RpW#-N3cpawb=ahoYhQXH__Ar!yTr?*Pg#R|<;F6Mju(D5SG32q(hjPIwo7Az^>xGhJ3N=fE!-(pdCztmy`!MQ-&U+NYezDhv~ zv$=U;ZNB8kvkJp6AEv`@v-saMbi$V`+?Uz59+pzUC|&T>;Z{9$A}SS zs+|JuM7>$Nw{i%DDBRL8weo3r^j1Is51$3I7hitUIBe_$PvLD(D$gnv(Wl_1)8rmwK}P1C_@iKoIAi)2|S3Mi6@;vKQZovWMU$=h}%!+%!{1u;f@jnb#5kZ=;d7Hw!K9C7-#9NIkroPw5ltoS=MJ--bLGxe{5#mp*51LS*rV6G0e zmukLm_AxIr^{3v}|5SMt7T#){LAiLfWD51)EG%Y9b0?_DSFFQm=ll_h;@pT#P(2+x z2#;jA_lGV1;}rTMy+lFum~$}jtRPL%2sVwf=FgbhtcFQrjPT~!XTLEoerERJZ&lXnqmr%-X{J?;ZA_wZ3-#2p0Tf*|;(Q^}1BxLkhQ`^C zY4JI{JM-FC|4p;s1ZQN6Zh>f*=J%QDywR4c!R70j*3WP6$NMaL6SD zaQ5xW@`&|qbKziwC))oW=U<@l_8G#N&gbr>6|^@5_GSGaAx-gqbmlAd(%-drMGskk zr+=eILm+R<#bEr-W}51YbB5ZSGSR1lIwxX-Ow!q1;hzI=d3rNth}H7M*jDw$GR+nz z7xo6Z_7?(gUje|pFCG5OmeeI#P{g}kmJROesc2UTURx=O=(QU^aq=v066C>+VVwYB zwBW?zIxim7gX{Lh`4klJu(R@@9yuYn%Q0o-lU~`0^4i32@W%-{YR$tv^3g{iyLDaa zDP*;UnC#|eI_(kuiIkz@@>P>sw$56#{RRMWj{4ct zJ*HrfoJ_fVYL^Xt^?uLLJwrXPhp zpvv`dMmmjjYrkx7awd$Uf2m`q5h_daJQb?=-*j{f4^(D^x#}vhTAPM~nCt_Sw(`v1 zZ#nvGE=^5d1RkZ3a`toS9YOf$3+L{MGm(rB)Q8RIZ<2)$w!kEQPuf?&p1oUiqo5rr z*Y@2@m3`Ot#8m6j+YMf@xrJtogE%rzy?F{wB;sksneaLVZDgXGI}NXkO6d{bTctkT z2pNJM^&6@8wmb`A_kus};}{FH#dt{FPIWN5?5$u~U`4qQFw$A);78{LAlZEfeEl^0 zNzhQRKLCW*9gZW%%th5n1vyUd6hOP%<3L@IjT%-wVFjoVeC zDrgg1PgqB?q(>-YIq$|#EO`qrO zFSXAU>9~h`766agbg6f@aeD|EMDcr;6PtDS7Tc4-N@%$ntz16?i*Jt!?0y*eRDe<_ zbvlnlJ^Og@*z=DEuVOWwwCoJ4-L$Go$n+lrVL4L#%{Q65+P2icqx2o;Kdl!(b?2Hs zDN&!}CtvD}IkE1n(>1lzQH ztPbFUe*nwkCjZWTxI?lp$0>u0uJt z>At?-jm7VfYxDyw9H>s9xC@FcIJ(e>tws)?1?gS)%E+A%Ua}clBy}5iEZ3M7ZcK4{ z4Y~y38GFZwnkX24Wl8qHWClQYH!wVYt?*^^>#k{+yY4wp^~}pWVK4Bn()@E55~!3k zh!E|^KlsPWmP_;e2Ans$LGPjRAQp5?idsb~kJwg8+o98;1cz7E&v}DiTDFZmEEk!q zT#lp>+lZ~R`b6=MW7kHH<7GYA{%bvZ8YFw&;*wLVGe`(&+x`&(e-*!xxy zCw*5OEIsL74D1~@X+;o@)PNa*-$z}XCg-mfxwR(koo)?5)daXmS1++}bsW9GiV5O- zSgbG~D}((`iit&U>LvWn zsymyi1&Bh8_14olcKC$5;^2CZgCHbf&G+s~`O8B4Ho4G#I_=MN?80YwD}0-K#tnWVdHcQzYeKkBe0Tz4o!n-!F=l)ZLzYs@?f)pX^Ujlr6GoEG zmco6da7QSblmuq&Y|}6qTGUt2C*5(gkel=!6e)w6a3GMHpn!WVy(d3=>Big;%Rt`$ zv8D}^KKz1SYGF?19tQgV-06}yx|16-%Y8b*3 zNvLh->F=LN%~Z2%>#0fREQ*U+pzXh8+b=ncxxOdn(LOZ!(?LPmx>NU*u)s9KuG%Dn ztjx1{Hu>rZ39D?sw&8q0@h}F&WW%*jwxmMw?hB9iI#`p?69F{lo>=!VE?TU%m{Yi$ zqUQenkf_DstsRri-be#foY{5$#>$j`tV7D z)y}gj7?6>V;o^8Yv;a7)FCEse>2fxK5!Nuz>%`oo@kcGLyeGQ+OyQYi`NJ?^`pgg( zerUa$d<&0r#wDF3KZL-HZenATn@kY77WP-XetvXePf?6~nP%o2;1(ab@nTPGu8K4G zztE&l_a9N6DEZplsxV>6B@Wds6l}HJA(ZB|L@=@vmd7|cIHgU)XRj02TpRSvPZ8Y_ zXrlNW4gHr^bd893@up_hO78K!4(K1IBbfO>Lt=%^nPed zXL3SU<%Bi;uL$S!@5$1cXKT$cCtnKcq8TFn1C+EIXJjL1b>BpZMz1h8% z`^xXf8pLYf?RR%SGsLNA?cjX3ZP_LFk^bAXn8Km3yY~tUamVbYsD0r#XP!pbV;Iu2 z)Rsh7aggW=@)-%)$fUF5%iJEutsz*A5E36v-WSAgtt@g6;Yo|4-nY=26r3jL>%C3t zYX~9?!Lv5A#l3%a#Bh(9|koUjcMidUGg=?oharH%$lBQ$)Y8LhiK%@uvfYSiuv-MTvpYnLj~T2v5rZo_1{b5 zV!96Liw^0CgOqHSg&hn+zxMElM~hilPh^mUt$pG5tPI(1?c-Ohz{rsy7#urv}e{Xtu(sOA{4?C|i>)?fo*rqPJ zWkmFAB-_5ARx@%4yQ0J0?ogf7N%T(p|U$Ow6jd@dqgF#OB2Ax&6b*ErgdF(9i zN*t>yV=*SSb1|q3aQ)rM=to_NhFsSQM(pS)ldjm$x{S|`OG3SSu6&V;?T;RL;z!9x zaM3I91x$&ena~mM-~LHsSY^6sgC^bmxX2Zoni=9#=T;G&x}2F7;PeryZk;mssJ=Iu zzE9QlI)*yQ`S{y9pIzsTFMKkVZa1-(>s}PIG`|%?XkvfCT2g<@C8suhxLdQjqwh3n zxU*%ihNej;JI>&^O%Qr&d3Q=@bjvG)(i?rdq+7dF9>twc#g$EXM*Hf>wM0#ubC~o;?b+rCp%`4IqZ{E6vtSK z+IXf#&969?@58|=(i=-Ta6K!XH&M+t-BJ@_yoz@*7UHRIZ9(VkU4(MY6y1Y zcMiN@_Fn1NtLW~VZ_C=F=US!wirzfxBnGv-|2#?fs%w)ny@@g1N4qUsQcqAOa} z9CdMP-!6PkW^;tgOAIPEK3GAx{hck;WUgTso+KP(e9wPsa?b7%uJ2)NbRMCoY5rn0 z$9WussvgX0!wS5qf=>;(23U%lX+;^nP+&Gq59)tLQ|#&)Ayn6*=Npu8@`9B-%##@j zu+<4zia-_}G<2+--oy`T-GGCwNK_p&J2thFk7#gJ$7n;R9?M+jI9_B zhIilJWl57dt#S%;T;+7f#I(sq3NJfS8!%AjBJPjpdB%zvhu?i1I>1wjgfH53TmP*q zky~D}du}0T`C98^4CoaGH>(~Qa=9*64IubdzF z3P;X-x)2L=nTR{6*$-itD7(mzla^vvY8-zs1+33v-2%Ryg-+ z(XQl79#%h)j4po7=$gw8o7MPCrboPw&g0nnQrUaAR^vA@b371>KM9At$LaEuHBZ2+atJK<$lGYhqUo&%KG}31B`#5IvUSCSl z2I3kC7J3dG0pp=olYX5E*wWaDt)HcR%IxL{b% zW8%~X%{JdoJG3uYgH)V7Teaz#N;xM5N)Ras)L%bh;775p+`nIc-E{(VS`Xg(v9)?#8!aZZ9n*eP2z>ek z@j9U$s~Fu|?3z_}Q;&!^_xV^l>kHdkyQ}(IOrIh+_ixo~D&sg$8pQ?G1P-tViuke!^X=IEfJl;aT%9NC#B7&-evIDEVL{&2#Q7pykch9$ygaa;d=>)P` z^l+-Lypj!kDN&fms8O^vvhw~LeHr4VNO=?mAEh)pEn_7T2!X%Id4MYMRWyl+4tpKc z;U6yryWkc&ysUM*YPgUs3pQUQO$>t>$|3591|*XZx`4T?HhhwIDY`THL0+Z$ZO!nd4+XBNYCd=S+XIUH$Y@=z@e$In38J$^2X(Ih zVMw3Q3OXBf+~4%%6p|1b!<5jSTjmCs=W{B_{XR2+L-(^uM6z1uwE{0Pj~$TIiB0mR zoR5(`e&N@CDmxGk!>h4-1@?PnSBo=#Y|k^TYLXgte^$7vXl9|j;UlVbYcVHY5sGi> zF|WR2?0aY8T5IZK;53WBcR`qQ)z~}d?l%ARt>>9@8^}(3?$l*%(E%wWED55w?w!QL$|;9$1Yqz5)#y- zBF6fidFKA&NAKTtnoO3>RL~oTTyHo(#?ai!#3g_@e#8)DW}a7*u#_OuP#N^*=(opP zswU+(xmtKb`Nd!jhrRkUyMQk&t36@sS!&m}N7iX>{dU!A z1km2ib?8e9Vxw-Y2Mi#{Y6@fa9zL&h2p=W*7UnmPS`ZKq1@`H~M{K0so~zQ_6O2<$ zkR1g~yk?gAm+a2)VlGzEw?d1FTU%&X#^L)@T&8=nxHRT_Q@lETAPE&YYFD{9+cevk zoT*f*OygvAV5NqgZb(o#8uF`6)hb=j6Q441o0OLfYS*4sbR&&CIH{#xtDWKQ$%r0a z-LA>1XwM5@MG~I7lEF2$^Ukx*269l9XAo!axw2@+FbVjQ_uYVlz7%ERitda6)mfum z4=VN4$M5^{k=?RdNorG2yT74a2*IY??=vjd6rOdh+(k zBvKciScD<-a#7gA><^2mgN5;;oDJa(NB2rgmdFak^uPw2kU{v`S&Na}TebFj;W@-H zCVrn(DN(A2A*(^Dq4@>O5RoP7&I|+4(0-*s)ehI`Oe#m=fL9HaKnrmZ{c=zPU}H|z za$e)*z@f{r-S9BpJi@nR;{Cx$tykEhQ)FT_+Z~vnFi*xeV2jmxH&AKLz4c|FlaYU{ z0@&~~1LktEQKKf(tyk6?vi|Fq8$OI5w2|;IsGj9bM3CKj9$%S1lvM4(31APxn`hNt z#))YgsN)qIs0V{WZ<9nTnuxhEU9Wtq`Hf1T-U*1erk9Mqq9NZY(AlBivfQ9R{4WSb zWxp@lG%O&18#;t%CXWmoD?zpzYK1T3N&0XB--FcfIHV`i?_rC-*?R2n+ij8nE2h0y zm(KNN8Q@#9Z=$lDJL}Q&GizuZ+YUcCjHO1MN(fNt4v*z$styz6}ScHc`1B{Mm}SzmW-w3karsS zQe^8z$t2;|Oo?;tT$3_S@{Q~gD1&*X8)vgtcjQOE{rD;3ZP#T+(W(XVue&Z?ziU_B zrjeBzURkmH^UPqcylBa`?#6f{wi~ij7ft#qA=JiWW&W!#oLju=;wKS2f-dJ!c6xE8 z0^n=CjzejTPsVQ6j(_V{YO=nJ`NWWIZ>Pko?FF9n@i+1Ye17|+?Wuqq^kmkLr_+aT zk?W+NecO#PwheMhKMft(CqAp@`oPQDbP+louWnb$iHt+Yg)b;$>rQO!3aQy^g4KIL zr^(a?GnR19Ryt}wU;X8=vt)EZQ&uTFfjhy60;Iv8!qM%(3S^}(1ny~_SpCYu#0wKU zy5`ac7Of)PiSNL=?3>*@!bu;}bXi4wJC-=Wt5D{+E6yDMQg2myBkz<|P56-(-fHx@ z<4STd>58@C>x7N~q&hpY$eZkBMNI-0X%9k?&PcwQ|I+c8zL8Pq$_n_9*15lET_R9? z3TK>Glx4Veq49D#lI2wzM8vJv)X14aVM`bDnoaKjALe0bBzLltcTOfR!as+{pw;uS zjZJW?@|pl>Vl_CP`p|kFZ~$8>Rz^LUbC71YTj8Y2ck?1Un~I2Jpw2&w(^CkpG>UiG z?@=s2>I-0IM27{5(77x0b`WYXwEQl08Ygmcn*;p&)r9ED z6xYhw5*u9G!&OOLt8I50y3~X$8CmJ!h_$E3F(qFeH#?w(X8%R$SsGBz$r}52qI2K@ zN}R4baECh4-?j$#`~KQw86X`BzLDW-iBUi1lq-r~W}bAI3GC}rJj26Uz2DQ?NfLhH zn2nX+pjocuxi?5hCz4QGX<7d!*ST+>8H_KPn7enAHC0ycu-D~+T1x4l07w?DmixEuG)0wzbQE_GDCsjjvG@aiT97Fn48~OSU z=%U6Na3m<$RSsO1JV6T9@a&BFH0Y-TG^QjpAHl9v5nk<+oknmqZE}M=W4rJ}7}Ul) zOMv~@N!LswSlXl!M`a&Syh!@#B6{VGcoLklQk8QU!XlDTrllf$z?7)$ubndyI!$RX zGhG~}0$Fq4NT+q}F7o9z^U3#qdso zlA9KMf4>I&Z>oNBgjC@uBm0+XRfXGqI#`t6zu#Cv@U?$W2KPH4;|8piJS(kU1NG&D zjg!-a>nre?qAOSXOglZLj9;9gSY7HMA719YR)H?pph{GPqdd@{K2W3+YQ?Vzm-FA6 z;y`-Se`hA46XIfeKK#`o`nNpxkb>ZF5QKLaf&c`M#Ve#9 zuCljkRe`7aSjG2ejprU_Z#3c_;6i#x$cQ1-U{ExUb2o|W>NW~OZ^V|`BYAG=gLjfa?*CXbY?aE0BQDO~c=bgG>y3^{9oSeiO*hi$_6(OA z3}Ild)#`8j%O6aAba&C+l|}JO1DC4QtusBtaMO&K#1NhaM3!@Gb89l!w=J%Xu$ff9 z?_ZdIq+TgzYJj$GNu|~a@LBd+On&xlb*&Dn?QmmBmoumtwv@nJ1Um>@VMpQcS7+ME z_>sSFsO$=k!gPhz)O-^#_WHu^o|nR?X7qHcAt*Ty4%sYx)LsnXD4EU_}<;@H8T1TI|xG}ba>zkdrIpTe9hSV9`Ua)czj%?uv&S($CJ zwdk!5Dd%gh;~{X4K&t{Z&BOH1wNWL|#G0yTRvnOTS&*v064Lgg*i*P&7+KzH1@W7* z+Lm%bqzrVpM!oqS1;#rJAje!w!gGwwTCb1;!`=)ICfk!d*Q8%bMR2YCsBT>mheE4$ z!gtqUylx}74#|wA1WI1`Gbr$|Dy?v&Xdi-OVfOh&>*&59B&U*}uO0qTiB7l|NvN6T zc~7~l%g?lM&iOTlmKdzDrpY>Q12xH}-Hyortak;I(?vfU2*y#`{$J2C@6TJl$Oa6p z)e=RU;V+$8iz*r}m+nm$GV)LWt4Ttr<~x3J0S@?A9Y*#_ni=Ur^b?uV29kWl5lONE z@zqL>9tR6|o{Y}N$ZA~zK-=}R2mS5eYshHkBUy-pu!3WiOM-?l7hQ<>Q*n4M>uT>xKD3VSTgKECT`OC=FJ)1{fXD8y%#ue3P zu8zsk41FW>P8aK>N-LM-UogE>nKeX4atnTzpuE8iA{((Q7Xa~FI0r{4b5*{XjJePf zl5htT2l_;X{PN9@m@=e8k7vf_$HZAEww|0M1*iR!hzvb-{tdaYc2E4D5Ruz8)obNl zb@D&&s+OkTxAqa9Kd>HKuy_AiL*99(LGN`$BkS|P12|DtnJs-Pbbi4@0OZ>>3zFhu z&3E=@;VfuMP^oOa@t#ES+^zdKc`o2JNm#(d+0~+PVkMs4T9s>jYYvOTG>6-B!-_|L8 zO6u<>iLMW{^PA?iGUoQ z>=!pkHESS`052fzYPqYIZWsJ(&rG-4)r-`8h zjcf2f7qw$45P;M0p88)koAv{UxM#nBNdPKm`|2!C3nHueJ&NU{Bg60B2gngUPz*W_ z89YHLnvFsE))L##igDYd%zCwmz(x>teanIS0OJE8ZUjRBJd^cMVn(CsiNRHikwIqT zkM(4bRLN`pE00$XlvHaqyRCIrB=PruASUZ_vHrmL5(o4{-&NcMaReO9-2k1VLD;z9 zPf=76Ek23$Ll!k=1}TpP-seVj@B2=#6Kmyh#v9ZsqfRX(Hz!^ALsy|oQ0*swmDy6{ zUeLy^u`7ax@(4#PUnStI-#>HQhu`U}$VY`RwR+FF9&v)PahQBaCBYZL-H}@FzursRz8sFF=ZI^|a$) zqZ*zV$&CUecSOmT;xhW?j6)-+ST^{r8A(gT?7jMN?OSbHF|y6g4z7)DM-^u-4s1!n z?-f6#KLh!seotWhs|Ygage|>pBhl{`31u<|o8N@5B=R#a9S}C|G#P}i#IaFo zd8d<%6*arzXm%Lcsg%QjcmctD=VX2L$LrsMeb|{74%*ymSCckFeWEEkRO|M20*c`bO5l*nx<>; z=Z>X&&~=*YYeuiIBk9?(py@b`?HNm5>)={6A6%7c5rGz6-LAUgalCUx5AV;g+Kh$F z)%W+ggnfX14Y`9PVHbt~o%mFa+H_7NdG2Y#tGVu0y2RxMN}46?QHUzIhE5z zI(WIGL823>2rh=OJZV)?{J8)#?^-&hFgBtl(DqB`4-3GM2Jm*BU8gX%ma^=N)z{gj zul3rlmPh_IZVOe)x}y-GvDhoV)~v4hs!$ zdt3LLjiiwyOld>Pu2J}C!ym?<+#wdEWwxJKa;?eD7(rYf5$F; z8_AHGq(ba!{=(f#BzJd(83!XfPDZz2WQ%A?j%t6IIIb&4^Q9^voMFJfr6`27ci)cqb21izGLtr9QTKTf1&v^-XB_+&vNofd)N z^Ia^T-i05aKW#ay4*Yw`8a#!S^(UM&gLYde_p8XzJCH0sIXd;UA>{-trX{&y4{-6wGDWk77 zZC%eBpU;1Z-x{3+qTpH-P8Yp`>G*2v&ZM{Tw)^mK*SS#pIh7(LuTsWaobZ^ zdv*SRY<-|yMvq9jHM6?VBBMrOEV(ai0Ns8l4U=H3t7-+&I|x@%t>obX7FvLFlz?ctQ?xsxuej%gtwX(-ucSu zc7bzi3~j7JLO4be?rQ#RTqDf>3ewOcR{H#jFU7)T!>@vt7}CK^>Cjyz3*yvf>P3uoQ?8%w>6y=ensVmH_Kv$n)W0(>{Gsk{1U3Yy`~Z6#q4YW`%Li z<00U9DaVkjwmjo@Ni$x}FAuk#q-@oI8|=SJQK@zh2j)k2dw!ZV@Fe38BUG5P0T7Zb z03HeUR(-_W-J1~pg-oLWtBB;bz=4PCs7G>RZ_R4C%L52e5yPYJ&a+$nvr)>8l0c>d zBQ@%G)^276FLH84ngp6Jpust=1vp%b2Yti@&PNz70l8M;+P9Pt@0FQ^*NecRV&CMkcFj#BQNVfhq%$NL28bZz*nY{H zGT|((gap;9|J?*t?Cf76!25QkX6eXoWUFyDgJWZb=m1R$`5e9!Xh9LvSFOZ%tIhCc zdb6N5TZp=nGVMTwdmUWeM-t+bnUVwpf2!OW`s-0<{`dHM<@yTCYP(QFzRt18S-%gv zr0vz0#&nXD%(am^DDpXPv2a$_J_3L=o9R7hfEB4x!1-%&vGpDsrzhd3}t9 zd?>+g#1a)Dg`tEWEyVm$)TDEdmq`+MUZQ1>lZfJu3l@QS%0YjQ=f)awDs8hbc4 z1-tWC@_X)~gg`gBX;t0Zi{!c?I^}Tsc&J_1`myv%_00C_agF5@Mok2{OnWWeZf$dp7_+fA(H(L|D_1nxd(Oe|#c>OCeGDOlBsAeX zP3~|6Q5s++!FuvDTv+-@i48t_NHTw_miX!?b5}otOa%M4oRe4*X7_%uGU#kc5?3}7 zc=R9BRKSjurCmvt9=Ga`6P(6Rlg6(M5Dt1~ufDFdmU|U0G{Z7OF2QFnBsW&(7h80; z80Iq;Ly2Qo3oPWodn^7pdlc@0W!`8~@qWy^N)} zbat_K*Q)weSQ$3yPPnD_|AlTWMYP|FWr!DQ{68Ew(v6)C@7$zmERQ>${xkNj@dJ>x zuEO+D4m4#!UfBCD2;@u#M;#_^AkOapC<&Auiz#L@1VG_IN}d#d(Npatz8}K~@0>Lm z$jcNHS7rQ`729_D2@D~_^C*>v{eyh-PtvqJ5UCG=NNMh?hz)(-R9*ivi=ueQ4BuOH zSPrTyzOd6mr+?oyT?UEYBbp-D;LxH~8ePz_9KGw5;$o&_R^kj!VEjLd|!w&KKS6*#3M654Enc&#RYqqNE+~2*&p5Ws;J4888UXo#W$z~;zcllPyzTq z^pn5?kU<|d=#b$fjw<{812@Ps_!+)bl zLxRsvamoVn7XN;}=r?LKG~@4q>SA3gi0=cMnUXme3~YlDj9HMI!`4y7^zh&z#>hNq z@uZ$_>9aDk$>yRl5BARA z8N`HB_d(@FI`Z)F^BpQ8z}SC0dPIRx);HhbBLCyTBapiwL20+P&7bIRxkt1gvPg6edKt>|fR~2}Ks){Jpmr}mh&NVH+L7f|{+&i00{hTDMjUlW9OT3ug zSj(L~4>v?x{X@RYeo`puSV(d|V@mE~P;jJmOQL++mo^5%oYDSCwDu#rB`=m-@_k;b zLUhrxmBSCagyJPIt4y>|o zp0&&Q>6fly+mIa9%P?gKVu0L=f^=ceAI=+1en#2rp`Kr;RYi_;#2kfBw4JZWDeAQKr&#+^s(ZWB<)%N$S8@}{)t`Rs(MiTQehrn6 z-?FU(ji7{i3iB%y`6 z)7WTcA33OhAQ!mQ{0`|GtG7t5Hc1E?O|?}!R**rgUxDCO+Dv_m;A+>Lec%OYa7aHW z(0fnrqr&uVT7+5?apXeRR`Jqt+%#HOK4G+)zU>7a#Br%tyz}^fr%A6=T~YlTrE3#3 z*=#yIK1*R6GYHImNGWAKtYpDt!XX6(pVA-@bhCy$!7i?EPbP-Al%xwMnUVl9nn)%_ zhqryV5bjtMwtlebv*qk;vQv!gOJMod;RSVWZ`tI~4!sb;v# z^J8W+WpUP}`%K4GX3 zASTyuUg`ahK5=#^nW#k3AilUp{?90~R`iM>Z!L5?gch`^Qx)qX*-~!=*M?f#H@j~1 z9!Zow@Y@kUzDio>(KJ3-^AQ1LwOyufZzDUD1rZLx=3Sv;NMPNPr?ghO3XCO`gj zcg+S`RnK2<|Ft=vkvHd9bBXEINyCPG?|Z3pH~OyhM;EIim}y`W*NPrOqS%^xELToF{L-R@cz?k;YDMQGU{O>Lwey&Jp(VSaW!s9FiCBY z!8G_DJ^19|JLDGm!jPaE;&lO>7YU$b(i;(}=WBsrz=#-z$Ou^sC9EXO1PJ4I zeS)Jsr$c++_xJJp!}B)596mPYq+>*t2 z`tZfK^_c!Qe(xF?PFv~aRwF08a*m0Opl)4Pl$fzyuL5Y}~mpNSMbO2>E7F z1k5k=n13Ea(#)-|@ucQ&!92Ep68EeS{Q38^r^d47e&^tV`Ejsq012>o>)vQxI;ae;kjaP*$=ojXf$UV4dQl8z zL&7Wj%^bN>9xyuU?5^h@F3g8{8Pn)lyLff-8NUXjd$A$G-TU-fQ~La3Ja0!pyk8pe z4{CB>Mf`S=d=Qc*1f8;ODWnO{_$(Fm+R%&)Dw;d37nIcx7}dXh!9m-#8D)_8yI#9J za^YTPK+7p4(_gmThvNvsJQ>k?V4MCm@w_A}sBhB^MiP~Qq1I#IKNmHk!N&)_2om_9 zEWj?~L7sBE&k#`TEO_!>#*+{UXJlcl!-j=tbwKT6GVGACltMm}2GzE#_?)9A{9kW0 zHZNH-@6q@zSuto}LknmIDS>luz=0G2J&=QfQH67h<}nYjLCpQ`Lo-UCdnH;%1%8@g zCBAH+c(j2Mydw1PZC#NIZKc96s=epJda!EMAFF0yxm}05L&pM!OP?i@9f@#J+svbj zZljsDU}g!2D7c8OLL{_&VM94!g}-p#;k$3e8}h1ZigY_R9(W{;@@pPf>G<`W$8E)I zhU)xkjUy0CT6%~+8(A1Wq6#sl#vj|EfYyR=ph3I-h`ZljoW1eOJqrT3Ch7m)&ZVFM8Q`^6%Dl|VV7BmQJwkEa+?Al61l5H{l+--@PmocqP~M zpTBH{FDO$D&N>X~PE0jKq`%-zBw$Y?W0ob4!h>KcLnxQdmll=w5p+rXHEbu`)S|#f zE4`Hk zIwj0oP%>4_s&5X}Jt|E#(b3GT75r!L6V9+}K>xLe>m6L@ot4_F%&3v67;(CNKxI@f ztGqf7lFVluI{yE5VLu?FbSUN$XNaqWk`wdWF~D^|h4&`FOD)q$7iD%C`T>;4DUhsE zn2K+7j5qR{(aaYYDoh8w^;bjtoCutQdheMwZNa|bt0f;gZ?0Brx-75TmJM@GH_Q?z z+y}>nVRQvX>r2W_N(S%OMO*keSr;Nn4Kkw;$HchjL!=9XEzk-hPn8{`Ypa&rQB@Ta8}VV@1(& zxtXol<_o`%C)Scql%yCKmF&^+Z_jVB$-j0`$YR&_vGGXcYKB=`jAE8LdyGw&SnA703S8X6*!rArfm+ zfh^O+G9xvc5?(ujkoyV<3x9n{QxtDoaMoZ;$C_pGM@hq{_-sm8GU(WE@f|Erh#ZSa z0u*R0fMXa~HWe{qac@ke=(9H@N)9q|;d zNr;r)&l>$~I7cHK6yP4*weZ@Ogh%syHYb?}>&z`5bcfj8%`L3*?g0mN%p;`jd=Y7J zzSYkr4ws_G&P;EQ5MlS1!sogfFQ}{s#>JODYi#2Y$5cNSOv@1k8z3kHzl((Rg^r$u zLUt?U)!?#j#*x{yi2UfTxGO&NX2*ND*USzZ3XJa9qondKeX*}Dd)t=as{5?+mNiCw zO_4P31=5IN(We2C+M0P84izqhmER`c0A$DR^Sa5>EdT$FvVF0Caq?KJQ}vs9GZfEI zOWnOIdf*~yytAmS-KeWH83UOPoNJKYTfZ0O8eL>mJKk;+_~HC4jD{V8c_W_MJA5FR zOmr`2pAc^RUon0Wf^XS)yI+`i#3ED4brYsbPaDN4+O1H z&;H@{;tQa5_fZ%Eu3HS?D#pt^rXD|Vk_=7>W#Ng_WoL~;Ha-=s^ePFV>S4Bt{WP5j zV~ta2rsHk*qO#lqvqQ#Fj$z*}DvhI1L+?U`hP*SG!jy z{jbnEf?xpc=QuyKpU|wSEX8LX8z9`1h9&;NSN$LJ<{Br(o=45mMl4^RSKhE53u<9W z`H#pgJNye+e;N-&Ku2x*1sjXfV`&NNGwGN1IQo|c6+NVkw>H!AnF?INtOt-UFAoQ} znTkh|DX+d*B$Kv~CB}s9uYE_;ifzRTPY+mdm+L*r0L3~5JjfRR0Pdiiqz}!KJHGV! z%&sC?L9ZI7?swq6-M6_ZLFHy)`%HqNx@jPga!{tSP>`%2&2ApU0;E-dHhb)GA5R`WiUSegXkStb&9`M zJRr|jHf>eJc>@FMe-I>A$vrRjtd^}^n-b`DE^&hA;&tB()TsYLY5j)*?5n0jv7qbg zH8VJ}aNVl77bUCg3wU!skI@5?O%sm7W>h=V1UR?Ba}BpL^kSW=VZkz`?YBS7`XvS` zjwgXO`uV>GXw6!`+T6wxyDJkHoElCsjhK==J4ZtP&Hsv_1qLw4`Su|?xCMych-jdo zb)OL(G%QjBQpcZ(+~=bLT3rZQyJ{aGCQg{I6M7{>G6IQX@YhAJ2_GPETQjgIcW@hx zMYbG@`P-oJJ1Ie5X$qQtlU#pGFiyGK#_v%*vH!gDF_dnEi&jpnS@Ipz1fu2XNyJrL=MHwLCVoG(e7b7&^(+3t0KCrp_hG#9B?<;dJ zs6Ev7Au9J7uR~;&&ayt4BZv-B2T7PbFOOUsuul|I(3hVo72v&QHo=f(elsLS;Af&p zWl-CDso=K#SN<>cQ&B^pnAXeUla&T|iv|;)T-R&0Q2y6U%Oura2=2V3i&P=H-Je+8 z?x6hlk>iAN&F679^cc?Z0;vsIhN4t7;38SQ$Bx5pZUz=lX?+qN7_FyD>q&8iH(67A zmF>?8vNe_dq}nnICF~w+NC5s zHA8W2oFe)ar*Q#3D+=5z`;b5N|eEiK6uw`5e-EOhLxIf|;wK>NYK*&!<$y?X=HW z@3K%}&!oCYa2!d!Q>wC2%MN*pbGz|Bus(z;*sHU!k31+dR!t||-v{&)SHzzESx(n1 z&*#HN(8LqkpdKyyC$!c(GnmzqoLavnh}~r8dKgUhA%!;yQs@`;m_%{+RYP12F+Zg3 zo>$1Xp1((H?J0qCpsYCoLh2u!iJI-207*_tfOcZ|Z?-Eg0UvWTY_7E00bo_6OpbNAws7`Q73f6)a4{ono z4mRCz7Fmn9v1^+S@T4(D?V> zlp463fmL%W$pbvx?bECLOhfEu9$;GpEH9jVs4>uFDUCoGF!Cu*1WGa6vvj6#Q>qDV z(sJ#hQ^Pxz1b`WMsSu6ZGWgkc@S?(mI=^I1KqT$H{YOl|HM<_dHkhnUKu3N6d+U$7 zw&yTq|NH9NklBdPth&-Hb~I`^ng9)HUHBWu<$tN$8kiJ%z^|gD6@c=}M~nh?cKlaJfjKGYssmWqFt91DF?XbMFH)Yd3b3mrhqDlo;+VTm1U zn1_HlW%~c1S3cN4B+m4he#-W*;RINhwjaQi7p8g{;>SkBh2`A9iLBDW5$dai;0a17 ze`w}xJ#~15J3QSGc5AYGh#NN9Qvc|$Db?8!I3%i#Wee?#y`_Ag`Gqkg@BL3e6gr@l z2C#!!+lf^ChnN|h17gPOiu^J%5UBC@ot@@uhA1GKgP&vrF|M?MJ@bV$?K#V>hDKZi-5OTmL9e=lDg@*87555| z$+iQZ)U$}D(_pC%HXO!r@x3j;6?r|K_C-9o%(eXRWH8#u=q`2@nayrI~Arf8BfDM^$(78{Ba zg{6~W!*^$@3dPfpUkR^?!yXq>90LU1%o;|1MEmfr|0H4mZtA@c;verd^{zT{&(b!8 ztn%GRP5WoJS7hE zZ23;C+W z!Q-%?<wsR5E5KXAC!W5N9|gAzf(ZjSAdI3E5-zy@BP;A}r%&BQI`PH} zfOP$_@XFF~%tDHt%wf+wF3U5o84AhLsr(V4wLFXD72*R(+IN^v@YYNTG#pL|=$X%c zEJ;f<`m%<0O6-1JaVz%f8W>S6?a93F>V7){(j`}DM%VG34u{~uc1|hS>V{EdZZEwS zC8cFUIYD9ew}``O--GW(>H2@rIv-Pr%)%*0;sl{TJ%KReWhmy%_*b3lny{N8;qs^L zc+{!%L`f?u(Nw?IM{(xxBl3pnFv=uFJjnI0Dfxar1)bt|`@bOD{x7z0ir1r!)1Q@W z_jsV#5Q6^il^FkNf&1J&#}fNmymtURaMwii?W5$xymklhzv^8v3ND>G*K=G_7AwB@ z3X1ICpxK!AnRbyRa_lEB+PD6jk@~&Zz%|dUp!^u>NpWQWAFaWpC_~lvjd_OkWl16b zz%al1+H{#~qGX`KCd^dAtf7p?CKiu!^~Lm=mcpz_yWxnQwc;yb%)&j>3wfOBOq(z& zs+9Gc7L3#yLd2)qG&TwrmLJ~}X2_{hqpIS6m>(U^J>$Syt|s>Ri!B+h?)PwSO*ROu z+YljiLw+tPP#fN&$wOR`9+DvIf*1l2_ZmtW)AJc_=^lCFEu)}mZj{A?PKeTBqC>}` z$8#UtXBU=oO(ruyTNCX@FboxZAmsuyNJWQ*nmobu$io?I)+WL*d*@%P`z_!@)A#Cf z`V(52OyFSb4Tn#MV?qaegqg{{0`?5E5Iubnmo>SMM;)XkN=Aiorh9pu%CNYB33+?# zhJIpCkLfdt@SY9MWX~}Bzh(iohQptfd|+X-)Tdm9$H|m|IRL=z1hU+5Fvq$`!UE^_Hf3D=P~Cm)58DWI*wSSb^1fJ_bmM>=&C zz%7+_ttwRanZS^?(1A>$BMIb0b3#8NAyXGLEFkff!p7$AdFCSdf1pu7{Ld~zhmp^s zg?A|`4Jm5t;-{Mq-=CtJZVY>Z2`C+mNFa>LBu|GiZ!tAb{+3(T*4sPT~W+AI8jg z#V+SSztFmsH8y576?&jW@IvT=njV1f2MBXg?3z8`B$}}ri#e61VCYEnkI|Fpf(d<~T~S5#Z1W3b zt4D&8;GejrszVnUuMPL^*Y{+@+GhPK;Aflp{g;ccBEH|mbkrav0~3eV;Z91dMVd1g zo5VAYJkRN4ILC2(mpn^?A2hAaoJqu?Lc4qoHQZa0QVQk%NF0A7irm?!=%hsjJK;tI z#Yd=HPlw_10bm^#Lw$5pua!X;?|wpSSzvH!?Z`zY6&=?+NlA~pebFR6+;#Aw}FA`bPtFoDAbWWBo!)9sOdpJCiOxM_MyIfCdY?T z@%Ib45LdD@_;VKm__3NxbetKkA&$m8LludIq?z`^Mqv%18fb1~-rH>;e;8&g8QSQ% z<*3P5lbDwu;MiXf)bVo;Loi&uZ}~y;R2o=jmgLl1184MfFGG*%yg~pFgJ~;3%S;c~ zO`V7kwv;|Xjt(c?`OQF#((uf;)k6qL+f!ABI#ATiqd7JPX4+=9M9882W$iID(@$}~ zbGXW%+x#T`(|O9wP0E$i=Vd-uU(oSz^Wuu>#pTD%e$e^;(%Dt}K3{FAXSGk>?(DLU zzc^fZBI*9;l&>wr=T^$`e_ea_i&5oE!9QKrm#-l;m}r}5v$ak71xz6=gMx3w5K;C9 z>0ZeM@xJt?d%3rF^X+qm;{!CW(DeNY1lO;x2|G|TsuxngOQ0{0&+^^Ei{Uuv<&F@dX zu|BlHkmVwFn_lbM{+g#d4wBjV?E+(JI@n-s^Nxi%W58I|iyf z-WW8icwJ^}$L87D49zI}77ewvjLELq6NML?=@F^VVIpQ1JYeg*)$3 z4HJ zR7uffQP-YNqB}mP2{Uf4Dmn?m>Bm25yzB)Oof;WP0}a5Xo9DB57DYGURRGx(UW5XY_&@wcG?W3MXZlNFcK#4TM#<#+?m_fG&)!FM4{ z?o4hyq~Vo^pFhhFCp)QhE9>>qgrL$ORSs-J5U%%A>AEPj*)xbWDGU78WWWoaHVa~N zK=)xFX|LEwI$B2$5StUAv~zs~O`YSuf#(V$t~!b(e_PSiu#hfFH79ht6lbQ>t_|p+Yn`B`{a$0fGG-HwfdTKR7NpXgQML94R=+(}y)<7RZ{hk$YfZ z9QC>H3~M`aB2J83n8tFY_}NtBY;<&UKC5c2x-V|d$@vK?O>t*}h{@|R2UW~8A3 zeR)#+=Iip(s zm@kb7+F}bp_)NNJ_$#1v&dQ3*^q9K!&Tf&KJCHCtSSQX?@p5*jsQBfoFVa}ZDkpAW zvWGX!WIf5mN+z$*@fwQdMHJm*ArFZvq%B@RC>%K*7OAgJ9elrv>9UQKI-@l1?-LNjP|0L0N&iuO`uy85O~d@0moFl1_o_Sm zw65ZepB~%j0ya(lcS*sB25iK)52|V~EbaqQ6UvS-tqzAJy;GHw9FmorHN$P<1YPy% zPYPZ)y)l{iA}g{6F*~-r=!x{qbxvNmfz(x`B|B&mE<31l3Qo&3*hQxo-@Wn0R@ZR& z?V7?uRgzkCzxqvhPhz>Dqn?v4k{-H?1cqel190I9j{3czop5?{hj694CG#kV4pw3pV~CyWzoU!6*usDn9@D@qtEW3#~ZKE{<_ zqakm{b5`Xh2XQ;ZEi=A@X1uvC`+oN0z6#V(Bk^k>ny{36&Uy9AL~I}(_w>%W7v=;# zx_JK+NlO8&NTG1*jMHFf$#*GMc|&S%-ogP+^Nx2z92d3?Y;K$9@7{NA9Rp!Anv^4& zn+ns-A_Vl{pzh|{-T6moA~t)5<1jt*l#4YrOoOk(^mzkTu>~uf7(!Q?fwxi_0qqE8 zK|2Wz^NP-`ug68J6`f0T)~~iQzt?QaQ|60P+^_eQu#mh^!-8gkE4r&JOR4@5cy@!X+gme$-_93ZZ?zXhOJ`AhM8S@=}$#To-?6pB= zJh6rsPW}RCC=GUvf;EyB4A4vqmxCm}W+~p%l;zE3VN0X24;u8CMi!%RvZ+bsl2;G> zfa1^-I(oDBSb#U$E5s}4jZpFW>@v341V-cst;I#=>Znya6O7@2ElG7fO|Kbppl>KqQiu+ zUv|tZxo{Z%#Hp)3TDx_~4RiXp`70`xFYvhSnhl$WnhmyV+Z#r$Ourmowqo$2?clQ3 zLt5b`G(;Y`qivRe13=G-oF>0L1zJJ)K?xUU>H(iw8$L6`YyTuBWDpllePVo-m$YuO zpcK4qEBy`ASS~z0F4^W}!B zf0d4dlFl1fVj*l$3*bt=hG*ue8tT&iC-&G#j#-ONGH|F{jkdIWjVdZs?Ymz{ zl`jF_>NY>crS&)?eoYJ^E^=L-# z(cl!ni8?}Ta+sN_Y{oUqQDK7z6aZnbCqpWaq_c`q>|Pne2>QgJ5nMhOpP%A-=FtcX z?IT`0DFc#mZl5H6fAo^c4S?ptQj+3kdQtKK9D1b8-0fsGrQYG8izMzokfX`O@n%a7 zhC7)9-$-Y^_$&)+dK5YTidP6Sox$uuK+DT%oPpIee^ViJ^aiqhc*V=PYB3z$!1N-F zTmZt+>w6$~2@4XLT5wIq5~1_@m+JFWd&HU3;;)nhKbO2l)Q$t9RvCVED4Y8=5Y7D* zGicu3H`9lwej)L1q!D;*U7qi7%w6Iu8QKwwmi#ntCL^~ovu$yb*>7zIH$`w9y715*ssO>LAff6@JTH>^U7MOL9{S1bqm(@_Q0?*hpt?LHWA z0WXWMjwnqI6M4npLS{Nl_fBG__T2TzVx-P&{OFv}PeQn0)YfaO^(gdci0z#OKW!$@9dg%#z<~CE=eo{-avLngHJJob18gGwLE-G?h!Jcx>KmCWHqwv z=ymOK`0XXuff%cb`UG|eN+03iW~WKa_g`-a6tfn=1xSI5(K8PQ$4;usY{wFj#=uF! zaIeKnpvp7*nXt#H&4J=F>~;^{8cWXtS7Z+3MyAM)GzqKXdoe(GHDoPjj}Wd}1te=_ z%rSB8-Q<|FU}Qe5EMV@0x7b0}p1W!kPfGzzvt!XPugfeh3C)}MW~_`T8o5*n4~0sD85kmZj^t@T z9>0sT{stp7rfY39tWz@nILHD1C|_9YQ0_iM^|?0<#=_Q?Xl9U= zxLh6f!e)7urp#;%^)4MP>Eb&iOsWJR^slvu(3URi}9(Wa6Z`Tn;ke$ zIIg;*tTV8RKDtaZhGUfcKr~)zI@vyT25(0Yq~E<;yCjBd0=+_F^=E@0{X`Oc&$Bc;a>0WM{ZPbvt%E) zHf8a=LE;U%$eIk67D2~d9Nnu^MocOt0Opuo?~Q_ZH!cJiD@ITrnG?{>rtUrOttD8i z`G53ZQbNrlpBf+Ki3Ohlp1^b{(@L<4L+{__?l|+kdvajy08JcAZEhun{Tk*0?_j=- zroW*lnz{VQ;@Cqc^&@9l1%Wyp7a>Km20?uTIY#ry$O6*>M@dv9lnO4A1#GP2#N0Y;>A-os#ruj&4|J(p4qMQpn! z2jYuXMN@tF`7%nK`L7(a140{!i;!y{H99*YiFnP49eHdhGH5iwHpOs3aXf!{%_J4H#-XA>YRaFlAj3kxr0GXz7uch~)rN;yUsX*)>) z?cl9a5|yM|}Wtpd2k zP@EEkhYZ9+U8eb>j8fhH_Ngkd<}^4p#-^qZiyX1bXPb}8)qFN3WOX<>KiWrsKg%~P^Fmzy{4w_*%Ga|VgK1} zsyE`2l#p$zb2wJVbs}wV!T+@Xm=y-OS36;3VxdA;(0-s+`glc2^Cx%KJpAFSW0LqmpBXc6AFXw4?7q{w>`8`&h)+* zGn#7*I$T7~zo{E8LCCvf`q?6+)b3Xjl4YYI-MSq4!_$g_=?wbGVuP7Z!G8-2^T|~L zL#pG1KNB`m<+Q8f!0Pc}t$c$7W0CO4pkuWK(o!r#$h-JYNUx}PFKzpHP#$$VU;+H= z*d)?koL@1BX^M=!{F%?HL@Tj1>^(R8-QM#!HOx?U$>l|`_gwFL239`G(1XuFWs9=2 zmJN(e2e>;-?_xZb=~!1{b5N`wd?ZnU%UD{r+U9u z>9f6YU8331b+^1Q?$u=V`MctV8CtpNFS(CmI$-`RS7pKlD45kJ`OPlRWW|esEd>>^d9gd0sNqXyS2DeR6LO3TxS^AccR*WYKYOfaX( zLGoiWTx(IfpoEet~KvFP0k`tKbHOn^{QWRX%l?6!w=inGZ+q(>|sD$7Z&nmxy^`=J(I_aWs(r=RZ zz5tt2R%OcL`VI_h>B$SwrUcg#dO$~j5k%&1!7A|w;B~<>N}OmO1?j)Nf02NS^gd^j z*P}{ll%ssL8;S@kgjM7kxzJau?&R7)WmBXtURR;Q(&unS@YGth< zDj#l>Xf9x{PX~SkT!b6Lnh(z%j)LwwAG8vPTQag?+xQBfHO|twB}jOd&sS>hkjnHX z5CSjyis=;JHwU_bTUjrlr6wu~YC0w0K}mEe2Is7yJE1RRxR8EQGFm%dm#HEv-U$*5 z4PWB|=e6o{H*lP8E+>Y5Lv}7a2|51VU6B#qpGo_KH7Dlzm~SEV?gMG1*I(}Wj#z1L z5Z!k9r$3buPQbdGn90kX;wOcJ7ERPK`*IKtCx39~PF7aRHyI^n-TcJS?lh9B+SKa@ zJ}Yhb82>bIkVDdEcY3H7q>BbnJkELw8*2lE?!xwawOJ_U-6`z=-lZjUkphexMi!o; z2Ry;X_g_@vV{D$x>5}Z!PVB=)=a)|;=2pyXVXV-nH!Fprbh#CpDW`4%fLZDINNOiYaA=%xZ(psZ6)^WiGvWTwBH(c z#`hg<(6HEs$CBASiQmqIEmqAJ8awkXQL3VW>9OKFCgLUTr2OFMuEOk#My~@PaP0;m^`dhxob^YLV_^%j zQ@!tN*zrdc)^z3ziKm`913Gtxy{jRta!&R@WBFAQOp(UE<*C;p1qgeQ4*aT>z$& zdMTQ1b(syIuWqMhC1r@4pE5jEm*j*)NtB;^lWa{ zFy^rcaV59!rZ7K1w9P0K_EWA)c5fSH9TmVcQdG}$;8K6wejx)QJ+Yb1{)*pm<=H(LWc-wdg! z>}*Ac0!ezbyr3~IOf%>AgNNhm`_PMB9(tHGZ^g>e3#D}*>poQaOSoX}K%pq+T3 z0R^)NUUN+A{T?d#w00y$gNm4>Qz2faSAk#rdLwL$+jZKH3W>{KQ-iV3K2l!$PD!BM zUp*0gTkB`|8^I)UFHMq*>(WA@Sgy5GWiDi5E*<{C8oEr_DiC2I?s^nyCAzF6SPm;- z7qnu%=1@inIcY_;!2FRzZ$(cf9fr5kvUgK$oMBxo_7js6dlgK?bkP@9qu)XpKVpxk z7NAx?`-Aova`i&3TMdSj75zLLvu$0G(6>aP*`>Hv_%W()V0x09FKQKPQj_9%ElFpu zoX4+%%8g={5hbc83H`50F!*fbhfScQ1nqza9l9+e5D26@?CzZ|i7|f?2VRWNk)<+* zOnOl&EQ7~0*7!Q5!L~PSG=nglc?7*ydlKJh4mMAy9E5w}UFy#X;SH8e)!1su z!}<=t9nevP-AHF7)w>YHE!3A3l3q`?v757fD-Zk%Y#y`_9@mOnJ~!blyIx#i=z?P( zdKo;0tEmq~6|E_%sZIoGAD!rJ!h5k555m`ij3$#RkVV#UPLg^tZ%%?F9rC6(GX@mc zmi)SQhM+6#Y2Iyxu0ere<1@;kogh3v2;en)47e2I$|)Dczbgrv_R_MU)zYvx=K~&5isDAW*crex>RblaG7n>qW*qsY@$<;zKnLSqZ)V4aYqe_qUY% zT_Lat!`Txl_V#~3m6YVxhV>0Zh+R3Z{43l8Au9N?B__JxRLp^xr$!?FV+UpT3fucW zgdI3w2q&p1A!B*h@6r%fzKu0h39=oJE@P1e0C1wDSmvkzl>{bBFOPpW30ir0@$eYt zxeFnkff<26jKa}{%E*jy_cmRY1$Zr$xdt%Vav^L_O+*g5*wDi_-n$I=B`WYtMj%)f z6w8yG3t%HgQ=D3jLA06a=Cb&{4vWyLPJBw?#1Z%8Q11LFv6tZ_L8~+z2JUeAD?5{k zBaegKR={T5m2#^X$o3$4RroNv9T(0Vxkp2gNsm{8wPNgHJCs0YblK?VQshKv9*GYn zPR!ImcW9^o)FeE>kA?jrG!uq}lIL1mJ@fEEue1YN))fDHp};ngxl4X%MTlzK`%e;V zsN?s#snvtlTVU{C4)H>HO``Vzl{ki@D+rgj4@`%;XH6wtVFqS>!rlzmRSAQmHoL~H z78VeVF8(mT0Yv-?IfqG4PRIF@DeV+)$YB>Uum=?K5K5msGA(}InjSdEzHwKo4+ZYw&1G>f~*8Eyju=6bp$pt33v2*F`Rwn|3WPg21j=cu!AN=l-S=s!{ZpO$f(WP z5d#8Cp;xx(v1^%+-CX7JxFjg`Ij?%RgOF-9`XkgCP}^a6_fvwN!t`9~Fwkr|5HqUj zze=X;58y)#ukO<#Z-ka+VCA2cZ(Qq5W?wPl?Si>WSGW;{!5Q5}7Y(AJFA}5!nhlE^ z9%%98hy9W@9S`Tuo6Fx77GoYO^?SmsZPk&*pIIIc{Vx=rrJv7|D@`#cR)l zq7HJo?ZW$25h+$dfeGMJyp=k>2_ymnm?{5S6o84E1~?_(cnd1x`NTU8WYJBb(sVcV z*+Q--pI+NQt-01k_-NK}0JGD53MQwbm`;~e+;63~cxwU3ceVdAn6g48aMB~s{W`5~ zvHfq-ZE|R)8d0d6H=igxV*sBjv*(`Xu97HGlsL}W#pMQ6%1fXWoZ~<&JhEFxJoD6H zV%gpH-&qcjn;*WfxpltDl#AW}*O$IQTvssmwpHoyuer6vUrNd)chf(OX}_7S+IGvv zz;mHCX`a#5zn>sPEkCAy`i-_|IkGHoD=)q9fEUzRSVR(tm~LyM5(2%sq$!xu8>N8S z!Jr<^%eqy1s6mfm`{9!VoyJT0izZoveR_ZDFd+XLVvZ9HIxwIl>z1klG@}LJ^#Y7u z))=*{vY9w4wP*Rr3DZlNt;MzC5aNGc{;U4=)o&5s7i#)z;rGwnDcW7< zDVzBz##(R}qn8&t%p~9*a3k)Wxi{?V3RQ`f#(`P`-Fkc2m9XWuzfDfP9ObOI4a%lB zx}gUB+d4^fJ4VYSQHU(jOAPvgE9=v|Q8{ohKmW$FNL%vKe{LouM!WDxxz53L^EB zpbpd=xlN$F3Q~jRXkyPJkKm3gR{@RBU_BdK>qRCuVjW%l{YnRa8a|wkm2`<|UI+#8 z&AfmJD+ix|Zjzlws7lBhKGvC#8u;;R0-}<`=dvAYFBGmt|8jCHa*;>TIc1)Eh0H;> z26mO<3Gf&F$)I2ixz%8Wz%K)X)GZ|u@Gqs@TiryRzSODAjtv?|*=5!kQmMZi70^}; ze)0aE!zHM=<G5D$S;9_gFix$IcE4J3Htl92nYjO@`PfE>ZfIA%d)Zp}sC3lu+ZCo0YVkJ7* zf?EXEq*_Dm3Im!?x5n2%N1S}36*QT&|Mo!V^w6!l4%wng`DnkuFcP#hbsg^dGIDLU zKbSn+ne6-Q%Qdi~R!_F$B6hLN1!?Uf6Jrh%$KaC+IN*TCf^%LBM1balnhr?j*jUuiL}6F84TI6+XaqvLW$AfuGNt-lY0|YS&BA)Y@G0Y8s3_fr zLJU685+;GOXhZ=4R%o!r@I4ft+y8`i<4a#frR(Cwdh~QS3PjQHUv9?tew(#~h7sz& zof1%lUkir+YE1BJPMH$_5`spAn*I`u0=q#E)eluJwdye^luVpiYeeW; z08a4Kca}rA%{U(9Vu+1TKKCgn^0b?R5ClX9_(`161hNUQi|}Ey0?nqawHyA)bf|s3 zc)Lls8S>g|_yOj)IJ%=aDOEoNuUbkJu1>p%8*y{|*l`k9@?gxMqe>i&3k>U5fj7hU z9I8gkL$#I+FL*JW0jCohcEv(R^zZI}EkC&bm9ie1|L*$#4yhv{pW9b5eZf{Fy5w3; zLf(m&=7i%UzP-cL6euOU_cs%yMt9BG2+DbWYyCW<*v3!04bGCg9Iw4`6R@1A&K6^B zh}m!)t{+$h)SJyAJj;sYIQ7y4lN^C}%9QHExF}MeFX@=lvoNa_p2%CJFredQF)<-y?7qU7avReJhjDI?MP7cxsMfCU4#>eeadlWK3a z16igodHKap>efzCfeSJgYdmN83AaLGLg!s#B5`?#I;z^T>KB~O(My-$WK8Qo4KpmJ zA}sn|p^i>;;G=Z3$;Kt6)vf5zvi-P5+@{*KqaRripZeJSmI|KBBay<5*ht|@X_W)# zemz(z));CdzlDKp%Wog+|AegfJ7^`2dayOd$#O)e5JzqG%+rAUNJ$XKIQS`NlGR@U zDH&bnO&Am%P-S_As+ECU3MNA!czr<6zZse?{3oW#K&V^Vt-0l272d-TAAGx0^no9-YHB=c{m@>SKzU{4nRiVt+0rf~O9hM-GxLs?&fW#8Z`kP~A# zAz9$JwVL7GuM&)gcWs338Y&t7%GV2Xi@zMgtWa}(7tTcY!R7b1DFA;R3^XMD^mVX1 zG>ai%xZyqWgkJ!@KM1;}mum@qxSxL{Pj&yM3Ki~l8(3J1Ok08IA0aC?s=p= zuw{Y+=-rW^8ADa`{LYs$ZNPIYmA6;0=e??di)%9tb3IevCVt;Fu}V47A=r>B?+$9e_=%PNSz&m=5CN|K#E^=ti75x#=wWxq@v^~a zLACLyZj-}wZe_FfoQNT{cLRYYa*{s^kOjU0 zP-;^p?AUo6EG=FDC4bGF=zlZ{pdulL05LZ|xo;{g51tO3-}tF?3RtjG{E5kLCuoBT zFs=Z?;%oCD4h$;;k5T(1Bh67T4iS;=Ql=#|8rHGFq^D%zK*wJ7q!UpvG3@)vO5EQ9 zy>OKNC3p(J9pHNuG1n=kNoVY;C9sbe_SLFu!(H8Gb#81UsX7Wrrpy#z9wKc&P%tDL zN9S-t>`Q&0a>h)wq1m6!97t;bSeNc}yV>J8J>d2~1rER@@F|!CcFg7tq#OSBxrXcW zV1>b_b78|DYJ7DJ*Vb}rD2wNrN0?G$lA4lc_PLwRhKreUXv12O$aF-_WHcfMkCI zv8*qv2W`!8FJ)W9=&(o8ycO%1W~ALvvKkhkH$z`|>J+K}dw4-X{~ssurF7)?ECJ3q zbYg(J^5kqc(ZVPB?MqFm#rjE?-K+8_FxzsvEX#3AMwZ=U1K?Mfy9!WrS!t1^-mi;Awk z?feyI8=AmQU1HB=il~S1zy(QFO7jM@mp^zdoSq#vf}DR~zl&EMj}_we&KvZqUa?@9 z{j2c2g>XfQtvyP{D7+m1!he6n_n=2I7Qa#U!jD@_Ox>O_sR}17g}SQCnB|72zIoRp zmazSj!C29|Q8~D$C&V-biAwr^!JR80yt(j)>!L(dx+pj9%P~&7uMKe=*VHLoF+MP@ z2Wgy*?tS?WFPP}~uM+zDCw%E^ZEFu>(ho@*ynFGLJ&MePIaV)^;DlGfD~s3xFi~{T z&*Z7|!3^)xfZpj`8({}M;5a?NH^ti|;AC0HYe6Hue|W;Ti-_ZN}V|m*sV7#>O=eTzgR;vJ$Zungg56!Ye;^NA1o8 z-I-4)Ur8;-HEpWHDn^fFyz(@RYv4Rb*7U}Va-2iAjmTLZy%%xc(3RgKTwcnbZZU$v z5$+sn0DoQ`zY<&lG{hA^LM#bQKfb@45Saq3X+02urLZW@4+D^?;Q7J?s@V+Fg%)9I)0uX1t!ueS@Ewx^W)45hOKOh z?_&hmh4P0ReUXc^n1yYDc+uLQ-kc0Z08ZW$q7~hkO;T~Mo$em95Fe%v zG&VU*e9``7eLq8bd7I&u37}7HKrF}7%n@>>+2lbl{g*2LY_#A(A*3OACbD8mab~y? z5O+9RN7#WXX;i^di1uf=xLTJq>3$QBXs}*dq&Vf( z;IZ3;&t4r|vvDilCul_0=hB6~(OLrw39&oA+fWOSD35-RMiXom*p>0!@96mv+d_LkYjBAn3<+8OAmi<)iPKK<+AZn%{|nw!fWuhcbG3Mjz<~uR^d2 zyV$EKhPhU+6-)r{b>$g;v)xlfgl89sNoGcb{Z>P+pLkFfEmFvMAOx=y%jV zwA&9%GQbqT5m`v$2a+k4u;MgqpD-yW7PC`;DE)_uz?na;)OG`z^lvYyO7erk(sBgo z0@m*{=XYv2a66-BD84(lJae=b?c!)$s_DLatI+7I#Q2S^r;q58O6q-1;t%Kx;l!6q z#SWNDUXp}o1;xt3uYg1ee%{3Pb76{J;0~m5HcppKZRWUuuPHAtxWVUB*I+$lB%PBo zt~?l3tCSCh`vDk0270CRZHNWat^J+Z=`=!2hC~MSo;%|`w<9p^AVLbFhe?IHuCyC zUp`Nj_uk2YQ=SjX@y$C!6bpo}CH^03%+ReMt$}@FX`teO=Zn6k&_R@ow|CfYH0q<) zX48XrIXxkXx?@Edp!Vype+hWt$&-?GHk0(q+8<{gVOkPVM1sj>NDV@y%>4ll*1mlCK8Zqc z#Y<#Nrq`^-bmMq+l|v@K#T;{Tdu_Pss`;Lkw)Q(M}x)sQ4e+^*LUu?Bn3 z><5p$bC5LDHVb*_9JF>hHrm|77d~DK1a$AigyCqsWmD2PXE27(HXgsy5!qxE} z^LkJ{Q?yR#F*Zgd^C~{<8V8~N`DisHjTMBdGc6ptHuo3)mD+-suGbg&FnDh}z`uV3 z@hrrMzbuj)h6~}22GcF#zY>A3($H%98^7gEnG7BWJ(qf>)V%B$Sd`0 z0GPDOvTc6YI-pTq7?K93R+0G8$XiZGZ%^uzGC+Q6_`|#XzoXRK4}xT;c5l)l0;yi8%lvlPURBGzezNN2ioGfXH*D4`C^guD^di4PFxVKahJ;-k+7Ki~KJ$RDr) z(%O6`5#2dsF@D2Xprab6yb87-+*vGtZFsM#(Ii8djsG>w&9Rz!*F;Qi>h0^Z7^>f= zu37b%uLJ@5y)4A6|F=W{Q0I|C4&}liwRS0)KCW26-h-li~Hs!6}yZf|939s z(OQ5g`MX5oqC4wse!SmRGdjM z-tdF(<*u@L!L@dHtc6TZ4Qw6(&B7rj{nJ~}Ozx)^;_j$`WR0&_hhQDO9A!09RHtK$ z%4Gw%1h@dGi1*O`#TLw(-1EgPizyM((7PxXf9n1b&Bk4>K~^KJ?Tr(>mVTg^h(EOX zp7rC`FOM(c3fZ}$NmH_D*h^`qPHwnT_+WQpZaErhzQeneAPGd+KJNc-Z{zwU3Ekkm ztwZUw)}Hb}wvcE56z=&7D{T3@3zz_-wHP}XG@X|f7jm5%V8YITjqYgfAL{G5f)I44 z(aZYcdBR=Iw6bW}Oyr-~YZ^G-{D zb{8@`UBpflBT-x1)HTM%l5Qee_W7iW?i4VIbT0q*i5}$Vo_B;fGYS}>a+~+{qF)ulE z^kcno#DX3(e7{Q7UkB0Ef(q(^Ckno1;I9>PB@H$m+$mLvUN~rYc}l?2f=KuJ-j=OOUC9%LcUi4pRCNpMXPHT zi`}pDsEnlR8JJ#ZgKK=4U>QkL|8v_sCC3R~ru6OG#P-qn&mr8za*J>nr0DP7!l?>x zHZF}Q;AH=QyuEom)O-6sUZ+K!l2a;2!fByXSwali>a?hAr&N-y!bpa(Z(})8q=kyI zjHMD%88R8n7?Mi%EsZfVhGdHwyTKTK*IRW?_vgOvb57^}K7N0k$HVE7bKmox_v>|C z*K@nZt9TJXr@cE7dsVOLlf><~_mFE7Kk(%UBeS4i&ULRIkb>9zvCIIm)&NJ0SZhS* zatuKomz<|1);ebq0eoQ3ban|`Wk|$=Fz@p~d=;icfDOc98$Ao7_%EvX$`tHn{56ZL zpc;*qfxWbSG~WUuwCic21jIXo@L}rNH;aZehWmp5-C+M9Zjm2biP?>~YqLQnw7nG( zzujhEHD1I0uqkj(1MeA<*r)MfIO`ODg7R87hcf&s=(Lk(pkRrSLy^tg89lRZ_e4Rh z2IgFn8B!3Y(PtFVXZ(I23c-mBtb3-+Q zAY5f4u-V01l3q~lWt;*cMz0E2?Psvqzy&eCNVybR&dPb3Xsc!bWdS?9Lu2-Z_$(P) z_;6G6PdXc61m0LSxo+sfkI--9IY#NAc-!|U()Z7bH|1(ig-_ZxKqoSeWtsD*^X9(U zA#a7i#e(K`UHzeIFL23~#rJPD`=;9ZS_5k9N?mjvG6V;L-3DOJ1ErDeC1y(f(fLP4z>9Q4MeKT8zW>r8f0z|k_NT?s>) zS=}!h_U<>`1Rh246n_+Ul4Vndn>E+!LMlkhIDvzO(-fK zb0C0d+20Ydb%2QNfQjU!=f=O|jsGtb?mbFG8&6Bmbrb@S`;Stn)H58%S=xkhjgo#bP8+4w0S-7>D%gi5C0{V)O#qml!Vd|7q#PuH z+mvVtd!$m@TQzP)7Uk-|mJH8E?Z5W0{XWg|!pLQfb}mi>pyDjoh_Ib*0Tw@ z#zo%K3pC$(6;FhZWobStud(a!dQzTr>u-wG5jXsOShqL5L<+dKR@Yn5?;5wE`Kdr= z86#&Im)BwmW{*Pp3_3<+iycHkd|LvJ+xL))16}ijW0!F~7_#?9x`A|jcEJj0o)uaQ zVrrHT-Hhx^wawO8ms<{FfQ`vYRtX2qpO+Cyx5ybE4TCq`#8v zwP-4OMD#w+!hf_>+sQtc!!LBD?E3~e`qx190tg6m%D27%z$BUv&UeImbuQl<&xvzJ zD0#?&Ul7m11{N06iw=MM2Sl`X$FF&G$YJ}x5jTIQ0)KL$l})lhj3F57kZw-&<-hN) z2=eqXfRdB~MP%nbUVzazs?dIIq#Ax$u%!geUn$)MDrGDtzY^LHzn*KMn)m9H_-M_} zeBh^wv`AS_`AB|+h+}QvLgTv@ZI6_jV=b2k9?~cM~8nB}0Nx zy2;56RvZ5w487+4{0C~RFmTB>|KeT8%pUKQe$)0m;=`+1R*PTRd*Sh4|4H%fP=n$N z0}fS!3z)1K?Nw`^;=C>9)X}`pf zosFrDOW=5J`jk(ljR?#4UNSjP)b6YLp?iJVz2v*6t38J{6}Nn_g@hSEm|PGi*?Aqs zS#oYrux7;&V7p;Ql+a5CFvalo9zo=Ni=w5DC7q;odERiBRG zQ6r&?y}x!?DdQ6JRcMd)#W|H#7Io7_L-&ldU6qdaX)Chc>FRY``zLMMe*f!Wsxcj6 zy`g6>Oc4n@XVTuVBWgY=0mIeaUz+3p6i4IvhHeIWGtIe|6`zZpe$ifx2WsPtO(Lv8 zDx7THJgks=Ew9cq_H$D29At_t7TWuHu@H{+L=y~CNO2L9om&Mq=c*F)EHN4d71UM< z?l~etO6_iR$nTz$k!^u63Yjy+#Aod~JWUwz|6M@_a*^kW18Dy+Ek7FU5SmhNR$5<_ zLTKD&kORbeD2PgB$yZhDRaR&<0E9|vQutrSTXNr$z}hh*jZhWHq6#mp+;24-zI;Xh z!J-L~%uK~B>3Si@B2<-k)!ybhtvT@=EMfvTKGLRqj-@h*2cTV(Ru0$zr1w~=|B*Y9 zV(8ric02#J{FX?(*Ie>>r7mV?z0Je$n&rs9x+O`1vYr;%3k@B|tQkohd|dBDVN95LXGjyr|n@7-F;NfemU5>4`1FnEb2G zq`V8Q!zjk9Pl++bTSz~B(E|Kwdd$uyJ)nkKHJm}HSLbf~EfO%XvcqpQ>4Wjz(Pm;9 z*S*5K`2IueYIkYz+5Cvk+~jOhA{~+C3VU(07!Vd|4=Y9BuX&AFf=`e}`0q(EriCdJ&X>0rizRPkmg`MF zVsF)R8J&>qrKf^~jS$f&RqK1U>(YRFt7q+fAjH1^Hmf(tYLR|;6B2~ONR;4;LRJvG z@PSAq%9byXaTrjZRiO8W5TZWLlzj&NW5%IRYk&SzI-GmNho%2?ri~%djqdrCwsaRe zA?2vjl4oAqB8Or`q28tb9SzrKLf4}zRH3|J0u0*if!{$$G2l6fZbcHC59ux&u8)ht z5sn;q4?{pB^^+j;KjXuzd@zc+^rD;JyRI-TbM9$M`#S}7eVNZtN+9nftKF@rb1d>2 z0=qoT${ue>e<#wHqQ;VG{uam9P?bs>h?U7P|EH?9-%~}}+*IpkX!+C_>>uy8uRzhG zpyWYd6C6ayWp@er^JG{_h=|o!Z8EbGg;<8%84WewQQMI}w`>1s7XqXo+u!s{sAC;q zWkY%abB-+TuJfYoFvuAg_IoX=VjuLfWjw-=M2~RF(RV_aXheL8l!#Y|2dQr1t|(ZQ zd+^h$T(2zT5cYq42{ zOjwOx65LCWUl7kJa3YD&U0@vqY?k}WbXUC*0H316B#>nr8-Xi&0)k7$@VVdxmHaaQ zvWUSFJZEX-2ndOg9k@1BUaa*>D#GsAm|cqUf8s5fw@G6ht$AtWRZyArY#j12wFJUp zlo1;&$)3{Qx_r0f0g#!#3gw^1b0FMu=U3Zs*_vVUzp!y1d|b?_2+#TN0j&}$^Yp&|lDTlFM+p<2 zWERTA=-~(5pS34-{ChDKN|pICupWX0&$`BQ(!_R!Zx>Ygb@y<9^{Bo1e}Y>7)JA2s z{@(&s`UqBe<8j4vA9%?76s|)_qL5z0I@j&|nSlCJX|3-94mnATMCZ=^ z=GMY}4y0s2o~)TrV9p}_17eh~!vu-0XG65e&LQ8F+lxX`X~CS1W1(Ot1++66;#A9#WJrA#VLS{wgaJVus-UxrP|O&(HLX3 zM^Q~CQJ*d7J~Kjx*2fkcJa+;rv~3>PXTp#eRfNmx{)oYm+Jo92)*Cm_BEVz z@D4{t(CcJ0r2UDOg!UvJngZPqsCR~s!DL0D8=WUX^g-FFL5R5!}y# zh}I#N_v3WFUt{!jg6gN}6EHIX-S7o6>eZ;YDmm8I(c!bL6@+ex#1RhRZRu0~0TmHM zkko!-9sPi&;ks!zm8(;#m9TKiC{yR&Z6g9=BvJGt3&N2R|G&^t?mc zmnCVH85B`XT}}7@BXr%hi>FQFR~TrJPRLq+Y*_jfuqOCnr>U9VNmdK5tAu5}){~Cf|Z>(4PLlX$&@3w_<7wCclbB zs!UOI`SYaJa4rN(UV}IkNGK$O5efSEWxTTTR!E2#p7h;Ku{U zvibwY+{b77%lZYH(j=k0;z}vz^qu`hB~r|ZZ8#SJwmHNxsG4g%DJ?dM<;>IsIr9`} zeJMe`#teZX00AG~CtLUn2RRSrPG5RO8)ef&9tVvL_7x7PUd`e|)I`{Tg}>r#&mb;d z(ElDc9VEu?%aRNHc{1@8Z-)6kxx~E9hvmLHY%ZPUzcvUZ^_uSj@SN4yxs+&Nt4g(a z^Bwyt6SE4;W~ZPt7alGcpk+oh*5P-g?`(pcJi=8~VBo(vHn)BXZuuZfsnytdL1FzL z0Z#R4nxi0r({cG8S@^=+I7cVrX5f-VQ*fo)F$l=5omcJUK@o_q2y8f@$~18zeWN%# z`3<0tN>-SeMSh1M)A6z@OZ<~XtBF6YO2Pc57+KD1s%7xKgPuz$n5cv@jvQ#6YePij5WF`uhyk4%_z&&JXc-k4(Hz9$Msb z(YV<^U8;{-HhrZ>(g?czxi}YUU%q7dT%d~s0=71T0e6BqqX@o&L>$rf8^e);+W*8ygp<3z&F#uxjcd|Vi0|$+eM6=T2n7B z2Tw`jg{#ig!{S}RA_q-J1YLm0PTua2ZlO%R0HA|+yN1Sm5+vAA=HoUZx%BVD0?P|v zM{;|24eZDf=4pW)68g>}B#mFM6@nFZj3wzhk#l_8_ zDJM-}!mc+Dlemu$tj&Ry3NnzKY9QI8uXaId&y#S#b8%PFrXIr0tEq>@f;uqb$#-AU zCeJ=cYrZoW7@2gyv9+e|#s#``<2WVN#df?bfgL4iQg_|#^FqVtM`nz5C#3hTAOyX7 z&+cRsc>~kgRBOdRW5=Xif#LYe{~Soq@2TePx~?eES?k|85jO6eqX)og z`*rgZ2Ci~UeywDJsCM@sYb$_xlX(9hqGoY#x*(7G^DT*Dlv`;OZuHCTJqpIluiWAy z^|owk{)FM+Kr^2h*&Jfdb`~KB6upAFbtPui3#$j|lgq~2rYQX-oPoeW-JIqw-V>_# zq5J@axc>k%1gCgq^KL+`cMT|QX_Q_+Ti06MF_1IfCHm#A>aQ#5-ik2Be->81_>UN= zyJ|I0TUnI@`ZXo*} z3}m)n3}iQ+(u?@--lJY52WATdr}qk4W(%DjVfR*c>hju(6@~JOnp%?uqwmAgf*d(i z)WwL7e~XRTo@_Ho+^5*W# z-K9XQ101mxB$yGLbns3 zM!=wGk~8uUqO$lCW#cJ@)h(69?K)&V6zk^Sx07j&z+J#~${A6Aht`Cgae(ff@#% zePe$ji|wMT0Rix69B{9X=z%>WMWLE!h*SpJ7(8Z&ORC3Fr%MBF-$F6JUCrj&c2i0X zIKGwuD<{8mo01x0VS@i^QO#o>%kir84}r5TE4sRb`e&Mo&+-&!_#M)wdGyyYSA&LK zBD&y738rZBS&OX8eL?W%L0dVU)JM&ku~BcF^NTOk`d^)z*9Q?oj@7!06D3^uEUnR|_hd z_9Xb9|LX+$FQ#!6)E&V-Cz9#qvQI&AlC7H90h%faTMGz33msV~q_sjl*;r6Bv|c-KN<->M^zM1W7ke#! z+PCkg-~6k7GFiQHWyCe*H*)h=ZWax`NZ;M{!!Mg9ZuR@}w7i?vJ;s?fjU4y%_RJc4 z%YVZ2W%JA&sgKDsJ_OvX-z8fVor0rPM^Xw=G{eZBi!aLfz|PSH4@wxc#iuvqGcXE!qDseWb+A4HO4D7#*u=W9f-bX11tkS z{vHx45ELcpl-v0tx&r!9pSqpfqqd9Xhm>#*Iek8{Pi6QCPh~_@a%{sM7c}a0(g%21nunp_QLA zp}+3J$-Uekx8&&=_>3TFpjn{0HrGBVaIT;m=$~zWVBi%FpV@-udj547Sm0yE!W@VJ zcWg+I!8VZ7;9`#A$WnTP?wy;%j8ZM zeEDKo{*R7T<15RoFU)jV@4@z7s7ov`6{L2JrqM1+aEleKmk7o+=kH1vt{PXfY`{C` zyB~JRnf9_BP+0x`{=QU_s+g@Mo|9lcwd%QNH_e(9$tBRbE4>Kxh)QgD^>~h2OFEt- zq!-tp)_;~jQFb6u+>Xfp((e;p?pz_8M!sXBLQ-Zm-pYUP2-#?4>-&8~Vr?#l6zP<2 z+=}Lxc;0BYN~70orS-L9q#5TGTbxll82eF7&B^{am+z;K7S1ncoh!SBVwB|{iu(Z* zHMG#S|HjG^)wIlBg`+iL3r(X*X;8FGmA5Pi#wT3ZJ$3q#xox*Xj}SJjwZi7ECa!qu zYGtos76|J+#DavUBx06Z4O(`GKUHudn{TFhD0;Roa_vywd{TLnYGfQY#A0^WbHm6- z#TaQ83%gIo@3{C%xj3bg(B88-`f&rP_6FIuvJ01`KPXqQD>8>ob$6( zc(4_TO8V%qwyp#E|^kX>?0`f2;i-4G5zsqRtZxrckhMyJp>`qN5t|tryu$ zflx6!X}RF^px@wIs>;7gW3NB4(cKbEXYLgr-ue?0iMug3N7QY(LXOE}6ghY`zdKGq%I zf68dsAih5>q59e8wMG@TG0m8=v|Th?wqi+~{~HveNrD?yK(A3|=(k{`hYdiIbegE` zNCePGhYY>#TQonmz4d`G@9nMQamw^={n#fJXL_%moYcxlcIE0u*1Ic|3F+N#pU^0G zEx4BT48G@;Q2|9a${#I{>mO>rB?VPPg0pMIXq912&8KCo^&$+8an%w3Ivg)MRk8t@Wl8?ucF^@*^zk~`}*Q9R~l&(Be;Xbt3pqU=cJ1e+)W zIkO4m&kPMb<HhHN~8#_4EoE2VA*8X3Ie zltd*78{7OK3v50Rv+gLCQI1SzbY@*<83beaPHIDrThF)_Ys^ z_QUWq_L&V)@T(I^Xss+oL0g3p<#;b|@@S93w6VyQm%WBqzciY8;Lq@(=QW?YICY)3 z3I?Pciyc%Ynx%?uj{br3C*t}Ow8l!ND#z;+XMQcR6=P!*Rct69;`{6{`KBbglnPx& zRCZZFZ+0Po^~c*C6CJzUS+95VWS$m8MA?wbl0#dki1##k9l0@=;M|UWAmmMl z)nS89lcAOs#oP$Y6Z{{>L)vY)g8)oEK3scV10Yok;_Ob~xRlJ6ct5Zb{x!t`C6cT6!!CjNb02 zmn|>&q6J7BeHYJ(4XAm3i`d(U=C2zq4Z6_!aere5ys`s3m{kGy@`fLj4DgNTWAb*l zT8K5fq*vhjs>g$KEY7D;y+*XCLhq{Q|S zELsj|cHK9)*t`QiFf6)tBuKd5vTv|Jbz;(Fp1ORhwGMHi=r1f5X z)-|f3=&A1q8VmkdtWy|IlH0Z+KbuP)C&>`uCF=qX8oLH`%ssfExs zEMdj*-&)Tz!umBn?(X7>P{+DgSp8s?MR)0rZV&BeUHZi$`r%trSMUP^PX`6TM%6s- z!u(0sxi5RxqiDLzIUhc3W3|_U1An7{rWkmcDC}%f@@B?55Jq6qY=(;IqU(?6ToLx3 zPfRo+(5Q4BQj^s)7B`=sq{=uRN`b+2L;7>YR}wdv*S)HIhymB|(MwCz#Eo~qULn5H z!losjyRp;%pv!&-M{-BCmyEmePx-ff{-=Ud~Xp1+TI4u(Xc?dydSX;+a_ z8Iz=hlpMJPxR0YJovHK)Gi8%tMG&&lY;r4{0;nWmM!|xt`zJ;9DoMIBNq*4T`c|^rTH{ptwxFtfLCe zQ1PgH;qpQ0+Kgh4V(x}{k5RWz#;2_Q+r=|Eynq`&S3MU>CxF%4i6n+0^{Fwp5(9LB zCg{!d@=Jj?GLo$!noGB`C7Hr^RnhTCm=_`Ay*fczLzRu`#*jONy;vh@@QX<_sG$`n zFZWfQynI|-soHY_u1W`WV%*D56#!f1X3djSPIWw=1{bts`tio;D)uaY3SGu*UIYI`G##$A+C+1eTjD#%BHcyH5 zG^0k9o}2I?ZYSMP1MhH1E+HB*Y)2S+63UCLgH_Dl+R~odm&13({7~(6hi(NIMjU2o zknOR2kcrF{QwX!=r&2)QpCR)Y?zY;P9cH&n8^oRt`ySQpU#dZR zX?|uB+_PQe?e;1P;q^zLlW;eHkL6r}fd?iVcQR)X`7?a%$5Tetu{&8x_A2t>+jS~z zQJufIOS+fc3eRBziBjbP%|-D7JQvRS3m35+i~ulQ=P|^IN^sfP$Y^?(QlpH)3IC5O z=t7FEIGVq0lra#@ZNU2dS^;l)BYpzUKh%Srmf7uRL2P%v*`K2mZ46&F4VsTzH{-WP zQLn7Og7J)j#Sd%m2CTXQV^dYLLP3`w7`kpdk;)9b$}g6`aDWn%4uVx9mV1;z_*-p7 z4MQkMn_+Cs*zFZtD{*JBUBGcXhY0_uf&`zwy`{Ea3_j$zn;OHtz%(D{opIXeh0H>C z>~rL^X+}eDuzEDa_x72avg#Pk zwc^9ElBH2mXU7|CX+t|~^v5-9^rg_YPNuXA_&zLVb?7Bh0UcYBOCZ^ALZ9dAE=M_QQLqoEJcDJhL z3D2MoJBn`P?W>D*vvk)_TTM9i)Xefqf{b}#+$!&PvjctEt<$rr6THz=ztuRLcFH%A zrHr9*d(2=zn-yhJ>ds60H6JZ>PM`Wwl`TV|l!$KK1uh)lu{+#69r2$me(Cf*_lADW zPW{z-#?z|>+=^7EXEq8I`z{N^yba2{f-bVs7GK$FPq;%)ty;FlE(cbNM0JrPOjOn? zF$((4PJwF2xdF|WE5q>45G5tJdZZi)F66lX%RpR%=e)u2Ubq;`o88_Djr7IxN9*qt zsU`Tlbe-vtO$`upulmrecmiqY<#P<_-OJ*hRNN?+l5WM=yWeg5t^9%(RPF5=Chxqt z7h7NJ-__)YjEOlm5{nC@S(DQGe%m91TU%b$v3(W+5^^C>eM05*@THRCZtU`zfV}mD zfWZzYF=y$)lcX|VMkvFNL~WPwmqiI%F)f4zW>`tV`Cx@JO3x`%b^e${Y6i zZP48SUs$p1QvT0JGMuUx9g6$d(0?78?)?hZ3tU)}$Ro7WnppSDAf_j}K!=4vo%TS6 zW(Bx#;0bLPv)lMG0%;2{XCFCgsM>6A)c*Z?F@fvl`gORzUrTVSVEgG@nfzFjE$kiT zM&-gEWRBnGc$HOq-KHDGaW&wEsZCn?&3%A_S=ut^TwY2L%Qxi(dD*jGaV9fz;3SRO zwB?tekySlH(mzhmpIzsvQIz@KA?I-5HjT~zKaar|-70n1Vqw2N#o*S8OPcpnv1lBv;=rqjz`n@fpOQ(lrVZMr#^Cu8FBkv^BVPcRal5APRdte*$M?-_BCmF zGvD>dYx{K1-u{)Jm6yh@^5#xkU6|1QzJFww;*+~?6;l?{Y@NEuz55MFZ*tA&J5QAQ z>GL*a%}YTUt@$S{#z$7FO#r-8VjUP_TO> z;riyouO)kCI^Hs`(zGD&LEtZk?MD@ z$Ij>7%O6cM@CxnK8S2usBW(9!TqN2B{dU-Mnbf+LdV8T_UG_q1Q~L5i!)XISv4Vu3 zW^qjLc99Ba7!C~1nj|{r;B!!O_4fTxEQ})utJfoc=(8F_ylgK$dd7cdqXsbOHhgC+RB$4gm|s1*;Ou@5@pmwDrMr<66pM zBMk``AncWp;fu+KDtdIdBwXt~TKH6ane7MTmiXcPgfdx*iG$S< z_}M1~aI!Ekxct;C!0B_Vjzju1iPP)-vLbWC&<}qR!(uA#0&zksHicKj%p{O2C-0 z7cgjKQh_pK8H4wJhb1cp>R87EhzG5#g`!OREEmVtA=we=>s zTV@VQcu)|bvgXZ-5#Q1VV1b%l^4OT<%oYsKpBP|EN}0QZL9HwX@6G?x_~c{poO1a( za{+ry%rYuag$MmSwx9E)_{^YCXYD*pZFx*jk)@scPR>xmLU+p#0J+StI)Vj#UL1{hfHGWQ{#0_hd$xBJ#xhY3mZf{Xy__wOHSJ7cgcU9lfjd8Bt zt2<%eld0o0*f*BmH>=$-GjB6pzHgUN z^~sl*?i_ow7cjtHa(L~+gM}Y}Pw=w=JRjTi3iGetT;$w+0oA^qhsn%nu;C(>}IR+;)E z?aigMU0o3p5^;TmC%T{*Xby#6X2I_pM3lc^mHtcX0!KYbg{c_k3i#7EQvnKge)u+n zG}JHH$>|pT#|PNcwFs_Shozzi!+L^3SSTgd_Unh>Vpvo;v=?bc@Td2mis2obw7jw2 z-EyPmNFCOiY_h}KzKAlz_D-_I_O^$xXHh>!zrSD)T}SA0_|;9SFhD@gho^=dD=Ww+ zAeGOlWedFHRhnGC8Ttr@xz-7E1pq+OF^UI6+o2`QYk`{vF3-zNxG0EmM&GM+~ zK+Pp+VSd4K#Op+KmSlS}@2-zgsFd)CE>N%<*1yA!@;Vk*`!lcXu)wn?Ecs&VN0qyp zJW;9XqS0{*pUY7u&AP4OsiNrW=$1h1#IYFQmAlL}%Jkj#zdW2*69~cE-9q?T>sPWe2W6YMT8EB@qH~Xze z$0E2n*fc%txkoCr%($PsbMYLqa?r8EcsKFXd@Q|dgtXMY21Ft5;=u2TTdPcvhwbYU z`Da7|Yo}bPuSOOtS`B`6Nh_BApLyu=?b@g*@$Q+C zAGN#P{9TTTM5r*Mq4z1Mw(AKUyKB{*swZkJ>&&T3$o56l@r@O{ zK6&jQrX;d{oIW$gR<;}OIkl)Kvf24rNB5(n{^llEI=U-{&3T34TYl|| z3^ceiJ|FL0#k*ZXi;o+~5b$!u@+R|^B{9;WTh`ANAq^qnpF51)$)`c_z=w4 z!In7zH_Y|!gtX+$%{A|!CowMSleEm?(qe0E@jjBSq*nho$@J&h0>&vwuaRgS9IqpPAs9FZO=QP@0G}?G_hdtAjzy7F8#(MPJcOw&^M-as6KPU* zhg~HpwpF&JDhQF|M4(t5-Sf_44!}v{H>bkyMwcgj;!4V`&Th5pS_ADwRH6@{;t`OC zSM7C-AQ8veR?0#@rcMZ(9QWcA+O4|L{0y+Gpull+512Y76U(x#Q6`JF7#Lll>qGZZ zdQG0*eNEms_NI*HX1n|RBDz&*h84V8T|Z3V`{#I&1?oGRj~6Z$ymP##$qyJ4)7N1! zjdx=?y>%i&?7lp)dxgSYCeB06`GwNA8wgtAzh5(!1@#eeN3QUli^@h!WEEcK zY~L@5D86V&R@1<-=nt2vsz_(CG7@k(Nxk!4@Uoa`rLZifcvFXYn-s$eOQbqAKEW?m zQ|P~~M%akfjM1)KH)leEfw|VL%1c^};aX7Be9m;}Ax1Bh0+h+B+XKhrIU09bF!r&W zgzE8|^gxUM1%(l-dNUfr>t9`&D|V=e`63HogsjDi-(eT!zDklWF)Vnv+*`g9*nn;u zXpZRFtJ$P8$HgP^hvwRoDutntvt6-Vb9&@JYuzYUe#T2+z5Qe1WbziZ)~l;-x4g5s z5uL#mz?naI`Koe`4GT?)h#}0+A20Mf%!`tK6N6AK?#Kg#X3Y}m;JmZ|twjc>$_#Py zIIhDXiy;Kk6^s8EtLcofB~WqztbS&UVoXA{3dOMiur=rGXK*6$9FVR+z(^ImGld$l z>uyo%BgC`tJ_R3>TxMmj8ED>t4bOY!{vPDdC}+tq3%SDq;hWDHY&!h^iR zc38U3JmB5ER=)vxopXa51t%WXVrX`6cEAOK+#S-P)n19cMT3{%)wtbvFIw0;{0TJZ ze@nFxY6qNgY%gcL7p$z+Fyqz6ax^c&0r_%k3|zs(rQs63S9YO9LS_aRB64fglW)iN zHl%N(Isswo@#aRGtmW<`F zWvP|JizV#{S7WAcb$X9*k9lnOck5&gmb@ws4Kfc<^rw!Qol8yMX{UpZIjVa)XAioX zSF?T;HM^GVu4^_+yK{=mETIv%2p54XIG+1(HQZ=o7B6jMuEkz6%A*r1Cu`rDs}Fb2oWW0qfdGprQ$jJ(Kz79HGF;1=ul#N(*FprTOVL>`y}T4GeW>A!HSrc10d`Fi}WZ&6EFq)Ui>6 zAd8k$7qHKYmc%F&txfV8y)alPD)yXRTXZh{;w-u^zQpmluWps+iARU|YXNuI>pg_( zoAom(tM=bA`p){hQWQQB9v~315eTDWSRe;CU%KuwI|y%k zwmcM=Bqsy!ISqz90K7m9eFgB^AgIkiOq;=4Xps8N{IcnU78gZFVxk=~`vmT@A(?{` zH_@gntqBbS6vLq__M-(1O>~$#4V9nTwj+%U&{4Sw z@k$P48{~O@9+|peWRh{O7(C)7S1^qnLL$9p2XlMNzw|XSfR;A0-Wu@auY=rVsbA90 z9iqV+;*F_3HY#i1yh(nh+UcqhY3P;SPM44?iUdr3+%? zz;CU?i-0G)q!dMEoXFmDb|k^^MaQ#NjN;P-IASV9Llvf_^~En*fV?NPJCm>M3LyF+ z`(#jM|1!5%{GKGY(Y*Enbh2==wcv**ul2NdFg(K#^FMG|vn8%wty2C@k0!bT7f*45 z6zCphz~afw4N_}*fj6x=cr(NvNXT>#-N{Iy&fJ=Bgl2Lei^SuNhwctUc6ExF=$Ax4 zUxwCHW=fnR(ZHA<{gDh$aGAv~JGO`htAtg%vD`D`6cUvHp<3FikGTUp-1RDtUX$Cc zB#otFtE$RB-D%s(ZsR%g{j7ey5(9y|1q=MH7MldMo6rLoH3|X6fKPHXT!{3m|K9a@ z#7RF;8H{TRx)_t}SD523-Fnqn=e+&0nRnI3B39`&j)$?55}WOE+_Cv1MME)liGn>M zMOMfCmlZ4fC{5e_h@x$;sz8{m*#289qv{Lbkj8UE*!Vo%tfYnj-vPs8nQ9EBzugqs zZROHK`G2S_=VT(@_{{P5D1+RmjGOIN09GLFP#(*rc%yYb#hG+9?&B^%khiIyaXVUN z72m&03XLh(vB#8`UX!D5*ec3`y}!x^W2aCICHuqJFThQ+{3?oL9m7Z5qn1gWxs`s! zeEN7#o|Q;;z^YMMTxjj1{LYnmJ{XHuxXnzHUSdXk85dRTL2<-9SGGQuC~Lgf`VvpR z@cSgcQSb6$!F@{5f|;(W#&+Uk>5F3%vGr_gG?5ibyIVY|)>9+E2&{{@6}1junpZ9< zgYN@f*Vkx{1r3c`xy5mwHSYY_CH@Tl;p?ABu;{7Y8BX5BxL7^Dfenm8$=g| z{QmE{ur1Y|lIdue?*ujn5KA~5>c5q=_t#FY< z36zr~>p|yQdeom0dfZO^{p;lY1-etNX%CF^?zHJUN?+(s_E~6F80mcOb&&t0yo)#A zFL0?drC#B55icYt7|?;HS=G#s?*qo(m(Xe(#T&KT@B?4>P#rmNbE(G)<#&cR0kf(j z?#14xS~FYtL<8@7=voAV@PMY!4$!eqM6EOQhn5UuM^2YaPyzu1T3kO z4Inf$k|7K!aqb!?kb&lkIpt|OlO9)%KSD9QuZ(YBk%NI*ra*!d3p+=CL~Rufc2Z9I z?V6m9Qu2aPB$JM4b%@3&hrmC$Y6ewOw9 zp)u;Vzhsxt<3C!#z%DkIj5^W6h0e6`%-@8*mJ<7Nu$D zPc;OLA3kWJS)e4p zhDD$uT*4NGKbkE9#Q4faUP6_a+gs-oJDraf6+3Zd2FKpn-=k0+&H#jSw~)P}X+3)$ zHFeqf*jC$YXZHe3Yp+$BDWq+vkZix1)B^*|U-PsOCzK9ACRN+cw3{G@rkM4ispY*m?otIqJ zqY={)l2YL^o$w*w;l`d6=$PfoZQS#%%Lr#WUBa*jQVp$`yNxS28 zrSP85pw)59b z6GOyml51mH=dLE4?LSYOF5{2xtTuWa%lV~ z_3x#x@aPA<5r|mn%e2=Qt9hqtYpEXn>4zySpb#}6bjou@+APL6&=-bI4uisNt*u9YqZ>ro4O8;6&-F;_ui#Pj_;06o z@k@jNSKT`nquh`;VO}Sqt2Lp8YJYAZvKve4z^ugFXx8eEA5_moG4$oS;n-JU8mr{{ za_w~TmYd#gyR2RDP({d8u2?w9w|~!pSNuUM-;d#gsbi75Tg={0yMM>GjTt+mQ~KCD z&Gh{2DYNp#Wz^hu{3C^pdjq03AdC;pg{C)Ko#E>EFk&8bJfJtQtTJ4gwPQO26AAK| zrBRm}5qS&*&L)t%W#d+5;H=ybfay?tpSsC~{vF9ct5^6jHb?BBXK1}exS#Z-j?D3E zbR#E{%5rbxs__<33m;`o{MrknqWwSatnPp`1RJmnI;)O7D>valWw63(9&@?d9rDZE zC4>SwY{hXkJxEFlhr7J?eice#EaaEgk568Rz0+A0iZ^FfS$I<~mn(=XiCaQXXCWHsQ{L9cb*g<-*d*yIx^wQ2C+hl8|w|mRGh13&UuB6{fN$s#B)kDozVH))fmQx zux^zT3Zi=c&yi~|`7!^%%(A0RxCd+X-5lgrbdc3A070hmZ=9&Ru)N_ha(8WW_I(LV zSPai88zA3*hnaBaiXb&T%Z&eXVcUmI*P-xHM?ZA5eQe_Gy-{;sKQO)8>q_2RCfmQU z&5Ut_v~ zPx}T>%p3}(4>uP`Q+cE(%XwxI2qUklK#P;$+`@A@z;?T?dVIY;ylPeB+hCQGx;seB zsyug@%z>F5Ot!-ZB7BCS(Y5eovwXrMY_y- zp}1Sur*_ZEB>DQSgjXO#J|a%&NVD!5Q3AdNbMgw7k^N}79&>{DGfz(!9W${<$^Gyk zl@i!-*rz^xS>_dZZVp^uxbVBr=P})1^Scn(PcRk~AkRk!ogN(HCm*3plAofGJ`HfF zZpZ$T&c8`49sR>Ag-M34A2(wV~J29kzc#gR&vgRrP^O$;$!g3{A z!gviqE&NbT?-WTD@Y8h2+WnGk_*(SF)4c~4(qc(zl!F@5t1N(Z=lT#W%M+F_adun$ zk(mVQ?Wm86CodB6Mk#fXgy01LB;!vTk(R7Qv@pB=ogkCK_bK?YraA}vJ4A97TEkKW zE`2NqV&YD^d=7D*V9a#4cb86X5LI5#H;MG*8Q+Dl)PA4waQm`B87$&9)7WHOx!%`q z4?Q9W(hw8=o@W-(o)bs393@R)kcwb&i>>z7NU*A{=* zB;H4&ZESw9zRdq}gfi`weqi}9t|4OEh!Q1wYJQY&0n6-?ab}@Vl2`wQcdx*soh&j- z9wwAH_FZZ*>Z$Qh7qSk~FD&6boay2#+xevZ$Q#}Wa)g(*9><+Y_}G3j zg?}CTYZcRBeQ$u82)$PO|C&&P)=8M0(5_HKH^SyNN^sT_0r0duo)cq7inPDbPH4s` zDl;T<>CR_!tkas$fz|A>8q?LG21ag)esZ@V9YfR3vLjmFe)cHL?j+y$rEgWk3$FRjgkxdiL zdol(91S(%KryW*-jfFq5mj>zbHm1K1@WCbqY*_EaK6$fA zYOTB5a=*vM(*D;A?FH5;`uvvJNjMh@$y3Mjn->*#!oSFJm3ShI>*ueYvz< z*)2ga^pzT*L71|Ovc?}Tqqw#T>OxxtbyTZ5SQ*Q-zd zv?-|JU36KemKr_r@CXcd(Pa`Kztx4*nE53*4d!`kUjxCV@XBhzj#2Y0Nq+_X-PmUx z7|;^0Em<61?M_%4`QK=_i61(9dmIPJarV2!27+9tHs(8YL|p?n(bHa?_Y+2-3(1_x zqRCicIj<&ffwsx&?1445Rh6BNkCX3cOp*M}tmtT56^LMBfiC4`*-VW_C6ARrqdpdunePy!(&gvbzN1pyf$31LS@!cKq~ z_^xP&ecC?n)9;`Du(hRz`#!JZI@T!|Q~F2ur?9Y6Y|#`J#F-aAeGg@>K_vpa^lug+ zZaoZi0h^oKrtXn9-0jU7Pnw54izs;VkS`ESI`A(t}7!>P$^b__|xFTG| zqjISA|1C|N5;rLK;x&k{QsW!zZuZJE?I^(rnSfl0cDtLG=#9i@B>(kEZodtl+t*zS zt+TFZ1-k%t7ABr|dTcuF07=N}TBC2%K3fwfXNWkikt?*$ZwXdTM?qHiFA|l0dK8 zYI;Usg)RX?kRYymGz<9cpTv!n+dG34vS@{fQ3Ck&&({m~)v>&3KIyNT5VqeqB?M@y zcuav`!D$3xY%R(Gr7M-h(yG!u`r!<&dYAZZ5i(d}a}6V{aG*jFWRaCOHJ;H-Y}NhU z4NY{()mdhIg$c3MNlkvDOq%DRW5c}t{H|@Y2 z-wwm3&|arlR?V2{oOt0!n(vyZvS^sNv)9&VUdt+O?%{ZevUDJ6UPY{YNvLO>zgD@L zl%(7VZoos1Bl3^|({fUGC4Vt&B}@jgkDp2Y@8RWN^H;>%n*wi>-2{QW$;@GpW| zYch$&b&=mEwLb0$5d|u4-|@Puen97#Ke>2xAtsPCSVOyr0aWNK6~?tfAk}FO3+`lZ zLH@tlB6D8-+OL-A-vLo=-hqmeBbl1WSmNp#BD(P%foZ@0JYH!J=u{3XBt^l}Gs{$kjkm?MFI8>*$ zC^Cy`82Y(s&1Sc=+t^ z>55pRI<4Sl;%`HCh^1#ADFFTf|FV|ICeF!Xip=1`_=eezG%Hm0)xeqMHH#IQS4b_9 z7?Z;a)~lrkt*V$8*1Hn{kkQfyY>ab?Gu*1+&1b^HqRjphwH{owpGO?{(4|xxf#@HAE@gIC2H~Vh z0gww0Sb}4vW1k>SZ4NeUX0c1py!?4IE%7TviW$~6HCPXaVa-8E%)p80c0N-x0JMZg zVqz&C?vvlaA|R!uHMQNSB95f6e$HltrAtR>QBIQaY+whMR{J0HIp+E9u+DOT_eYs)8wO;yhXU`qro$&oH8MF9IzcytDe2N=Z!9gCv_!C*w z0A9OBP8;%S^ofYRnG%Yi}l~PfHL}y-d9l zYuH0cmRnOThSEA?wWUO-e{0mE2A+BskdFUDf@|FOUdmn2hEl2`TD)T~W-_ug@j*Ph z3N<&9^$s>KvhN7pNS(p!n>4|NdE4;-@lAkz^QI@o>VUY@enEKh?zhm`8E@O#Y{~E>mJR11 zNPFGZpn@z$j~jNt3tig6ZgWQE`!q|j1p%?U0`CAQj7fPzDL2PLfniwGA47{1kJ2QE z&|VZxT#HQJ!Fzuei0qhC*!{dfrOY4@=#C0-usF1CgJ{x@&sqzrKFpAs(EiHats!oc zGvzX~KzO3+WjJYEO=Q6dFzhL>! zAaGOi$cp~w!pGeT)%;xu1$xA#3Aq!U)&cvDX^Rzt?*WLR0eLvqNNW7kJyZfy&uXfu zvG*eU_GNWyL$`}Eh);X}eUHi?G4OBj$Mh|5a(+um&)?%&tx0d%#{LTgVs2+Sx#PSw zx>W|6I4bb-@~f$iIx8e0jz4=m0@3gAxEXml|MlO6z#o*ZAkIk~=Qfsf+Fg9(&e1=q z?KigX97JcaUnwdPgZ`dcN{jKM3UVy*iAmJaer}IZl<7jB|1{?h3W!z`By@Vn? z-D`G*$HFw@q=M}|Rbxa47Bznzh`1hnhV@=JnfxpKIKaogDlEa+zsETm{zdqM(o{4J% zDycT$LVjb4?E0Jul^*Vk&V-ymB#7RrP{ZrFieg^R!J7vhT)i+8UuAGleZHyek9_%` z2qTJdK`6U&**4_(RgWqSue)wXWYx6Mbv^h0q_l;gbQC&lG<0(sYsb%zn#*ZA-%_Pj zLAKIXE9>|_d&OEBA7EA;b(P)I0B&#y_)E-3>+(0836}Q7(;~wQ#Jf zFj5FZ_s8fqhy&za21~1*8scjh)|#4uovN{Die%J6Q_*5H2WI3LDTWn@whQ^(n>$t)Y9HMno8=`N6Kl8=cx+>Yxxvb7Px@%kgKKG z^{)}nKrhY0HZw5LRH=qT5GR~>+rR6F`N;SZ-rcY+Cl zRUTJzGQ0w-Gq-=Xunq5h(lGtf=37{7n>T&#V13{Ka8r6oI{A6Sajc~;u~9!AqK9!~ zVx#B_sHk|pQVNR}QLZ_k=0RE{DX$N-5A7W_exQdxy%U5#1g>jyfqb@2ZqDPhmuvqU{P`KHBaSJdnTyQJ#R;P}LAbCv)veZjF1)NG)_o!sn zhAKL<2|*P>b~bSo=}jD)KE3((bg%(Z8IUYuKn+h!>SDP_KZ( zIsZ+VCZ?M>8HD`_UO+0z*z8`mAoHW=aE<1XfkO{1L_fT>^5vBaEiG%;30PGCIiwH>*4{i^L+)P{-(u-{-vX2x8M5|jlR+l!V34rT9f%k(z=g!??Y^F)crc4UX3H?fRnu{=t7Q0-~Uw?*PK}-270K@ zx##5!9jjOo8|vAky_T5Cn0tEVN>3y5IEnuY%sp^x?2!KTNv-1P^z>JCkvI@l0393q$Mj^N@OR<%IXzya8Q+Cgnlpx& z_lN@q(pS7FNW!lUSqyjcdzYRUN%xm1s3hoh-}X4FH{X2j`aW*<>)Lw56+L(te#X);-L|UoRUV_7t`a*0jRw%SUh+ zQ{*o_?ikXw2$mSEP8xeD`4jB1O&bvF(5~f%BfHC-hSy|vu|s?p&93ZP-1@=2By9DB zbI1%mbV7=ox6DfzJG7*I%xi59sC`u1Ehupl!GOU3?ioIZXN;v6gegc)vOZ(DXsZA?ll~c42*_)l=bgoRso_ zdl$}&De_Au(25v*>&fhR?g>)c#e{+9$wwI(Qcoesdo6PnQ)zr4nIkQSyw?IBWf2`m&SrZiFBbqPR6(9;5I9@PKhZDfs$V!uwr z_QGB*@gn2|nb)&#K(_!Y7|{K$H%vGi&Q6|zgq=?(Q0&Uu;U%C9ggRrD0PKSlJ$Pa6 z^e0>&8#LWLs0+4ozF6anp}+UAjGH)#31Ze-9`CW4*!jD45*!HsCUwuVqsW8=PxkX` z$CQ7w>N_;kEp**)VX~D#ky3*{aLqagy1nUfN%xx}{x;Yk!{APU z%5MI>@u$j>Ie9s7hh5O({!9wHp^v^0Qr_SU35#v}XdQTr&uB;`N%ROUz81UH;lo7$ zMxte=E9TtG&;F7i><~-5Pg)oqHR5Kt*8yfD-4gcrA1Z+M>kP$+Ao}#mpk)Elm2-Z} z`cccl@lOPoy}v*%U>DKo`dTmtm?lB5U?74k%-#JBbcKO!@?91psx)y>etE$T`hS({ z-EQsacC7uQUGG$xDDe?f#15Bk9pd?pxR5ScHmSREKprxz9!q^6(VPpO?Y}scs`20F z+F-!IWMy&N{rXwYLSYTZiO2(E3pB=!3czCC3}-KifEi~NwImvNb#Bkk0AK>eC(Igx z`dl1hCXVY_G`dQ=Q2QYLtJ(&@*4AqlH39JS>~as;o^IAU{dMABQS5g$eCP^!P~4~# zu%MlHu=*F5LI7+QzWFD=6WXK@D}g2;uwnyh$PvSbJsSx=KbX#OPug^Q@ z4&a^tuz-KHeXkipMyhG4fY)R#r%q|?c4%q7*c9uC0U-Sg(ifibt(1MgeBAAhwksY|hsf<~EGbUy@q!V1)bCNK6&!sFkamNsX3zZ${o1V->zCWupP+mM-~#fhtGoGNRC+MP6=@B=Ae zMO}F=Eb^spnmC9Qr=3c6w;5e$tdt?_zDSAZc;bHy(dRusf0mmi9kkPi6uc$(poV(i zgRyl2!vw)~S&tc5rD1NueCjDMCY4Wz8#QV+w`_R#C@K$_ljb&t7otxKYK$VhXj-m7 zt5ul(@c08BJW%3Gfzr=g%7p(K*|$jOH_@+$mF$}Vg@5%PC6pV=!BrPD2%!3w*2v*ShBQ;!4iuT3E6j z_z1~yJ(qza+OTx4sX}O)kwe;i7>_!pAE>{t0a2h%wVtj0!{=R60mn$s>~&6Qrpl*k z0mW>{05be8RVwk;Pf&QoNi}(>z3TPS7PxDT$=iZu8V|@YbE>LSJaGTAR4H!c=&XcOw#(Hzoj!4HG#++%ee=AJY`~wf%ia zKhnKS&gTFvjC;G&{TPVx{0HF#&bv1PAN)5LQfv{$?h5Xk0SPRH2L3L~Tj}>upgb_L z9%lZJ<$$}nbFqKjkJV(=K zpTihN^)_5V%=tHx>4SY~1ra<+)_Pr_Ih9ZWMC|W#a8TeJHn1t9lsBW0T>yz{(8ATJ z;Tklv{iUw1IB~Ft2NaHuz}|6*?v=Sf<~ZCB2=voeDKJ8cjE^2s#MU+_2tWidJ`#jl`n3 z)}VR$*T5(#4X${-;Lj`x8sAjrLd1NC$*5JU)9VsPL(SN{5fOi^Yrf z^C>-*A#1wyvX!bRFHw-@N4TvO@s?nkKbqSRIA=;A!%8S{%lL7pWY+l<)`nQnnhONS^j0ah(>Joo$=L~PZn70d zf~JRaGDkt=c1!AEt^Llxc?wFQQ{wtx+CXbgolMc)ETS?tbBD9|j!c4oqB(8~Y0&D!mQ<5A69*s3|Y| zQH??!Pl=mCEd?+L>W%}6lCN3+7seoONf@|C0DYGmA5nsT1n-szlG(&LC=2YyxtjyG z%wNYT0K4|9GV+`MqY?2xg*FxU6Yc{G#iVy7r9G|wq3O#9UIC`GB$=k<90;a&ZjALk zhp*SV-?DIfI&>`)7{D5)b4xX3)&czO#+*%oM&=J=op8HQ$O~2z^^~785i5||ij$mD zedSCa*&g0jyEW92%P)5{Zyu@~Mv;8?3p2_H?1?Bc!@kolTA7$qL}7!RjojM<4l887 z%y%e&N6nslxKHl=r#%*~}bNWwZM6qB| zkgozL!O!MMa4tH%8y#4iUTb%b@&WufBXnHnQxEk0#jG9tZqQhea({9wsIVcxqLh^+ z2O76#M&rfaokA`L?9b$do9S%dTIntwHv)Vv+HKOeb5po42XZDbMiQcWS?V9$af!)q zZPlGH==%7Sv9~n$5Sh3eh14f(ix@cB*>(OJVw0e*&`}Z; z&&|IC%}x^sQZlYbF~Q|GA9`+BDiQc58}?PD1j~JGU-irma-3;^m>+hEV^M-&*QpAGq@v-s_hemTv_fBt`u&FWW{RW!xU+f-IkO()Rc{Xdmeg zXB=*Cf-9piK~l!*0KrlGrvi9I|4k)|%-Qfyk6_6}-h@1wp3>(iUqvK`y&si(|}hyXms!>{0r6-O9}E z;QzM7GWPriZXciG+VL!*3BdsX?GFM9T-KDGszCL6WP|Up0q<%z40)Iawg&u)iB>dt z=xZOK<>Em%V`E&O!9R90dhcfmRuz1b%Dn+vm7g+MTRtC3w_grNrlgck^oqgLwdTw6 zfKXLJ$Hlq+S%aggE50vr!@XvH%eko#s>L2Ao8OKdD%pcVg079)Q(6bIZ2dI`99P&u zygjdH@`TKEHaJ(g4;sy>Drt$(7wq$vQLo0DmIixKlNzFDVd-G$1n4YMs!v+*RLYQw z@2*{bCey%Ym&kn4*@pp*V8GV}mOBi@gGy<&CN3_oGRQCeOCV&X*?49-P{ErX_iN#+ z`EQMkobi3$^!s%1X__rM^XBiNTAWc+_fR0qMxg=9ZajgvF|*G!i6y`wFA2phO2GHp zV0IG}YW!W+?LWbi6-cwOuc>jn3EukZepfk1Uj^p|#kqySHXe+I9-{n*ReMFn8o~AK z`r6gjVAVl-FK`5Lv{O7rDj5kE@%lrb-K#{#(my1!)q(L&U+II-^+`TgV|3YW)CRx& z!?9V5!y0rsHTkZ?V_g9IcettAF^-ZImFdl^x^Rl-OA13T{RvyvbA^7XsClWC=E zU4=HzgD1uB_hRR7bd#N9&nffB&ZOsmfG41>L^6)WUlk-x|BRmi?_dWu68?>S`&;NMa|@cEVs}EY9>OxP5;)MyJ`as$US@|(VNGtu z=*V@=0QTJ0+_lj1m)mCD58@UZt)3jV$Ai*A5Pb|xaKeHchN3YCKn9Bi5Ud%{$pUK` z#bfz}jd>AcU-zJtQS^Y0a^?w3P&QiwQaXTkI z(pFzSY)ZY=kV+Tj^OixpY# zf-;Do{b6UReL-SjBFEMP+_{aSq6L<^MDXPcLM-$ zYPrnN@mz%2dgdqcYl&V ztwS2d&k3rK9uf-cJthYIl{8l_Gp54g!FxE+725k@IPsSIYjcS$dK0hhY+TK%Bwvb?J*!}oZ{)v1a>h!|l3Sm!--BXsFKMvS zq$;S)1LSdt8!)zBz!ZoC#wXUJdVw_wl$ZR|K8K*^>eO*BLcnicfX;QwpJka9LSBS1 z_cCEGr-iE&nEw9?oq7OPkUXK7e9JOzG2^^~vyydy>&q`uzbxoqD;Y0X_GK|#=@T}e z-OI)5K}1uMnh9*O1)>w;yaeG9m~IO{n}yV0{IaR4y2V^j|f5C)Qm%JO0f)6&lvVnp({WT&SyhG)QH*isZUCI>ewPWVLXn5WN4G(P7QZ6w&2^yev z{dU2<8Eg3*)WZgkdY@ViP&plFN!einj0B(#MmJoQf%_zuWMd%NGpqQlQC4xT%Gk=* z6wzwoSJmi!7D#y^%cg}Z<1&@5mUA^2>UqVbJ|CX8U-S?CvtC%cf&iJ>Q6wU#osh6@&SnK$O z`)}(a%}e{>h3$4QDWRk33y!QmrJiA91>yxF3^vq3JVW684riMwa@;qwZx+!rw4p zosQet+xkt=!BWa}!*t7{<%Q&wu}DDu+PxQCFz6kQ%KdknJ3yBV=isC>#un_72CFE* zWK;(*M5xe#Y=4P= zIy;ls7OD4B`P+pFpceojqcV}eW?Wq6Uh8ZP;vZeul&ack#BiyV5b``%b1#oK_HhL8 zLh~F6(A(7O1I!x(DDB zDCsqnV#|O%$O718H{}c|?gLiszugP^h7Eh7gR<^Tj}w!TH(I)0)zLfzi)xEtS(SIHm1Bmxk?cmaQ`FnqZKxkMMu^C7gT<<;Q&vk# zIS8+Hh&i@?{rbJp(LX&uS-khy>6`d-FSp<`O)YG-Qp*Oizw~(Lj9p;y)0E5XyLePo z=fZ$(R9bf-;q1QDna^2_bG~?U0^;(HTCQ*@{E1AK+IdtNSIag!epjbO8`I~}ix~DE zC}HO+Q!}P+lZxN_Iz}DLCxlYRxVOqE@!4A%9FEA(uKC>KXCH8+6HzpfpLAdl&uXNB z0W^YBra z!S1!CsM-I1*^8 zAm2>sA()V=MY|~WD=zu}taC5+3{shHVEqtQ5@@>SCHG82b z%PIeo8yUP_<_1a0>xekp*;GTULQ0lWMgPgVgYrrlrpeuRT~I&IsF(ZHmAl+wm4LwjDwVIx#_mFyv>CiP(`%h2Tp| z1Xk<=BC;w-S&Pb5S=9Tun^x+8>VG&0gX%@mk*Sd8J+rCZ8T5fiU?*0IAq5ebtVQ*_ zS8X>a9>M9}3t_L((`j`mq*u2@E*cCBkr}_ZGAfr>UqYXWpodENM78K%<5o+ji$fvo z=Px4raEbg)`ce5A()!Rx{kg9i($s3*DKn~RcU3|rsrX0)&1%p5L&wd`$i9a}k6NiQ z6O?MpE4S`LT2v>ZOxi7Eq`n6DoDM$9_JB`z(_x|qt*AJuX9Wu!HJ zcr#Ftq2`I5InC|Xh416GB|dF|oF6|R>56Eu+zI8uC)i&&RK4zcUylif@47G5lhRp+ zlg}Sd=)~9-3)T735|2Whgbnv#y_6|arx911t0?6wuNMZDBsNj>vIk-I;xX)NP}DV> zS~6lqogPgix{6+m(G@GyHG@Jr>L)*N&O0@Z#6@Tl8zrqiywS`ysvq!_i5)k{@HYit zI~YRbsfq(I_sW`9H8kmQNARlh`7mPo)%E8c7VNyS1sh3ZslH+~OEPk14-}%J8=Mt6 z*Q&x$;QV~?o{ffyy?&j8t}9Kwu`*iVN+4*4x`_55In8QIhugE>z2zXoYP?<##;~K1 zOUkYSCUc$t`)=| zyeb`GkZM|YzpX?(cIZMDVN)`kcPXO;ezDKkfOoU4!ACDEV=8q7#=T{N<%XrM>AK`s zIHU2g+r7-Sd4hlN(9|~a9{N;#H>Ib~$I!vwN=ZZdkwz+*#3p7Ajg~TVLD!nE2`lrQ z4iAexS}baTxIzizcu$cf&*}K&NVYO$VXtOuSK_?y$=RSu?L!*Gv1c1z@SJDtTQl$& zhlrt$w&@XVsz0TZK%1j|G2||NRQAO|lOywgAakDe5R`)tErUta$>z51DRqspP4sEr zjUEzbCk>F(u3w}j4i z!eUu>y|4pm+lZNt5O$=O)20sQvOUv1wYZj3Gj^pbInB46mMnzO^t9-6BbnLGB{yhsVVgGH|6?gTHB$E$+s zM~&bQ9~3lojpIVz*=d2Ym{mg_e~R8LQFf<3#-@yn9l`#sk|N`(Y)+ zF127DZGuoegU1NBVk?4bhfH^OIuUa_UPrS&*}WNjJiZ5tx_bV7i=G#@4b2kYTS<%| zBewSGX|C@Je%Q`cFqr#UzgS-v>$;Jx@)o12a!+v%cTD$eh^sgn3meBlJk5rI)d#=>pcj=xL?-63meV0i-@33(p>Iq$KEZHus z%W9zHhB8ksSVj)arL^vSuF85xh`_eAIk7&fLI*J@3{fguIohboR&%SLAW$ zURdJe34RN|Dz>00(1+y6S$Sy;+wxiFG=5(d+U`*c-}4P+>3qP?C8qf)h;s%B+RQ=^ z>`Y;ZSoxmi3jQ+^g+KRNi{@ZNpWFbBbpHI?k9ED}V_s2h893Kg@Hyrpc4bHM3au=6 zcbcFoA`SBu=X6q8;C-Tn55Z&+xbRfgwJ<^#CGB$;MaicKgJ$uml6@s>k(OkH%t*dT zkwhaUt$x)n!d|vV9ZWmxUagdrbo?+PYM$s*qDo$unr1#4!|tMx$Kz(Th&xNa{Fv9g zbbdw8LDxuDPu4qhZcudEafBv)XXkx;rZ1~VGjc-Gi+)7c6#9bWH{p%nsdzF!_hs|Q z_A_#HwRXZ&JG`(a-TB^|ZnsLqte&KW&r5xEofTd-iBTgug|^Y{+vu`lDNDCzKZBpI zxN5&o=y=3eY?Hz3x9x50gM*1fXd3szqhU%lT%1*k@hq#}?^7g%W-C^)IlAMp#LTWfvNXd4%{t&na0%>`qq>13Oe}W1 zOw9{B=GZv0Ab)Et+2`0wH{za0*J(!bWVB^U;X#AkdzivO{OD9oAkD-esOQH>!d;azui9+` zucH>NB6?#!d0-pz&C;1Fc#?a6bBSJ&MJ=UV<1|-x#iaYmJN_3XhN2Uiu^8Jps8Rzs zvzOZ?AB_qi%^F{9)&$LkKif%=r16k5tm999Qm)SiQ+>Z2#d}*tF5;p=(DMX?(}fD! zwG^@!ZpM(4_W@x|My#z<^1xzhkaAGM$G$Yd3C?-l5|rf8xr^d%?BZmMX35_{Riv_3 z6$ZI_=)Zvko1fehRYWb)%oa(#5yng?fQax|&t%~}u6cw4`~pBKBYd&Nhe z@0-TX+&75gKAVnYwdqq(74wHY3=12y6(Q5*3177LOnKkvUJXU$S0G1A<}7<%BRte9~}D8%)Xyq>HURa~-laT-1m#g3Y^$`a!|MEzdGo z;=I3)G;3bVb+i2`TTZH0a6=k2MBCH`Sz*j;JdRvb!Mj4JYCD(! zQ(p_nmZ_G$6rt_$vW>RAL4l~QL%UI7TP#nrFtZP#v7>1Gw>-r*U)+ttwGvTdkC^`S zc&MwjL&!3Zy)1NdfSB&4{&}{i0r}C-E^c-%R;L3~<5qQ0aKl^iHpTG+dwpvVk$Nix zU7zL?!q3*f<2e!h(GzQgX0saT%W4cipXDt#KMO~svNnR>-Z;S*Q)@!`q?c7(@lkl` z3my!Lcl@~5d5(>~KFXwaq<3jptmNhyT*C*>v%L|$^^TAU|GM+n^Eyp>_C=<-j@V9W z0yI{pbH)qnV2Qd7W8{(%YGDMI3mRaQuIIMZMb`MLf`L#BE;kAWh-v9xJaDxDNF}w2 zht+vey!R)=A$v@-9IHpD59+*f+H4;fmjvatSZm~ZtjID~?VVLcH;=gJK((nsS7KSj zF&X;qYBXtmN9p_J^>4IAP7dNfQS?sx#Cu=|*e(Z^8-`wHOx=q;me1WkbMX`9d6^la z+rx~wzJ#pNdv9cMt7Pz*irT5Nf@Ni)#Sj?W+T~q~fz->gixd3h#BHyqeuN)>m*pe0`pYJE!x9=T<+bj@iYX zyj-q>X6dxjQ&wtDHwLcb64Hcz!XAtqkIerWj30OWd!#mwJMpRRux^gT-M>X(&oDt< zeQ7d(kH6kvf`aaYWv4i*2Ug5rZi6<}NtAmcX1q{o`+K*D;e6HBajFB>4N5qW4JU?G z%curKFFkQ9B>n=vxp+oN9JrgGtKr5cz!;YT(R zf$CKRQDB5d1gM_8Z2ywm4qv5rWUgBP#H6p!_Jq12X7OhDxqgA1Lr${(E^J zD0Y#;24qfNDvMBhOPcM3#A1HrR-E~fYo3?3qfHz=3X_ds8&~SeBQDC@LU0|70YkLKg)PFp6B^{dkh+Rr;VfQW^65^fw+IfA zqrUxT#()cv z(qKi7ImSrODY19KJ~0Nr6yKb3eXzh7;~$j%&_PkE|8U+=VNaJ6DP43SQkwmuhc`32 zWH|)E$&L_%XPxEtpkUcjc54KbgFZ^$OAog^(b-XvD^gw}9Q7BVHVA6m1VF9f4B~AS z9W8j;l)SLv(t>0bd6}m*Z!l~e4woP$SP6j^RT^~SoQr4K`gi>Y?e5n@$~jb@M#Ozzy;QchV443Z=s&0_8ODmSHZz|kdCRd!p8Qi( zhqsQx3bAZEeB$WC!!e1IeuLVcgWP`g2-G2PmeO`-@D>xpYYdA5;wK(rieHPlpeMD* z0jiT2JUj|jxoxDn&dYZ0x!*>mBtIZ8^Ga^mpN&`wjrH}R_m#h$%_7@NZ6je{5mz2y z!I&E-{Q=u!*7Lw@SRY@~yvblLsm;3_Tz#w-QZ+PE#n>U!32R|jo|kPPBlg#&RsCpJ zj8PpGFFtZ2Mz`fCnl)dzO8{LZ_Y&Sw$lDpH0zfr5TOMym8_}JLxg-!X1 zE$59Dn;r~S?<>C*u7X+Q%8wjblcoKM7xBWtY&mry|Zia2Wq??Ki>#%eg;v9(S4kB z0l>T*;$gtRnK_>xJGqyT7dGD0u=B}Xyf3a^i={H=*O~UBDPS#2+;D;s50K|c$jVKsQZfniZ z%(9lFI1#VZ?V%WwIbM4m$^f{;cw)1>y-^;@nV2BijEPl;Ds7Jxj)BXxBP7-%O6&g* z>FF-1=b0_zW;BW~JD|o69R?tT?%?wc=v@X^#=>tv@5l}oeT$f>?`03(wN?3PJI;+| zh%>TK$SPxL_Un=>`#;Cs3=~rxt@}9xd);zZyBl&$!YjSF@{He1GIU54&nWY8>gP%B z7!`&R-qea*vY)pn+beF1Vxy&YT8E+H&KW{SJ+h)lFT|j`q3+~luaND>n6QA&&D0iC zIf@19Rw^rRX{i~Dj$-jqwWOlfjKwrB>~DC?_9~jS5)>QurI9c}=j$lt@_Xs;$((9j zB${<1#`ZlW@-%{W{SM)|fVv_YlMy=j#2$*wl;KpXv*WI+{ufI7qiX$)3#A?nYh{A3 zrNJvJ;6w4^9a$l*3n^Bw-xB$D9}-=dnb2ryQ_It~o9qmVT%$N!$!{^by=(X^OgQ@{7O#FHp7< z?l{Bs6YXFI(-&OVW~3~gyV(mTUxI6Sdt(h_3Q`=6$EyP;-4-I*Q9*lEo{P8PL7BmL z=~;xbm zq=R5EJ1V%?!?dZaO>97A{|8_71|$7wY$cSivJYNG(c9L}eToV4P!QAHNpooW7mx`d z%O)=Hk!;4h(Fj(L!n;F&naUgg0Es%%Ob`nqo*b*sAZCrgYHf9`&q+mMFMC{p58BJ3 zsgNU`H|tEP&;Ju4$?m2&={h1$$he1y*#%FZ0cRM)b+!j{J(jhL5GEGK38f(6Y>glK zwKr3N(y|*t>9mrx9=)UEZAFgb>4!$!fJri^c8$xE`BCtxpjsG5t_;GMd!rn|KWKP- zN9>9;7&UvS3g_>juBWmNRt9-&s^o9ZRj8f)xnu~YphdGv-c}VKVDnTala#O8T`(ZC z5p^MtycfKtULP*9PL<#6vXcA>bt{Tnk<-dn!#7VTW?c#5B+^Nq?UGb}_|0J$_Xq*n zfsP)>VPZ5M=0*-Wl~y+wci$?u5UU{$C+r@s$LzTs0KKJ{x7 z@cUX`y{50J+tcpG-EjtCMat4z3)oF+vKX6hKhQIL=qX@J9#1U2CWa&|znSUWB;UEb zv+K3K(%DEv>f_AF$kA)e$1Lq?LUsoF?5Viw%HO;I#oTed|Szy|Ezw0RW`q=f-kXKM&yYu_Ox z{{t#gfKZX{v4%Kt0mcWgs2~Z$cT^QSv5?Br%-G=Q7`-bCVr<(=uh*3I2ms_c-T?~1 zn71-#Zx7b5&THl?Fx@ZB)o>arL@1GMY9BV^p5ifJOkYUS z#PSIjSH>6k>?)xCSeMo-k{Np>$GU0p`NS}S$Ig;@i*pbj+`cPJK5e0 zOyju{#fY&OpJ5o&S4z?wf0ay6P#aomsZNS)1ycu^LK*U@eQ=uVOBxGwH0vSR^lXe` zfaw(@_W-cD_=*Yo$QUxjb=TcvQ316hsZ2q z6ufZY?3Z&ewbZmdPy7i?DVNpFcYnXV-8#ND)$Zkt7CK1>${XFA*PJ*L+Mphq>*Ao9 z?89v(UVu96Ezx~KAQiWZrj8c%N`?F49A7+;v|YpY7C(wp)EL#xPzeE|4=%c^>b00g zlY>vlT(&~h^$EM^n6ZbYlrPaUom*-OjJhqmrRd;dy{J1cY8XcdH3!mxLX?jzUMXvA zXok__p;siv{-U9NrJX8M6V8Su#*Ax4^jbg^GxW|Go%~qlI0DNOXYVcqyg&MQp%6Hy zrfll~Yl*`Ee!vnE4>J>IpNvG{Ot<4(Ub#Eo1An*^;HCR`|(EauZ>v%5}Rf zP}HcFg35Jx_yx<+6>rx?u(L?yHsa>Hf%fQIb9a}Azlh{?q;yX<^d>ka`d&l~O2-ac zJszun0fEK=3C?LxdDesrGkT(-!A-O0M#WO;y%|p*pNxiSQDK{j1CgA(9qhY6EYWYbTWw}yTS=dc;WuZZs^P0U5f6Cclx^(+SQO)!vwr(%@bRd zfuEast1ig$Kd=jwcT>S<7VITBmTSb+!62#QE$Nn5Y%9;B{HnYu8=kKX9P|J~g#{k{ zMV0-1>~2bVR15dkSB(Gz82ycQ?wGERm+e{DUOv?RNyFzQ%dF-q?Eo$eT7XrR}TjyJh?dd`wEN!gI?}eE$uXto>3J9cJKpakr5h5cUI?7O0B?aA7y?4qmQ zgD^t}&C$Dr=&tu#W3pkLsf&E@)`+DBt;zGH7O9}0w5$hoX~`Nt*0T_);?C9@z{}Dr z-J*Kh)=f*%#L~q+Cf_pNkF@ZjBc@MtpN(xI*!B2?PXs#3w${_6j`gLo&W8~~&y|fQ zW@4mc$1gkh1#B)kUO2Y#pK!@pfqqo};76nzly~I{Dx3)k5zje_tquDQl_(n z$ZcL&WWPGi%Jp5QI6JJdXhX46uE+h-56%w?0$%ZYAm`_Rt}=dn%O>)_+S4hL)p5r=&LA7fu0 z5B0vsT}P!|+LW~-P8&&O8Ov!yDV`V@b*qMncn= z%|0<(OlB~K=QGZ^_nv#7bMN!~abB1gw@TJo)NXO!N^<1@9CXmK3ofqq#?Sz%)P7HaN4*P*O1JeKXhQuH8}d&H9vBT(TL z;Qk$`v^7&0YLw)=n5)ZeM!bFtd^A(>(X}QT_OVk%MhVU~+@{U8B?^;2T}58|i*Aj(SL&9lE&A?Z@g~6aYx^ij zJ_UzBLsKm;_{=tIgpX$I_&krzCIwVYAf1=yYIE&N+?(Jz3@1Dj{HDUxV|Lzd)u@6U zV%e~pTB@s5y7$ug3jd$%>OHh=8pJmb>piyv!u%gVMBkI(vAYq)@l+_M-Xo#bWng0r zsXksns}>}jTDWIVV{C`YbM0aGYpHSuCOMs3=|y-PW!tb%pqF>%Q=uNx<+7mcV$xWj9W~B~^s0E+2FXpjZkI8d6V{W}xFD`_G-+dg4T2R^e(2 zFjVsF!{+8|H_01=O9+y`2UWC4nhGq%YUEEj(#phX)L?1X!0S5 z-0_kFA`gSa2BDVFA(DAOsjexDxZU0%3$GhbRc+A zd973H#`PCZ72sgj?RBS8NSi1Nr9P;F0XGFB8cfsbe4I4_#8l;QL>I;VV3|z|g``5p z!$Nb_X5)u*#OBDIe&@s9Yg-yCpnC_TNohcWy5i{Whh4^f>8^+;PLUA3)t ziZeSrGagZUYyYe~$B>#CX#|W)!IQH{L}83$9K04oOZUcGxVG%)HgQ}!cjZVeQ17HV z8A%ouq{GFY1e;ox-cdiQiDCSj2KPaS;x|2R4eG(`8iiYcJ;4S|96AGU!oQ?58xH{^I}$eY2S%SiiM z+Q(ve_k90Jp3I3^iM=Ek;TZ4f^|5U8m1x_$2>SnJ0NUIH?5>3dF&>XQLJ%Ak3B0#b zMe%r(HQ^Yk2WY8fLCSw;Q)2NdeRYEvCnJI0zrhj$-XydrxI`wWYJJePz#p4mz|c6w zf1bQ(??E|Q9JhG+UQ1Nh+~xwBzxGFuuIfiAmxlT~Jbr8S|IQ9S?~V7#6qC1`7y1M* z+4MBj+lcCPwKUZ@9v9ys7G%=23KoHG`A@pU>xR@d7T4TOYViAl<+_-exLB$1wpwKu zIp_yu8Uz+(qig#OtSN$ct)pi`EdqstJqg?`NaBfN`v!{XCTfEkWg~4JjhmAI+<JG3lVq>M6-j|y!+Z8%S}}_q{0Po#G_&Ff=62xmPhd%?JHyVKNmEj>Tm6z z`69WwK9qXF!14IYm{e|L#|CO?v53_oDg21^VY7Be(dawrZzGo@R&GA}1=U}l))OSE3#|fFE*sm0j z>A+v|&@+cV@uf#w1N=Qxjg$gwg4%JUCg?~1Kd2-Kkc7(6$X?iW^91^jj_C_Jh)$R; z9QPhu<&sulpbg;1(n@XixyRyeMKx)mp;MJ)<=8T3(~!`?bB%g238%i(+_~gN?9uBUm~9mo;A9l)hUU68U>gB<{r?drq%HISXYud)m$5VYV3|8xF`Uk+ zx(IH?RBoD!sHI{}yb5|k3i5 zXW?(sXA>yF7)`+up)PWf|(B}ZiC(|b0gS-FXj>m1{qo-QVTQ6knVK}mf)a?-p0w- zB;rl?vETPXeOMF&LjGeu8lY^Etxcc(=gb$i8eX+l8Ap-z8s^1j*wcYQ~#8lr0 zm`drm01@v#Y_tkfw5rf5@|u_(Z*MAAQD0P@K3>Y-h=c=Vy8efdMDT#+$HAg|`!lV0Kw+ zQO98c$n)scu0I~xsZ=^~NCB`-pLWM3Zr8d%nL9P;@L6v{c!RMLD_CkzoR{jyb8 zVcvdIj<*-mbSJBa?MJ3hWOhqdxrOQ9v4vOqB8V|-{$O36gM>i3X+(|LZ)@xOhCTna zbT{f=e?1ty0x>1FyA|HNjVYBKpPALpkMP1#)|8HyuV^Z~{$t&FQ8^Y%33d5ad$DkZ zTo<}eLi}^-q3_X(kz zxWZ$<*@fHWeN&~Ba@ArV;2&Eqe9oKG>FP(rv=n5S{LWd338GNviQ$a{fvE%EkP6;->HYMo!e~Is4@{cWOoE z=alB2?Y|pRbDfEIeSx9{Og3iHdBc5$dx1qwhGY5^Ki`3ux36^32yc&K%QEapKXw)R za)!u97{ZY8iISJEk>y3-(|n269VQKL&kF3tai8`1+&JmdIBCQ;%t3p}ovBi>u2VW` zwkxStvQ8^RwjLqJ30A9EiS|{pYV(=tHW#}QUfcj|&3D#_y`Y~84~Vqt9*j4b?@ z+Z_(+mptlLK1(|m!wk?sm{NSkE|9b+=!z>}-tDI`U29L^$K$lBGth$+qZZ+H5!mLo z#M|#Xgkr^U)_D;gj$IIA%1`k;Oa(g^XMUic!m&MV8vW;gK?Z-Ays1p5Uhv<(<#WJB zdE(Lfp936AAMID>cK*PGFjN9i!ccJ>ay{l-glav5cJUmJlWeR?h@|}R9XGtBc_kU6AB%f0o!ogvJ?%R zGmD--TRkZKG@15a!#FCumFAs=Ul zP5{IBbtEvKL*(P)U1BvJyPFWB=CqoJ`ATs={6_8WW~p&f^(LzQXLqN)=*0iwuU4Ix z4%7wtVmPqPZIda75~;3^^W3Fd#nu?-lfJ6g9iA|r`PKS|~u6q68s<; z=rJu+nHDD9xGmJXhP^PN2=g8Ly50+zmu{aelv^M(UJVzcLRd9x(Viis6s2LWO4mO{ z^eh=9f(mxM;wo?_5TwHmcce_t`e0f5)$xHRByj2Rr2e0y@9ewE(=Nt*cC^{ZC40r( zH`#t33F5zrp>w`)i{mexm&@;0y=@R*K6f1%#{*K6u74xs^lkmHrA`>Z_+L4rbHE$n z4Qr^3&$r7|zuP&aU#;=0p09=2b-`gctAX=OS9$z%dVQJM#I3RW{G34AcyBvONothr z8*QKGI3ylAD05!c9X+=gBC0=~R=D5p@MG@DSMHfNe0s@z$W!o zty?;Z?ENP!6RQHzW+}2TVm3v2&!&u;-5Ye5k>|c2h~s&wd_jh^PO{awBVi9&n5=bm9+ zHYV2^siEc^>@0SW{MyMD=RGlBquAaPYJH-fpQqx{(m;3a6lK$6Or&y#4!_pStU1`? z@g)cr%*SyvDsS-8y_M*NPb9Kdk1&0A#J?B1dP$5d`N4~)OasAd2e13ohg5exCu!4Gr=(eLeOGmrgyNMI?5=Q%x9==z5;mUx!-M@P)wdxl0KBca ztkm~e<-1PX=gPiU-CdDBV{}q<`tVp4Mgd$XuJaj-S9^@2F-)|~cD`HN13NGy^m_$= z3z#~8-sn5mMELB5V{$>=p;znQ+fxUOGXIQqcE{VslGj^1~3y)yR@c5pca8REtIw>wk#Rj2H53xV7C!;`HK*w^D76QTB?+a`h5 z;d)2GDZVPSB4?s95_zRXZF+xuyEb>{XY9T4Abr;KN?P?-WkaTwr=;!h29MH?OoJF_ zG|x?LUHTc&2TA0BHbeSbiuM-zNfeKC%QJ+VoAZnMlV5-Ts(zYzAt+5uKK!(_-T!3Z zG^q~uT6YpEF>)W=g=7Cn(i1#zao&}iXbq4g4DEwuYtC_MB_hXj;jdLgu}H|8B>~`2 z2Yre7x^OvKv%H`?p}+LDoxXP&(X8k{Jk-Poc$GMgROz5t`w;L=!Z&yowck9MY|wxv zqMJ~uE$x!acRbZ1yVn-0Apf^Ac87$z;PG~9+QT5E-=aD>9UfoEa$zOjKIv{l@-uwZ z>{90Y+JATfHve9#eK!3DA3@>2-1qy&mF6h>4Ej%#)++35CsV)W$f%wdHX8bYhV8>{ z*q)JlNZM?GzR?WUqiA7DvJq_#R0TMLCCQ-fZ1DA7NBA(!490Kl@6}eP9@*F?a!8sk z7L&~{i4M)1v0nf%3>d3N0Y=@qS>jCy9{}!gl5eJd2|>=R)lxW>a|kKc9uDSJ`xtnd z<~8%u#F;+~ct(l!f%Ji>KIM42rQi-&s0WUI?(B(66WNWP&Jy2%-+g}*N`ZuWnQZ8R z{HMJK5$dLsFFp2lBn%Vu`g{|;QuQ7?6{n8)+HCo!+3@Y~qve0(Mig6OD?jT&!7`bneNG8vmdr?v8G6?cR!e&UhF=kR~Oq z{z;+ni1>X$><%K5gM~WE=Rq=r=i&fA=|OzRJDYk(8hQjxK&j;B+Mm&1 zbj{JTLdMNU4do$GSw7g3cmgV>9JkhiVgv zIA?4bDQ07a#{ULIJr0NG%8PlatIXSrL^SsTJKo@oP-KEz!PO2B6*z)9soaSLcQGGQ zx#ow(n;O26gtfR0XMD>bkJ`BLx{#|&g@{Yy*;2-#t8yDnEJIrNQyhMV^CY6(_82S{ zku*2^o|#tF$>7EN>ln;%fq3$8s!TMmk~84J z+EZ3D(#b!tYeP;Pcj{ zMJV9cf?hYX4O8r>X~|f`bx|K$FAYD%A}dS^^#g} z%mg{owq=Qrjj^Y&C8AkDulcg-y%~&UXi3QC;^?E^tO1N`?!!Hu?2WK%sr~wtr@u4U zNdKcGUDHv06WI?lkL^=4I9(FYFj3u9rsgfp%KC4E=XeB6QFkyLCyE@e!8CS5>!~rz zaT7>~pr_7`%8GKT2@H(VohHB5g2M$V!aFK4b~YnB>Tm~(t%$D6L9r-ysI)?Ke^`kI z17JId_TOA>ya8S`_=Z z@8|0$Z+G|{v;Pc=kHn~3xk_Oh=lxh}U+z3gy0QDJn?Yp>Fap-|S9n$!?*#Sr0It}Wz zjm3x<=Qj0aY&SVW`_!9WN(_^kcd)7OJ3Tf5Z?_S5cYIjOD5N#Z&u6wor03sPR0XfR zu`&;`Fgnx(ct8?%i&nibwQ>Bk5%m=F%j=foYaO?B)bz*PjYafAmRx%ac@6#fQ1(b} zR<5oxH#dtI678$=0B>*dkn5(VN-L2@xrCA~KLSMjK)Fnc9Q-daH5ARp8a&`SWg$Km zDpZBp-$hvT`+rz|a`fWm_8^L}o84|f4aBzrusiJnkr`>46`eA60}!0Cge!14Nbj#?1J@=KFr1 ztFz5N6~*L%!!8!1-?29HJN1A zY`#F>Zy;qhB#hZ0Be0cy3raiTdI5Pl=hTN*Q@`g-Ns2KXVuJhVQ2k#|G>7pGfKoaBCfHg(Xj=j5Y}LB1+MIWa8RXvu1HZ-eKW2mS)JLU^Mk=jv;J#ZpV>%Bt3c7h@^|#* zRtM%SvamgI;i9|1V)R_+wYKE`Qcl3ews%ipLzBAu>?{z$yiC@5qtWTcQ2ws{rLH&0 zAv63zVh-b2%wTc?yO`CP))Fi5WB6F3d)!##iDgSX)MgXlTf-#nOl@L`0C|7tU6MYLhkxX426Dhz3vW+C+|0=6x_Lz)PM$I`-e3M35egAa_ z=9b8`qR-BFTy%YF_j_K{wt4>sk@)4#kwV3%PsgvRK_N=dNYjn!=6nb_K0IN$h8sF3 z>9OMO0lr@zB{<9ym#^T3V5c^&vhXu(DtMBDQ(E@@(lP#igiW@EAj60%u(U^te|3+c zMp@w1Xfd-+fy!-9optU3MC2Z#(2tUxjK-hWJFQwhlI=_Ak4rgJtaRPM^J7|)aey)G0G<(c*6u0I8D@Ib4050FOJBPTy*R-fbqI+YdR?L{tCE0v$Tiq6PAj&?1GQ|-{J ziT!$Fj|R#YKDezK(}Q?^8_>Uf)8SvUDz3Qilq3ttXD;ar^yanO1s-k~FzV`c=ZxzOoBIQ4sYz|0Fy%mCze1|>mJxwPKossFq0}?5u};ENuAOuwQ8%>OU(2GDHn>qq zsB@?3fpQTh&b|=oBf6}YT8ys#cpT3yQ}~(u_%fDfL$CQQlhKzD$n;U#&X!^!OYvRi z9V;!GoKppP_E&Pa?XC;9+jf^n{~4^s4ZAkrAW4@NB>E$#|F!CCxQEW;*_tiesP<;| z;fY@rVx{JRIhAi&KbWTZ}5c=kt#?BD-%Q-nNOo-R4oM{bMoZ3CAc)YQNicSRvhFcc=x#d)ihzg(el z5F{!xXR8%7*<6-FBDEiJcoP|h{6ac&RggoE&F-PwSQ#z5yVJaiK41iiYx*Xd>g)D-^-h zvU7aHbByEDyt)XKfYye8Ff)-G*_UrbPZ0f!L3)U|wxD#-wJk2lkrxQ5#qx2-Yh^QR z*FstnCZy&9FNRm10BOIEzZNPqQnW{~HGvMH;)QE;cvW5BH)Mh47a2C?!n(uQHXw81WO@Av*^awB6 zq~5?mP)i_^M{3-3NUTBJv6}JGpm0w-GPWWM96Nf5typUvlzU*h_e|J{!Tq7^%WX!~ z+-OvnHR;C%GX+A=NBrRQuMJqd-;)tB1xNgPq6uw&BSus?YWvr|q8;<~)vgnI^YDXT z3=;>ZOeH^$4T9D2;sqq8ad^L8_pn-epcQy?T1)cR*83gRv=l{sP%sR^X8Yl1ZTPJ3 zoCFTRQnd3k0grv*!Ft!r*(U0i8Ey|c3BDty*PDLRRLN#4jOr@V)#ZZ#)EmbSm*xiK z29DJSUAYl0Jo_0I+TrS_o@K0lh=X|}s0;5RZn|kPE+02*-9QdFEMC>Cy@8x~U+9dC zWZPw^Ffa6ZCebcCt0^aXHe5gcM$US7yuv-thMWQT;&6$ZixejP`;B=om+$lo50CKU z+-Q5~$;VK0(t2iAD2?t{^jJ`kLf_Z!p6K5e3g1+4N);PJvX^r-Dh(-^|L~MjSOj1L z!!qN=qK_&b?~%UtyP_gpS*AIWj0f~l9Pdr(&u-)p+&PI z-!sZsnbXsila?y=?D$R9sNy_hTumJAjwd^M&KOy-_OtmXW7yf7X#J5DeMjPhXK(7w zeD9Rw&s5mGQ$Z^oChmNAAB=NA4n!994PV-J+1)$E?h;TQgM9+iMF9 zqLX?q+!cRX9O6c%TYHxzEEcU;)N6YDO~(?neFiqkg+-*c@{PAqf}b8C@bw!db%zo6 z+|0_&bc@wGH&Nx5$MB6a>@CY;vMu~>oPX-323GrLn0G2`*k}6y4t?#KbI?Aykh7Zq zmT0L9Ua*l^+bBVYZekySz)ot#E}SZX4M#=Nhps zEw}b`h%W>YF0SI=+uH3FX6XFrql{I0Gmw^?7GhL{@GO(mDosp$`CLA%CbPJqLp|`z zVML<8&O(T{Zb5pqPSl-ApTEj?6FLKDK|mg;^oc;F24$$Q9x~6Z%sxJ=J)I$2F3&Z8 zk3eRz$|-Nq*#w{ttGY>*!;jU^wPN250;y#j3vmj_K zMnjnbKm_HkQ^#}+i`mK^XU$xHA?#qRqNG_qvkrSIpJThB38WakHBg>)Z_!5Yz+{s1 zn}2joBxhmz{Hu~cbMu|mjGA`g<;**8oz>uB|JmdW{QJ3J8f-m^3PM(XSx*@b{C2wB zLudb6wznlJHy>y8Knv^@{PK|AK8(s zme>1gPo@b*Ek&yb`ZyjRC zQ^i(Y$Lq@-Hw#A?yW6Ab+&#ApiRFe$TPe)$nTs9~u{B$o zqQREiAeoo$YgV4Fo2T|kgWB-*F7dvbS)6jO9Jhj6vINa=b@w@3ii>kWUVCCfA*r{& z8lQ9OezOnQ%g-*r&|l0^q;0&d-sK)B(~;@ctut#773$Mo)aN!n1e!=hR&H1eoya7T4jzhg(( zS&LkHYIg}*U(I&cjXS1;{ZI48rzKT%U8MxBQ5LL>Hr(=Z3Iqn!xxtQt$FxNvQDluP z1OUW`Zds~RwwV~qush5~ru~vgzlmRx_Wd*#Oq3!y~cg2_O8cdE7_>t^wXhb8O8)>?s9%4|jhMlnLknAD1v`b=EsDF>VwB#?Ny8h@&WG)L2iEB$UWA)#xUyjlB9(X8;~f;!=hn~V8!EBK-fzNf+Mo*ONvx}#1N}`xV2N_g$?!;}$Yedt}(l2YU zoQDB0QCseJbVxn+Nw}cX+M!}4YqJs&`E-WpwH9h7|GHMR$Hw^Uxnv0 zKa)65NhqIi%mEx15m67A1mt>T)bJzYwiXEacb!_#pqRRVAn59X^3@BUxDF_LPxP9G zvEyLpQ&5Dqp=(A7?I3RLNiTf7T?64w5LtYUy2tdHafuAlGn0Moz33%^x(o|4`(qak z%-DGws^{f`2?nbz-TscnrB}V_DHa8`J_P;|@c1rvsvd3hxUxWJMY($*M>iy!U56e2 z^7tWb+_CLk85rC?`ILoA8;-uY#d8Ra=sGcM1Kydm8sk}A;a6)-CIy@z3<-PpE3$jd zf>r3Z(fKN(oyD6P)akMm|D6EYW^CRzQmkvLpMMy?U*OG`9H#Pqb`Y)^adnFk@2~eT zzM~Y~x3wBxBgm>Bt;X92kC0GBL=#)6hY^&Kgpah%!+n{K)=12ayJpVT1pX?X|K3vF z3|68%6vt?wLf;RR`{iIPIh!*D=3W$^tLs0uYkzxU=V(#o3_WA)pF|$-8%1RdrAX@U zuuDJ%&n+ZEm4#`$dFtlPMwE$N1n+6CQL3x{6}>Zk#yh<2zXzSm)>?_^zSefpX#(mS z7`X!#d6|&S0UPoSN2)4A2j@9UMpHbRL>>M5A9|&ng^1@am$}eik~@oQ?wNUzP$RQ% zc6pSWjRsSHecI{UWT%l*%EW7vI}kz3iRE{bga-6m2LHAb>2tu??cf(Rl2AUjTLGM%2-$tt-(@r&770%E}KfFoBUY z_df{wXevUZ;-$295UerpmY8FPe^$FNvJ$K`P%p$Y%@n_{#-y}wW_i4Q#CTaUE5DTG zRyrabwq^OS3~AS7F0^U1)3*=zDl8G3>@e(Jqr&O|Cq|Tdmgg1ZRXWX+Kieg6$JmLM?hQ;ZI^{|S6 zpqOSoJk>g|*zEaHLd^A5T&L-F$w2F`%TLqys)sJ;CU67dzWb*Z-T{vLW6qvm+GLgu zC+$c&2?SzWS%{2zWmGm&I-H!wQjfjs??e&OiGztNIVrme4i3GwlUZN4AG1^ER^WS* zfImZ@4KeSLyO@s6QDa=2P#7@CXdc7-yXY##zLInDuv78C0oV*zU9`N(}k zP$$bzVIB&|*De(fj(EuIC=gbG;riNFF`Hk&a?vkiN~V26mb)2r2iy%@zfz=}%5Abs z)n@esH;4jfgY^C0C>hcW)g|znOV7P++^D|kvuFZ)mDHuJb_iaK?gA8ogfa=oY)$3L zhFkb`DQ%%Hj5yiU4*gtlQWFf4C=Z2#2Sb+|RvrI`%Xl)?`ncwBn!z)?gm%BOdV)w| z`p3Z~**~gTliULvqWUXHsQf?qijf3PlkHNf=Om?XGR3TmXse+3=>fHlsgEi?qr&UX z^xp#YDQSo(-E{pCLA_+Nw@MBagB3R@4PI;OplC7pDu#?iJ_Ii>FcotG6fQN!PAJ=_ zMWeP4r?u0mm4>CY5`NoEwrP`gg}*$wieOghMTLIf`^1ojx3tjmd2=Q`y?UqZM{Muz zNa%k1Ea`0eH0fX9lU`MSX2XXaC=G8&bN+$BOi&T0m=Exh4Jm)RhOXKWZHuv zR}slr?(ms++6nRSZ-EyDY9$(lD(~n+_n|kamGp5prWj|Dq0mZ!y1>i;9Uq`S=S+a6 z#H5cDp2whzScb&(Z09ej(oaGkxN#WNGwiNO@w#W|Clc5E!JsEs>D-4azW3#=;;PmZ z=J}rdgdNung1wdxf0JDlAe4|jV8&qBT$Nj?v#%FoF|(3qJ4K(?50W<4!67VQd@#8x ztikyobz~N4zPzsR?1wC9b;I;a3s}APRw@FRLHN4pr5j;I1_iMLeIi`Wa5=Uw1Nrf zIxAqF9JE022&vo~fTNC=vfY@MeHQ|uv6lj)EA%(KN(+vAm!wJicL4QMu?o5gS`;s? z6sf?$aGwE+ZMd-wH;!rzq4Yo3(ag%1nYwnl3X{{mZP1iTOy`Z_s`QPaqBHDaV9Lx9 z>LFdlW+?N$C~66O4&jAs_J^TyZT5=|!qc_-!qVi2^*24szTEat9u+J%BwvK04Xqje z5q19?E$6um&qCU^NHP4m4`m?=@%4~HE9;LMg*eH4#bGo?S=O`R;2Kl=+cn6wl7i%y zT976itvD9;CT&gyOF<1j44XRiit3|8gFNFMhHcVqOG1CNwlzxa4{ylcag6aV{y%jB z^L%Cxp>svsb386duG)lHTUGe-=qYYfoDy0I{zOD|N`NGVxg<4)WhCk(cU_T*=~hP~ zGS@Ur{qp6A)5Ovm{c9-{GlGf(YShnXz$b4#dhm5AhUjQ{Qb6=NzgJ)C&j+k6Ua zLB=2k?YOO?=i@Q4+*+XhdUz&%q49Qwb{a)E)-Ss6)*S@6s8Vq z5O;RLdf9Pcnf6As*}?I`SuBn0`mQ^#zU`el`4#jgZYeJaG|gEPZ#-tZq1Fm;sl!{~ zetuC8nOE{Ql>PjHKyNHT{vTcdo$n7&BC_pt5xt@g=d=GP%60%lLT6xY+(X5-ZPW5E zKd9(d6%2SXCEW2zrq}G#6aAZl)^cD4x)=+JbihX8%(T%MhqFkOkX~#MukgrOe-mAY zSkND2K(3OMPQ8K9r&eeCS5?uiNT&Y+edQ0$!FNtMLN238h#Npq2XlCC3Ph^F3rZ0E z=0mwEb%`@38GJPIGrtO*#g~0`78Dg2eK}Jvj{Uk~bpq=Pj<>leJd&jJ;aXe7#h)#R zzdLzjRmS7vc_}mdNKCspk14G{kN21m8>xD`J{NLgX&YGLeqqki-M`oy6`8y#EYl?6 zw~!aM*_;dPdo6Xp>V>Ihy1X5^H#%WVd>ujUhv@(bHS)PBr`e~^ z&JQh&EeCk_PU;_9YvMR044HPLPI?w#<_Oqgd&`RcxHJI`ViXOx{v2eG!-ft^*v59O7_BOgU>C>YO4UF2seM0+%~1SLnVyIPOma6 z>jnx*gX%G~iYH&?1T#%#wfz@q!YdAM-zyD=Ud}}r8-GrKfdDOEYlvnvo9Mc!A8T+m zE4v##bCQNx2nPVR}9vo68Z zRe7^Ipk)Q2T2kq1fPcwAzMEWYbwr`n=@ zP{${QU|yCehmbni6jHbk9W#uPRZD$f;d29GqY$kkDY9fh>PoElA~jZ#Ezy9bhNYSP z#3ocSo_?neTLaNaONGp*P4dCV6Wr7~Hgz{lWCD?)v#{5+QA*Z2V;nRfik=Upu_lgA z*KViDuK%oa9d#MotH11f{R2zmeauCPXhPvOQ&!Y>*trU+VfiX-)v0KqIOW`yZoek9 z15zWPMHFEYC+#!tAfGh;;*&0ICG>^*hNi> z1W3QL@$5hg40L+KV^g^=jY8)bYoid!^YN!1!#ckt{|Z0ILg)^u*+Q(9w6H$csA_i1 zVK6kn?c)_@qE~||G;t}dFK&2GvHj!JxL`QBPcr-qAMLmBa_F9`hdT%^|IP3qZ`oi> zNy1kMC{cr~yPC3U*Ex^-ZVFkTwQZq!JdWk8H}^jN7}`h80aGnov1j1N9{YbeX>_Hm z*nN_4<`zNQb0+LT(6SmLVmTBczlt9woV@4OkZWGtpR)9lty5|Kv)q$!%szGcz7g1Q zD+`rk`XV4-iQxrZMQW&y2lUUZDv$1Xx50tp6gis3x~mKn*~hf>=1o6(l`zwx=X4Yc ze={k@iIj0m%iR&L;@Hm>bj7K&t}w5_8^7Xw#`?v%sCA!B;*?5CD?(Iqf@D6@J&kq# z@Z-jFn^Mb+;9*rK-HaYsxRnC!Y>(Iu2Ri@0Bw7d@h9L59vPpQm z9gBhvRQgHLgz%NV9*_B}JS2c+URoc#aa^7)={4Ae^hSpK_wpl4kq=2hZDHimo8S?bB-+tbvmqR0A@myKo8 z6bk3v0)t}RwhQSqUZO(QS`VkudzV{#!H$wIB~uJwxcpw4Q{44&?@4a-AOT#S8e-C7 zYmSD6cz3z=@R}TTR%rRKJ+Vy|KC*CU8`K*gOZ1SXwMxyphS3Zyk4jLP8o(6N0JR|W z^}X(We}}N%2Zwctv%~?;NMfujQ|{PaC}a{pxefoJ_aBpL2&#{dmNl&YjP;Bd#r!AK z`lqOv-O5cMNOC>?qsb_iU~+=#y>ErM2!0gg)^yhe4U)!n}x z61a!Gsy6C%%`YD}`LtO0zAbaa<===aQVtp%8=F7l$p1E`^f}7!OcJY7IKDkr37DJy zvm?GLElntEsdToLe1f>u+df-offhXBHe;3ZS62>N`w|3GE)wiQ{}VaEtET7uQ07Uc zBv3Zh51LI4!Lc}+zfj#!YBjzS%XuFx#{DL!rTv(hd560C&0KvV&6DtNpb8o`3V5DO z*oN8{7h1u#O%tUUQcEI)GIjmpmA$5#TGV8cP-uWBML71f_pn17;igUhL$3kGxmC@tj2$p$ft5->(XTToE@57z1ocrT^MIPlQ8dxBO=*SO_JnD&Slhp-mwV?D0ppOrcPZ#g^Fbg zWp@k&HbF0X?-y-1Plm!S7qdICco^}XvpYgyNXK+e?Bq3u(vz0AEwD(=73 zrSH8+5*{$ax;6Ax*JQyn@QcRCH{* zHTUEz_kzB?P}mT(XVTqFKQQ1;+$^(nteO%nJ91aN>5#PrGQqj@NHr^1J_qkpk9bV& znQLC@DqEpRLOHk-bkH;1){?Y&tI|pgiWLTmJ>Q&ZL>E4Ob^f{Du8mF0julh4&`$}6 zJ;|ZvQ8#z3O?4)N(S74zuoGDOX-A#K)?+yC*cmk8A)PyEKrQdD=sT*+ll{nYI~nyo zoMuRs6@6`8xQQ0vWOA)iE`q*EH^7|^H{D_yzg3>H6Q(}7=ly1xktUgZN@w3NL+y#n z73>gl+4rFcPoLRx5tjV>n?Fe`44*AcE*r7rbNNp0hi?gg=B4g!dupd(EOpb=MMGx( z%LXYqh2CCXFyaclQzE>S%kN@K*l?4=`kjdU#(+%5CIjIDnnD`lpLp_G@|L;EXc!cOoC z^u1MLwNqZ)S}`5C0Mo~M2FkAb%p7+m7>4<&62qXeUXD^No@N!9Dtl&Pla)J zP90jo*7M4}Fp=!Ys~;~MfGGQeyec&Z)81lh6z?MdC(*>RD|(94Q?7e$xIgP7WN9^| zGgZkURPl`M18M!~4u>=n3TER7z7)tBv!MCNy*X0%!XszMv7FLFnLeUcR4ay?6hlA) zx_^*Sg83uGtYiHK$N|R9EaF0db9_-TUM2km5&`yPk0Cd;&mUe49e79*9#U-DK!+uI z+dIj6PpdLHXxI2uRVOta_Xn*@g`)DCFPDE3ygfLT-PZcuNaXS4e(7+CJeVXL&ji8E z80&D{l&VU<%{4_;g)!w$Mf3CXBXon>ax6HJ8h_dBrXm^wd4gYdd*5`q-spF6(fc%# z6b%SYu$0Pl9Hr<=ykb+uB^9l*H}!C#p&t-m^>rN{U*D{1rI4K?2W2%|j;ra!x!y zH16r4V%x5Y9*3fVDABRG86{2gl2W-15d6;}ASoPQ@PN_=R*$a%@GOa^G z1KdQCOpC+dj|uF#Y|I^AeoQa$&H=0_Q634ETxWj|^goi`>rM*T+}|pYzTo7(Z5MIx zF_`*5TLtj@REPZ_J~_jPFl)Z$o6a$QG&BAxmdC39cKS4wdUn>MfZ-oWhCJ43(89Ea zS}wo=*R<>aMT)Wbkv;FNz268L{UkHdF@#jP!Tp6*t3qS{H;$@Wd{?|E6A1R0>?RZ> zZ?9oq_<_tbHxWDT%brwZA~n9ZnHBzT%i^2OIy+aGD|Eg&%~R06v!LU zDrx1V>xkbrR3YVdOZD@7GJb>j-A`B_@S zW#93$Do?#^CnSwJqk^9esoMsKTKwbSwyx@RD4&~HK=rfyzRX>!alqUp*|l>&7xEk3 zSh1?x8);dwQw3-0Z16S^?I3oAGzb5lvw3c?jo=pm>09;qRLS^099)!@LG$pM?LIj^ zG@Eq$auOCtUZDfm?sT=Ab`tC8g)+3sH*SkWVu!~Ys@oSk?EOrKdedb3`MCtEg?9>C zRCOx&ZpF5yg3bsh>?U@GZqPlZXwPukZ+L8u2h#zHo6RR)HVW^~?Rd~gXtvw98iXAu z?_wO33(2sgOV-Ol0g@6X9IIH?G4wOZN<>0o z!-@Ziq{>Oceq|}2w*-wtG;ZvYJJu)+ojzsHUbz*tzyW7zQL1+kG-0YkIgjRl?t3k) z{A}$eYbYx~8iqI>E{_^wmxf<8Gl`b79&*$95dre?XG>I2Oi7BZ+NG!C7dmrT$k0eT z?jCRY)3kae9wrQo%;_CVj;c=XitNdTomdB&s|`04dbRD20PY1-MhR;h{NXtLD^J== z5P@Bl0ChBfg;vxi>J9RcdAVcF_ig#=n2&=zCTDuz?_)RXKPVi#FT7*-7^wM4Q{Vf( z=~IF5T@I|cuNiYn=j(Ma3r>Gsr^1pc=ZeM4sKO=VFOQ0j*JG9X^;K(ESd12@1D$e< zW@hmckioy$I1ltfgk&2w8E0W^e+6P<5IqAz$1*&4|Z!R`XtD;1#DQLZr9obdpOyhnJ_9QG}gJ%Fr zCPdo2I0v!@V2%AAzx)Wep2!KvqtYTX2i+g_%jESalGl0 zxHV>BS{1|5$(&e2O=1+fpeCR+eaY;@p9)R)#^3#fYiK#)7ny9sazS)C zmwK1B9O;nE)GUSTGsoAy!oT@0si?3k)~7k6b?G{cLvn-d&HsnAZx3X8@8f^YbIwUO zbay(!DIpQLw8g?Hm6K}+rHe~4(`80(imrCw{Z)TQ<65^j zq};}plZ3m_RMA*ckM%>cU~CvXja3<&+T?7?_6jNefRe?;o2Ln_!BZvMy^8@|#?hus zs|!nX_Zaf+d?{SXT$cX&izQ!~YFu(G5A7Y*+P|=K|LiZFH2Y*=Z?G5$eRMSdO)ZsL z&Kj8Yv`E@=vO2N_J~uO0*$cVp%TkmN8HwGtsD&UI;XFs~+VrWx&?7&FAW-KS;U~9m zks(n7N2cfYm6UA5i#V=3YCUId?b?Qmw!WPTd=hF_yg9V|LFUM27{{aoZk)?FQe5$+ z@lb2kW=i!I+aPMLF1DUi{*3Vss0`O!Qx;zH}Stc}OoNnV*j zs2ya%t@SB)F1eYNpQBhk4;4N0&YgcXsCD@fTx<*@47gRgm%#B9x#zg({NJ(9hK)v& zbC;f^1|28$gT-@3j6(GN*!mS;Gd^{>^Nj!WMG80f=|m14!mxw+8Ka&_Iri6zP0h^A zp~qRu<3$hhRI|K0J(kYN_zlU-k@^-5uN=aUZ})VgS59_rgC2&f!3ey;cQP3;hi(;|<RO13u@^}{Kff}&3MSHA?mZgXNpqbpf39@>D!g0-}bEEr%$ z2%bVEaya|CAq~R34_-L&fGNSRMA2qTlgEYwgFw!N1%8n1rgb|*4n5ct`9_r~Yz1xX}GO zqk+3w8%}G5a*5|F?|2Sr?JyiEbu@mmP%X~P3!Rlccr4kAGFPEN&bwH6iws(8|LFnm zsv}ofM=EpewNRvyO+sTI-cQ*5t@5;Yko$`*ZF`q%pdN-o4W6K2Wd;_=?iGJ|TWTX=x2n$ifA5;BZZg|y(pQrR|16D!Bzd0DX~-eiWA&sWqLlQ zGE?ZCAL+EQIZWDpE}m21$gG-RE{UFg>O+_b3WN4bnP2(ZpDv)E$_eeeu_t@SkgBHg zNvg=k3b;)o$TXufmBfnRQBxb8kj-|lJ*CV}?~k(9cXxH^cCdGzQm0qO0*FL{PL+jD zc)~mMEH&iyGyZtl(AV-;MUnFBy<&dC)Qj4Hn9289^IeSl)>WPQ3nO_!6hG2tLy|=u zV$rFJ~sE z;y9^eVJTRP)MyI+7BqKbzFO_IVkHuy#;Y`gs7gOP9P%dJ&flFro)|7w#t8siErW0tcUgl#O+P zma#i^*4G8rq!CMW5oVyojtpu=qsvWX?Ea8wwxbf~VX-L`coq)zXt)q3@7UF?7ihh& zQrd97>wKvx>y`aHG6S1PYpq`AyYIF`%%wF|y9O#n`d4+p!Dy?Jk-`j@wya8Ltn>}O ztxHdv@s{;3bwDMJja3T=&Ccs{7Un(#oy|va9k7frtz$xQP~v<^VHQ9*eBGSEhQ;q%b=RtYO>%-n3@R`_^F_c zJ4tUgk}e&YIe!4dMA0V#&XkmXiFrPhbHD28WaYG06dEqCV5$zrhnRFS)%b`DowctfivPI@7tlKd>Oq?yy`&escT9V6o zC{Py~`0J8KVMZwUsuclAV=vj@#z&W~KYOI(KF zR)UU&Vfk;x%hf4@$c(4}2aP6@;zczivV*~K{$(Dw3c~DUH<1M>O7?RIgR|ZkL(zbO z%d;9$h$?*S6|@ETvOFjzAp*`(bq}Jdh6F!_vwITZ?2U!j(DphnSF5H^_Aw(Gi!Qls zDU23&7neu0`w>1ojrqdR?G{dCEhxgH=kV&g77b8adWj1W?IJBTvvGRT_&C!BglIDT%t z`@)pzy}kln*O+oH61$6gT>tnDzm2@Z#9f??WWm}~6paG$QQS+WWZ6euy1=5bKJ}5Z zwEBml8dg0zp!*i&odQYio*#T3mC&ZK*T9Z()w&De+Kog3{pA1`uN7(yF!a$Y&XqP ztB0(@7~R?UtYI8uAU+lmUW5!9M#*R&d91I5gCgUrJJ^Ja^Ta&eOe$1E2H4=g0$A>!=sC%$qOoUcrakBn7T-_BwdTc}J}s zBdnnrcO87sJL-a40IZO6-+{H#jG}}3$eJe$_LqcGs@*GGPRG$3QL>ul6pgZePX(rt zo=#CAg(#Vyr*JEKavJ<^H(~tTQ2Q|x`gTWSdqYx8i5Hvh!e=Ifo)ypz(sN&&DpZZ8RS*XlG1L(t)JX~Y_0K%AZY2^*v zGYeh8Gc|z~A_`gXnkm^U40v!aObVfiFtEB1=`=eO)5W8MTWnscZ%Yz(pA_6;r|H)r zAQu}A`IW?});ZaV{3g03cwKFDj06rZ7{q4{Ey;Gu3YM zC_k9cGHx>kgNj3X86CZ~4k186sBQ0MMjXs^#J*it-Wwx{NALo^0$oVtNV)su1mZQG zU$Qc-t8;65Z(h24N42Sr!v(`$^`Xrxv2Rc^+fx)gI}FQ1!%2byQ!c!nDLG`9%Do-0 zeEexojhg;j=?R9U`eKnVOtvD_tRMt$vlHrpn#0)|+tS7gLNuBL^kbE7aCS8#Y^Y_A zscnT*;i`fM`zn~ki8pVNSZ4R}YHP7WyUly|?#{NLm|*J%SjJ=+zw{&)tfd_ST||}A zml!G`>KsNaeqlNju-by*sb)Nr+OtWk;;#tF?T*7(ph`v}IFg6}D{id&u+=F-UtBF| zS*^HNwTNIz>ht45v!ShRo&lbO8Mkqso&{W7Td`4Cqb^)?og}bj>6F=Fn6+28agy;= zbb5m+H&$%SqkU67mvn(e&`&W@RGy;#n*B4?EshZ>t~S3KDx)e3gX^Gwuwwr`=DPFd1#{P+ppnlEpHVMDlhun-cq9dxieICM`_9~-r8BQX8Z~z zcvoPX)2IHfXuuMimwmb>nE@(ze`6M-xxZWlKE1KbrW-Bg8})G#b(|uMC}zAlo6y;> z<74RQb#if`F>4K2&F@*?%mtm9F#+<8raNjHaRoNquC%VM0_6hhI+9ClC5ZaFzVF>Wss!>X3hAcCRf6UYIBBAmsk~ z83?@)uZW&$z_JurD7X6TkMEHDvZ5@HpB}3VvqCoM)3D^B?#oO`kFs)0c72XPXgVVQXU=v3mKZ4nkYFL*AhX7TDuiJTS9G*@LXMeNX$AIJFu;d6+jDTl@7{G{Kpnc( z_lFM7%J+D(wa0p$azE;8&+_~&WiBXGoGt?ObNu_@ATA2m$l%^SR{}0ns~~T4c0zQ8 z_(~VbU-QI#Qf`xXioDE1HDAOkkY_Y|gjW-BCqADl-HA$N}1#U~-T)_v2)w%`kVaA)n zDcQ84ZWr>xJv+Xv#XoWfc;N*`L`FoaM)$K5?>xTR)>S@Finny=%e5UnN6s79ueO_V z-J-rGefAj523bBk6X`@iH{lUCCG5Z)apK z<2qx{%P<1>sRLL^HhaVa*&+k{3^XW8=ZqNhkmVeUfvDec5WWn-kS-hn=NF^;11`$b zNnMb!Y$0EMXz~q0l5N=@PT{8*%n>RQ! z+@(FXS}JZ8T5|JkO&;Hqlxf=m7}}9Ll^Hu2iyf79SJP}~tWFmoj&?hsskSAYGx3Jc zq3-!Tu)PqPrAZca5h&S>CUCZrE~2ljNB9h?F&3g^w}!k8-)wdh{wOH_3{uK{h`U)^ZcL0Nwee%Td zcUqR)eW--#_s6Sm8Rzj>qU8k5cPK1`<74;1d1O5VAh93>JC`ED+37q{A8oN1ai1jY=g(40tHZuSkU!fn2vL(Zx09JE4- zue`v9pZ|<~p3xuKM4_Fl&160#lw3;8xUu)zJW1kI_Kht^^+&~40&<|+9v$oK#QRv`B7;W~12 z_|_s6J+K~M1s*{8srj05^{&hu-AA*Q5e_VTaFyR1V0KkP-GiU$pm3JuY;Qwg66gM|a}hBAJh!C|1>1=q*qe5$`;~+m+a5DD zyZYi#=BVocPC(RF5M?>>BtcyCsiCA3%cXqH=*z;NHzqK>!wr`DG)}oKoSc+8wFYKI z9)w(_P%!Za23pa0;maI)W!|d_!dwPkNOf`^GzrhvEWG9IIABaC2bWf$n=lm#7^+(f z{`v%tNE+ReA9MHkw+y7-Xt@YoK}Ub)hCCVomB2MvDXqqk1^H`Y2-PTDDvVu@Nzj6A z6k61MYQz3521>z}<$9{iZ5{fV^REZmBA>1b>_XAgii|42V02bHJS$7hm|bdPQa-cs z7t|scg7enOSh!6_n>c66t>AZh0Ny1OWR7qWBW}!Co00`P?`Vgb8W4Fk;8T6wIRzI^ zzZD8socM;wGQX-61N=}*;XBt#UW81#XqR&u*<^y)0r&Oz7i(PBR zqODwOP3W@%mz1|#`f8>B&I6Urdz)w;4fG zB4Yiugre^ciJEQ$DoEY0jGd9XG0_%7wROurR~C94NF{*7zVyweP>M#cajW+czz$J+ z2~;uO3dVNgh(?nax|^zE_{DE^aZ5Wi%pf2Q>~)kHB^P28g`56Gv`sKj@yteN9=0PJ zrXz#AZ+b_-`;Tt84t|`zy5OBM*4ZK{jYDUKXBtvb16q_cye_{R3@HW7t=w{{63ADS`K6_@-Wg&-_T=IUZt! z1#C5ME7INL_!@;Hm`QU^tTJZXz;~6h-YqvX1q;YQcRy?^?WN0g&&CwclbVIQ9DA47 zcH}^lAmgzKE3oL=XexkG;4vcmV4rJc&j5 z+j@mjGz>&L{H=>u`e;uWAplDq{4HR|DM8PZnGqfx)fu=d&^d8WZhI>o@u~(*JX_1? zTcJT^3R&hllx|La~|UajJ?@li@}$LD9l?FZn&|YW+G)wYq|dl2q2|KrLbNY zyKVhKjqX@19qaoeII<=jpQ2sN11TC4+fbK-dq(~rq0c_g*3ve7CFsB&H{=%UC^nBz z#iK7ocdI&@xL-I%sISmNJp}uoJYiRQ+n6JYTHXP+-p&~?o`-N@_#Iw2&{_Jsc6L5b zqpTBvFO8kd zcmdug)3HWfu91dQUlG);{|ellMM?)S?9~P@V-a)hJ1M5wMcJa&0M?uzrsQbe| zV;aYnDTsG-{)?}xJ8H{jLXFN++LQb*@6<8r@Y?C+6ycE5gqUsCF7uZ$3pXtHm)*VE ztvpcauDet%$?N0qjB=MlG!Oc=6De(cojFodG@WmSFf)^7jJOuydQHJO9(t8Dx~3-|b9It7ry0I_ioSNd`|c$4S1t#1{}N^C=6ZZCUtr8& zjs}7L93bN(R5dt9q4?+Q%ecL~2jH?+XYk8$txN$>&!1{MwaU^ zk@1C%>-y*>m^4k_B-tI)0vMYd85eF;+|VTw+GJ#RU2K;3=kq2N6hb48ywm3sGKG z2lQk7n`}}BWF6+UNT**tX}!82*ycj-nDn+ez=PN)T$RxC&N>l28nPVF8=On!8n9NS zZ>zgDkK0hE>71(o%60j zs|Gw#o8MESE*PT~trLAgwSuQ}sQkRJMdAH_6Ri4Ro2dV z_4?#Q&GvmD=zeX>eVvvV@dx!vbeS2!2v&Uxsg#y5C5KV;3l#htz;EDFb-;!K8vAE+ z5He4m-cx1;R5o0_)xTwItZ)I7vy;8|3EN&c^UH?;IcO`+0^AM~Lk;Ses%-#dsH%P7 zl_qQFTi5$X;`hZ}*hZBfE>_fW+} zAX#9Mf)6?1V#GZT;9F8Jp=3r~@XRwe3Oy-xedi?S4B$pX4v@NaLYT{#VT{A7PkX%0 zxvJj!J{1Jf8eAj@tqW7j@ooo-f9EtBSykk*LbE;c2HkvQ| zUE>|F3#rtlJs^*cp*nA$fnqus(KK}F$p0@DQ}sPrP%v7Gob`{-b#)l3c~rmwiXCUS zTr01Z98$`I64C@o*GZ!aUKp4OMlZVI>PIW|9Qs9TL-I6s^Om5~I;;jz^xXmbTUS0B zWEe5wlypGR+-Pk6rHFL$Ih12rrk|?eji{LM{ZN=k_{OArl2ATlma~1X>ecThX6;(X zsZ0Rycc1in$67jnyVKaIZD=ZxY}Nh@e6PHWW!b(Y3HF*}ujs>6{Eg#H8w$pI4{FTr8Y6N*{1fI$g%D0Eg1k8EdSokoX|R_ndd` z2vl3hUO&GFbY6|GZj%q+kb1s%zx<^p$zcd^MApbkKlJumE82y^zh5v>>VLKh9LY7C zxadMtJ+p7)IlxQ+E*YNu5EJqDD~-S|cC6^}{$Q7`kjGY!~oX0g1F>qeio$Ug^TtJQYwzdSGs;^$C*R{kr*)WVS+@fIh z27qrUsiYh2!=AAOm@eeV#+o=W2FAtqpkz;ai~@dVWi-*CZv@64b}+zIO0?XRxHsGY ziq!+ihz9mm`DS(DadF4nFzI&Y`R2m~bm>t4+R)Z+ngS;k8)30Pf{7PEGdGJ6SGl~_QQaeKyY-UP6qHs^q zpm|X6cxu*vaOB{WX%_~X+HHQy5b42fGPs2!l(+ar0Mmwy$C{_ebc*_ppoTwt0RY#) zDn8%hY!lB~L^5sLUSI|JOV{4^oLG_e0rY`*7r;YZ3HdhU7xYbF+ELtvRZH~FD)8HL zpQIqD1@YOLiB$`?KQy$C(>2n9uiskvU>tR_?{H6kRR z0DsQ_Q`QVE=h5)O0y0FNqO8{=K#=!j~wD{39z>SXMK8jgiLCb7l+)zcq&fvsQ{5{rB-T>wboECUVHl zi_EVZGhBEO@hV!2#Ei&jPO%`}X$j(iPuH!Dse*)UUX3($2VlzCUR3Z ziNqV5?;m`HWh7vJhWk=9FwZD34lb<3umLDf2e+EDd`Uq&*`Sf!J0k?$AMoE00B1>c zX$+)l$H}_K7O9uuTl(1V;ZYO~(`Ox^^xbsZ56fTk@tTrD)C4djcK)KD;zo$OzQ@N# zF1k;c-q}5A(@}{n@XRDOk1hYB)tOoTH1g!Z%KcCbcbvi}44qr-k1lY}#J4%+Uu<)| zQO|#Un=Oe>`wx!i{?|ag8bBWGy+s!M>aH*^Z2%oKEhF-~C4jvJ?~k3MKAmq@*VbG$ zJg5~#8vRD9)~&gKzk_p2t{(GwP?0gpQI>vJfMcb6jhQ_P@ZKed75$M<`$`*E;#3$@ zzW^R{p5gIEQIN?NHK&0CO_v^CpY4{Uts}*lal!k))?*Yz1;tL)pQ;XL>$MbE0+Y^E%lSj6^l!a43bV~)Hd>YR*?IFkkje+N!TK#e zjUz6##T#1WVG}>w4tZzGTbb=V4=-mu-s3hTKU0`-PxEv=7g#s4)f@yfhrm7R=D*za zHr7ch(|XTE2<I^LamZcfM@KEwU}J7dwMa9R*}~V1?EW|Es^dZa~>N!WJm$dBQmH z49N|2GfMXBvP{7dvS2TaW0uTVh3U}0s$T>?fMU^crc$jHfSSgsj@obKw(&zS6oKw} z8$MyVw4*sBsR>i5y^k)?vRKkAsVt#de4G0Q=WeW1w%NBR`HswXz|!%OX*AMh^I4qp z49IO_S*mdlaU{5& z`^!kj!u>BqC7w_Fik1Km%qJ8BFcHt_&Go7yMm!mM<_&(v@t&d9H(*2hmwAi>$<`!l zTw|n!Zt~cuos2325)%bTC(^+^6F~Ex=sr~jD$w%<6e0y|4^_voLzL=sVCeCw%pPHx z0$`{mgef{Dbz3p(Fm)i$b25Bv?p ze92Ar(etS=c8tm#**E$G!h9rDP}f#ZCxsL7NC;D=8u-k%WP3d;xSLr3=q0bt;L`0q zwwVIm4y*Sl*;NLL?pu%dx#zCc7jy7idu%RKatnpa1`2H)ZbJ~A3#GL&Mvr8&((XB8 zMUR18*}Tq|=x7hQlw4o%tq(J+Mb1Ue0N|ohcX{YsnVGoNVu33;pOo`9;V1>46(;81 zdQw%M{*RvMzi`mZW++6HF~;h2M+UkJx^X z?M_q1g6-yC=?B_|Js0z%dtzptHMpnL%y~hUw+qsikwk&k9?L?$Sf@0%erRW?S5=>08jn8jdUe?$qnWSm$AE3I zrVyBg_F5=goC1}D?;ZC9iCTIkRl$@{F`kk!$Hqczw67?M zBp4W3gtKplva$1J8dm^Tajsnp2Uta~w%LqB8^Ha-l=ynTO;r_i`(#z_DzxPV6F>7T z+Pb(~AoH-MYDiu90Prj)Xn;ySnJ>!$Y;4UdRc#bqgrYwHR>jc&M6g`HBg>ZVU%2I4 zWtPnHH?w;FL?01h9S~)73b3QpDsjudXT##i42;!q*DH;}sxYL)QR&f^L;&RheJx zneWOY+{_#AV337oK913z_ED|0@)w&T6^EcnTG5=O z?{)U_m#;RZb?p03hT%{3B)-7%E$})Ha7`9yCs6+BZ=V5$e0*$|nEMWd#e(1pRRZWi zCEBd874dy5q_$cI9m6wz@eFDNAkR3Gxer*<-aR%v#)tsQIr2eYH^@L-q*(n7EI}yT zHVU@_vOZ322gXJvl&m!lH_D7CYZsoPHgM3%Pye+G#{Ijs+EOBK!@`$wO%um2E}N#6 zn*uPRadqP|X6VCZsvVIaDa-I?5ZlxStYc+)EeUr!jnewtmBj_9%Vy6X+2#Ju-TtqL zRxD^>3H({4i3Y}iRe7Q6$_+NQ|_0ASJAVq23xiOxTs%o}y`3kZP`)0a=&%Ls< z)R4Hd(I)f_*j7p_61LbVDX5l1aiM+8aCSb>#SEvOh7cM(mJ6g; zz-a@Mbj!6i{69sj){-K3fZUuAh#l%x!L<J6dsYI$1EeX`)0?7i9>fb$>G7cP0W1pNt)4Djv-msV00sEe&P9-#C>yaV-( zuwa6FTEXI0H=~Ilv`8^M5Sn%VVM6G^KE^LMT1VeRn}KjZ{G)4+R%T_=0AwrDCYx>! zxi4!GU7LSVH|?uUyFVGagokcmh~JY1OM~w8Tl>qftwuk+q1X5Q$hZp3E^3%F_8|H#4(MZvBCj=B&C03~^M~}OE044inKhc~Glu>3Jz2$e0%O490 z?hd2^noShFJ-F=}y7^|KlXZXN!(dO$M83aDS-XnGQ~+@kXSOafb&o_T;T}SMzW;WW zdlD;L!){5xdBWN9s>TWDjl^Is@)!`ONub|}b@Hz$TB;TM|46O81p?4L z`r*@BCu+*mL3XDp?`vBtmcJkOb)19n#)9)mNXLSw2j-a)gcdEoz$C7pkD3r6S4fqN zo@b2g+Y}6>x$$~~c7=b8R$6eEv!np${~M74nwhq)ktS5 z)IXyU;8aNH$9bs>(Qeje6pypsZgHmE>hiA5<@#<{y-bT3G5qFft?erdJ!+0jTdW-m z)w?5dx?kF*!qOT8qeaBsBL6 zf6E^Lveoyi?Xav}QQQCI16RpWG!2Qj>J)Iv|!wrgnkVyQCh!@Jd-K|AAIhd%6@~8{ZCGe8s@SVw)kj zO%~jVlYKD#LsKKpuL|1*baDT|#RC63Xj?nv%|)!Q04&)#wLO#8TA_#z z%wtAE3m)RvV z18e+@)$E7sr1ika3%o0q(%qgF_W&=s{(tiECXfJM0J=GL2FbvGUcylW7~Xi#9Q~~> z{f@^^JvH~?t$WPoWsehnGL=SagfBuCH6A+t_*C?f5jS2sxL=W#n42_V1%%l?SXBU1(+Lk=|S9AE~`2bL0sFo*@8!s9TBT(Vab?{VVq^K**^+ zd(pVxc!A`&aoJFPV$>YZ(V#o ze3s)LgA3_({`%u-mFBaX|1ZAYeV?r@8-Xx7zAx%gx`wo<)wbW1t4NVwn~xa*ZAVEx zhDy&Aq&P_*UFK`0fjbv{8}bZlN709j7B1>V&1m$_k2)o2_V0EL5y3hXt}oE}fTlSO z!hk5NA$t%+o3y?{@8m4n=Mc~t>`t~i4T_N+FzRN7=f4nEHaYL=@wKp74$cxj-?8YI zP@P*tOOe}eEvxGv<>Pt@x4xM@HEwf`izv(W`2L5tI69%VZI*G!) zjX*2= zj63PJ)5F5KX_M221B4ADZ($%Eu27z-e@us`{&=~()l>Rk#+J;I0l%#WfqeLid})Al zEgWVg%9;CROw`bdr;SQjI+Y>Gjr zX>?*EeH0vzo14eJC|`JDivRgj>2dkkwhbkF(G;>_CDwMRn+hCH6a@)#39^m^jK8oN zSW7>}m2@1Z4hB~I!>3XJXxc`h^giLIZz|muqQv}@OKgH%Q#25{W=~)2Ne1|#mr3Ay zpg09c>Z9rG+m&NJOAf<1c1DZkX7>o-H|tp7IQ$<4Ay=mebvk+U8(!^X;)ht7LGs)s ziDKi-cDB7Du)JKIFw8 zRX~}NP}C9D>Ax~5HT<@(QmYyKhj7m7BrsrLXFJHw16DMmUjE}%Y&{A9msXHq3#=fU zYKNq{Sd?wwL?lO_C0#*3vvrn3Iz1@dCHTPn?pdX4_f*#nQ~F)49)dK}VP{GPK?&jD z>@VYnZf1aC6!Fg?71HrVB`A)3L-=FGVl=?E0P*_I^C*&O!j^Vs#P(3rybEAqJ_MI9 z7~w{XxqzL3b5i(QvpqLqFVH3Mg0^KzGK~wL$Jb19h+P?wfvwP*+F^Z zDK!w7bW|fNTy_H~*)nr9eI;1fUFQI>}W8F15#|B=1MeHrT4 z6FY9R=ckStL8WyuH%#NIMgMLjN%orbbp$luKNQJT9i!ZhCyjj6sYT9MJtS^%{2`<% zcZ=cSm}JiHiR*tCCu$P|^(Pfw5~>O^)nd28dFzWkG4i68{S3*ADK(y!9M77uvN+iZ zEO`5hFuiu&+Te|E^35Cx$-nrsvh*<^nv4z@*ZOhFg^X+cQX@0yfW2I^ZjJx+PyY5} zx*8xy&RPQ=(ptG^3Nu6?PO0K%VX8+7 znGw(-mDJO9iY|z@!UF4eNRgLOq=^Cif~D_*Olq(_>7YoEljMhJqXFQc6=GHP6ZqlP zF(Jhz{vfJUm+&cMZQpClTB;^Ye&<($3#8WH){HEPm`)V=Bzea)RFGA+ao;N<)_iv`uCqs%CDU8jEb|A7qGwDcrHD+R5}mt#6y9Ysp%bgbKGbvU6BRwJp+Zi+|*I9r%{R z3!R6$(-`k29cwBLC*+9)O;%#WG{^mh)G&W{G{&$tu+460G1FN8Mjem&la#E`yf8OG z1^Sd}RB;M_2nO7k046qpq;xts16u zpeY-ukXLR;-}h{806lS41CEl7eul^pBy!NTUZCaC+k14QFoX7QK?v2ebEKp88@a9R zIBXy{Pq0YB-n=?s@%Cywu*+eL`J$7a$U6cL4U1wxMuH=;aFIPJPX~EMx2nnR@PD7B z{&#xL_X;A!JEhcW77WOe0rm79a3WBU~RK3D&cm##(08>R)N`Z%meXPzss56dk8hmcxXdtx^46(V|_{`HrPI$fW%i(9? z8@vl%!PzF_JrWc>ac|_pb2qUeU4BW2fi554h637g{0fl$t3mmK+*_2`>W<%|Dn5qF zhH)$a5t~=I=Ho*KW2IAsL4dggB#C|-MdJ|ojKY+9UMs$Ru8e)G5m1e&7@RQS#R{p^ zxw`6bCO?0I6AKQ1(^*;R$dFiUdDoHHt(bVj*4dqMNRgiAPBWxno#5&+M!m^`AI_Ez zM)Ty6iX?2cq`IZj1eo)I&}3zqJa>@3VD-0MpS=K&t3)$q^+=W)GyEnXA5V2C&YmyV zf{>nSHFzQ@)n@rc7YJQ@fDXoDWP&)TKXC6;RT&a-KCV4jD=YD@6KRIqjF!RKiCLZ> z?gSlJxO=#=D7Pa@@Y31Wn+{4v)k@XCN-YQCF@G5xrMAD8Fw|BL7CFQ470w8~z5a`2 z#_v%gqpc_6%>Fy$iVE=KE3!tWihz+tVd{0TU=mcU+R=~PU~FZMPnGFB;>r1*?it;C zTNTs_A5{33*;qS3u5>K?45nFWbT?@mES8wtSTLL$g*f_At@)yY=E^P+ovqM1xEnY# z_9K8YB{Inryn9o9_+j!KO7_!^eoGYa)^flSf>Hh&kv1Y-k&@W0to)|o>2j#!7955J1O zGUm4F#)nSUdM_{vs|?!6HJ@1<@-;L|DDm zUn0;!wvr@t&CfQvvr4f7a@3=D=k>xb(yK3i0xL5z;U2kKzBhL6k+;_hnfMqpeEhag z*_`HEg_$-oNB2NR%75oV$pILaj09F&^U&;6k>&VD@Ryfvz~~@_YNS)$l)|6&SY!LYG#! zURTLDU*<zvtYA2 zoZ}|&z5%y#v-oe*J_@!ZRWb1ioGoBH34eA4MQbT&aOXRfsI|GgI9aS`?tJW^sLmNX z%sVRr0itEbHINErcm||=MwhDz%bPMrK-qZmz%IuO2C!Rgm9I(E7n;5I0c=T(co&CD zZoSiA5q!M++UVwf{Jm$TeiW-ORys;vh^;Sbg7`CVpqS%;DqL3p%z%5NzFDjlV8Fmg z7djxQ0zR`Y#i{7(?vF2S=Tt!|7Q2G&`#N)dT^W&Jz)W<`-@G|#Wo7#q^l7;=E6E^^^+r7)fkh()>`e!cCcZNy!GF_5ltimC$vUWD; ziXxLiD)%1{B>_!!xjex|mbd|^|1W8hxzR!v?8BFJt$~KsuBssEg;@IA#Fqjv46QWF zCiB-qq~>vN!v*oDo+sek@t_@_X6vntVExP4dLXyz7Y72l(szNt9>LjBq)6vVyI|~4 zU_AdWl?&Q0#{TT(-W9bM#}eGy10|e^sx0*YpLKHl`>AJ{=0pJq2eF@l#z*9}jm5C#g){giD6ZIAbJ zu5htc)&^Y?x^z2huL}2ZTpuSe&iu~kcOwAR<>L%MR_f0a^-|3{Mp`cq)x^xg^9Z}& zTc>h0M=h7O5c_M&FC@(;xYojJ54W_r^ENq|W&xKU-P;~%+l4xJI8+05poqDPYbX3~ zW6cU93Nn-{MYc%x*331El#IFjH+fxWDcoD~SJGDmy@;y$3AL2lRStb|*&_!LI)pJ# zTAlo*QCnyel$&796Pn>prwm%yTf{=0efGoUI$l1I&K9xOOj{3b1z=ie zmIX_MxqxH$1>VaC{?qaN^9g?!n)laC7rh~W1@svq&!CX%2=w9cQ&lSjyUfjCb%(zE zx(qm;lsAQ@3OWUaP2vy<&USA~x;rRA8jVzv))3fYP68=D&wbW!EC5zGu%a7LR1Nd0 zE-Vqe7R&?B7U(&GozG~`h=N2Z5JB&Ag?{P z%w~fI^t1~>bH~Rp!hZ#pNC4aD0RPK4fWQ5##sjmXw{Go_o?F*l7KvnUcgG=R>YnVt zRSvj4tp*FvU`}r4+W*mQ(&6)>ylIcpO8p%m!wSRjw%^ZSoZX0U0WO2Xul~1fpBA8r z37xfZz)lO?vfoFn1?+4x2%JOJ0?SOL(f)P9hYL=I{#$RL^#=mP>ZqdrAXDHt+Q)P) zIJQosdx5@I@pR*1aQL4dq=dfm0!-_|6H62@2VcJj%t|(Kt?q*Ndo7VgKALG$icM6L zYnF9jbz$AChQaZuN2QPJx_#eAM?IDG%h5jdL0NpsSicY#UT4b^+f0-HZlC5mNQu$! z_7aFHTePd6&9ljU*yrKVc@G4E!tOp-$m zji~`DV+}(C1Veo;6hKmMVYy=L0g;No^^|Zchb;=SGzNuR+5{`mt3ngK%JI2>*y17R zW~E`8R!EET+csb7M4&{jTN{cRvhqk7&)fvMAU~AU;kQ@-R0H9~egxf9&bikZi7rs0@JCvBmDLp(M;+hJ0rObBVfZfY6M`x^2kOYG0ixNb&Tz<=p`y-##M^Pc$TB2K5*$M$ESS>M)ca`&C>v z`&1(Vs1YC%OGuign^}JPbG!;LPJBl-rNF}LzLMXjG0^(5SeP){abBnsk2L^^#Ls-l z$FC6sUw<*~nf__47r)6sYCO4fL-QrM0iP(cim)(_`l0PV^^?f73v*`u`{&{vCc!#( z=uB^z0(5i7oWn?Q2rfmR)OcW7P&qw0e|_M5DZKV~S_EXz0Tkr_NxS*ws<^wIaOE*$ zzTLl~o2R>TC%;d%UWmkzBNSU%*S{KIUB%S6+l#|wbJ$z2-9!UuLi2ZRalHKp00LGL zcC@ViI0vw5iO@%JxzXFZ7Piyml&jqj3JF2ai&O!AwceS#8|c6f_xQ_sRZADBUgR*H zW7n?#I^X;&(zW!o7zka_Q?A(&b0|Vg{a!vmL=MrEU7$08$fwj<2U%;;qQC)MDgptRFQyyC!c=;Gqms@D8P`DrX#!Y;L$D0bK4+Lv zS-&$O1kiBqGQxkx0bK^SKgAy>)q5Tj2?ri?S1pk!RNr6Li-9^rzoJb$hL#-)m5Mk! zFSaSN@2S{r!;O)qC1Y$i?n23>bhdMTme{)g+s_IO=m(is8@*0n9(O4g2KfHBEJ$D) zYh2KuTFGDa@U4FdRz%$_pa(O?!(e;ZGJQCYwIg1$7SqlO1 z-HGoQ?r59nIcU&FDA69eiRPk5(s<=`c)_cJb6tq)^EfChVS1)1`;v7J`Xn&hps=-zun^aB}&d*&+WKt9Sb?QcQx__N#yPj1st)i4PD0NMsQOt zCNw-pR-I<*dxO*PRg>LSiM6E<(Si+2{RS=K1+q(WKh^1Gb!c52^xv>e$$(?fW4G1! zf-rmspRTiC0CIf63p@>0n2YuLspBY(R~IaFsh%Ly0C-cu2FDK(5wq{XF_}(qv_1D2 zNp0BZHXYVnN>!7(3&uNh_@s(wb&JE^8!^VA3 zBRVAwN`3DiVL zjDWromK50n_6$9-Hmn5U+_!r}?Rx^09Q%$yV03GNSAg{0E}77^QwRQ#9jB4?Hg(B! z*7TblUc3k)UJL*UA|zr{3(gt zqOD@rS$WWNL&fq9U#6&mcO{E+2h;?X{cm<0S7!5+Z63T4xzL)$Y>jY6q+i7-*E1UJ z!Ah!};Mq0C+E;UYUl3q>KW+Xl*i#6I5WLHq_%?{ne}dG!RYmo({AVcvLDQw5to3}W z=+*Clu!)G=C?aybaKNqb%%nMypV$7zErWrT7pEd_teMS`o+IC1`|6s{>bzb5ke8;@ z1~92>wC4uSgH3@qnAQBH*UwEixufl^5ENU7$18F*psghT*VsfWl^$MUv>XG_36~TR ze-3*I7BLI$8OqGt&L3T?HN#g-${l<(8NRapZj@lG+P0w>IksRi|8)ZgKhHI5_kpD^ zL+>dAO}8^`*c0Mp;Y?r*e(2^sP*0!unL1t%+bSk3o?buDyvvVJ6^26Y$ZsB7e&Ha$ z(9J7PAzW^?6M}TeA)-VbS~^g%mVk=4$b83(wQ_-d;Z#L~f#sF--$4|RuYZ)P70xAEf-(w7 z_G7Viq+yai2+YMlINYf}YsF*t=Ct3eb6g00mwX+BtbclC1?s6HS8aVxtBTMY5TgwJ zGynz>D-h-SRm8ITE#c!r_0Te_``jS|H({Q&{0WCE3EMNr;@jnH2PMu3fKNpH#hbG+ z(kv|VE4_i(jn$mT)Eu_RF40P=(;*rX@XcOAzZUT0op6U>sDt0PIR2YR6e*S0xiQl0 zR_4~^)ZP44F|&xJp|$Vc1aqw`HNGGf8D70d-kg9{f>|wW8=s%b=6d}z7Uj%re(|0d za{L&M9W1T60KyCqmqQB4f0=LoKfx&O82_vrPeA;OMk=UamSCx;mD^W3Bo17Ux2I~x zxSb#1@*m*}%aE!$JnyBT|2hW$kR!zl-D`}Sd20eDVn&ns8UG*jSuZp%64;`93IC`N ztgRf5osADTmr7`30-t1`1=tG~ZKRr%S?Vo=p+R%3sK-Y?jRTe}njAX;q}k88%rN;k zRuYDv3(xdq#FA-5-}=ev!DnC|j``dX zUuFCqjfh}R=iNCBekgHYlN2D%IL)dP@eWtcAVa)z!w~aGSSg=PEq$#!;0W?lWB`gH z4QM#jnqzx6Wph*$pPdv!HcKb^jh4I%Q$m@h0YYXDt}c3)dW#18npU zRbe- z^X8%BpeoaH(%zaZ-N}J!e0;t?Ji{44H)Uq^Xv z{mQrkXkFj}FaIT=c7vT4 zPY1GR_v?opJbRdg@j5liR1Danw5#@T>z>GgYx)qo38%iQHsj>9hGQ+6)xA=Zr*($;@qf}=vV+oNU;yL=qf#$ zp|He;uW>#QuQHv#`9r81E5)M0Vd>&Z=2~nip6>zX8xGh($?ID;(bt9Jyu-@n=|{Y8 zt89_(t!uE^g>HYJ10uBllfaY9+EKt)(g%`_@M_LMi%8IdP~^~OKVgx(z>cyoCy`9z z(x;Bzz-}5m49bP_c0Lig?@Zv($urCQ^=Zf;)dC(SYC`yNizK?IG0lxn#z34cY6K3b z5wJ1VF&|ec^pAMYxuY&ft+(IvY=PbbLC$(K=}HFr56QINRu|Kz_5u-g#rb3eW2nB| zxxZthJUp~ZIFWz^QIID#R&~KcP@v`C#^5tP?jGa+=6GiGfl{VG?PVN19!Rs> zt`ouLMA9aA5DCd~1Lm3NBL)^i_*Jp$cTZWz{KH%*ShZFH`6&J%xR$6-F~lucS}6m` z6^|JA1is4b7Xi*7^rdI0FmD@wRAk{Qr&pN#pO8*d^~z8O*A<~IZ-Qbc8?(qE-JBl= za2oY>az$^s3Wv@`i(M}H#+x>KCM27xaa|bQ2Ar-ZMY{ATP|F}RH9?Yt`vhXy7O($= z7VBC7s})X1`$Y`T9U1Thq>+;Mp91?q)XCQ5>5k%Vv8{=*YcHDu!xo5ne*6_OvXYgq z{jONZ%6rq{F*`JSB6srE#vPHN=<`_b)sJucZWCwtsx8KTS#Rpv7%#!S9Vfuhg8#P} z{@{OLp~Voo(gvb(@f-I50f^R``wFb(h-gzC&mwOMJF9v{n&A)w2)@Q(_$7^KzTp4{ ztS)>?zp%+1LO^K_ebWW9vU~jS8?sF`RHA*vdH11#q0JrPcIbo7B4l7gqg2NMk-^Gz z{cxZM7kdlS^W&x9@h>+d-IOBzpEq@cvya-w zs*W}l1SQ-9v~`nUvh%1}D!PCO>6A4d&G z{oIW(ZvlIebk|yuoQPegZ=z}W1vc7canf8UrHA5dGv76R;=V zMQQRj6p{#KRZm|6a|yv$4{VfYvp)Dg+)GY<5<#Dt0|@simgabt2LP;0RT!*=;94Vg zCh%b{-ZRr13sw(GowKL>{#CiLzKI5WDe~;hx8TODIq<4bY}Q_l$MA_S$)^aSFK0Xa z?hBfaQ@xseZ<}=SpZo!+U=+$rP`B5XL5i}^f9fUyJj!*hw0}WGv5#qOfcGO;9JoEf zxnZqWReHvR{ZnnhQlC#W9`Nyb00-%aMF55^qN*uyP^pie#9h3mDts1)$sv0ys5>DoOASXZh~Q#w}YnBW2dFor9sK~w#aYEsQW zBewYh1U(hs?{jIhb@u=mnBNL1+`2UutRQjiam1S2I?GOD&EeNQ-aC*tyEM4sP=Kyy zrlv5B;}h1@waO9ykiebmf)VNQN0uR91E0M?Cb;NwKNNOPz~a>-zq+?vWma7`iLY8!J)g3{qDAhgkv6 z-nA|5&>B$8v)GkF%iTjY2K@6ASL?SE-B(S8k}OA{(+mIH8$W^Uux`ji-ucq#1W zeL(oQ)B-a35!#d}$&6ugfA3vDxsK6UJW*gFtSdt-qE~3F&{My91CI6Ifdr{a zufTg<6qWD9S`u+$3!r2d!di*_N1MOUbhLgB>@Yq4uxnx1RM z60uI4Xt0@(ho7{zF2nzHocXk~SS^bg-C=y z13x}+?yu6(sY($Y&WS_UG!~wo{+9h5?_nvXl@5LD619TU2o&IC zFPTC|aCuJcfKBWnySq4ckTM~TO4`VX|DyGvGG+k7_dH<84g}o17K`)?yM_kU0@0^= z^0glAT#F-nCGcN@O@5Kl2Uf5n%iGtMiETFt2#46L&-*wy;6;tjyg9cS1)GBgUUBxV zgs;DR+rSage4Uf=MFob8f>9gtpJbX?0Ee9~um!vh*jR(beR^I;x_XdNgQ%pqY zdbbeFnH_!(wTHY<@{&F^{?t#Yq~`xaV>K+=Dv&n!BiPcC=7@I>!cBki5!a_3j)pLI z6hn@F)^>ObRnRx?s9BZJoydR6JI*#w3q+_sHmiSNO~f~;BD}!G0l zwv?zLhaT*UC#+c78vc#6GbVYM-FLh74EIr!rmS`Kj`ejaivKB`!VpJYLrHh-74?>!b&C(&yv?b%331_^Qci3|7}m?FgyWh^Zf z=wpQ9!XZ^Xfdbqt2^iKL+pWNLL`D z72gW){w7iL-Sk+yEzvNB4}To)eE@IieiB1V;h3b*siHbdEAq&^VK*OV{iWJbzglF8 z*OoOePyf8Ef}+Hs)loo>FU^HU3dSvc6iuUD$@hU1q9T8?shNOLbMuimpwX)!H$;%w z6Df{-8TStV$W+-mW9xc<16tnzTTcmf69!SGif%!6K;MI_iC<6Tn_;WI@kwH9BkG8#b9i{PaeXA1hdY#+-YZ%DL0#H~#djjr?PpzKzZ7 zS`}gP=1K32Xa^)=3w7^(xdp|RAywDw?SYi1w|eJglFiKVlXWM?qaE}eWtRq&r`wss z-;Ww0G0D?t%8!Ul_yNeQ@aM2Di|06txptDM! z;ZpP>1@n%Gd#Eku_#P@Lw{tKM+q`NE^~^W#rQhgsUcCWb{0B$iME|hmM6JCctxB>5 zPcS8qiIn>#vu}wa_rXxFS>O$!)fCoG)*U=yK*PJ@Uoy~A6#Qt2sSyqLeYMtQnBY<6 zDp8W*q?uGD%iE8k?19?yj~mhyJJDzEu!4z1hY44szRdOkLz-2d@!<9{e{7ooQx(?z z%C)0H(`8$z_qh-jJePgO9KzZ~kWf)#uHRrZ19qY_n79s55Aa^>e)NMhk<%_O` zdoEa;1edb{F)axS;D`-BQ(tbi(GukpB*yovq{v#-tDAocF0m#rOiMS5_zdAzQ1254 zpOJVeFl4nT15TNT=dm~>#D}?!=P}2DBM%JhErdkD#m3+jKhM%LtLQ|AQx&UbRML7X zxbb_cj&F5~TpiNGmj3oz%=S|f?coNHn$S1;eqNTWxu+_omjZ00Tdbg_{8tl2uh;87 zaAUx$nrH9;2d}@qLxeCRK}F90B43Og*&=7jmb7No;jfxO^Xb0XW%#6NG}M5a!2Z2* z9IE5=>nKvnp!xA}Mh3D(YqrK{y$2;_8ZCPQjYpWII8rL8s048BunQzHH812uzX1&u z;%Ps__sH=`jA)H_W%^*HiGd~7J#~lpJDK3AWMNF?z%6ZzvlToeqirtS_CTzsP&iGrWkFS!km$o&zE#9wz%1y_{2LVBrQ z0X3UosJlK9yWJnRy4JbCAsuvxZW3XBZc0#`~#Wezh(Th5IC45KejE0-ARa zLhEY{`hm##vDQ>r71Hst3^>fUmU2`!Ro6=M)2ZreW$N}+HJ7@`Drk7DV6AOflP5dt z*3G>1E}+9e6eXXR-~f|fGHl~w9PhCnR3otFyepD^^o85mq%6Ace%=lp{ZXTZscf`G zrCmo)X_3rYa#{tQFpov$rR8X*_>HI*IUwuPJZw_^y6?w`#J}@S|5S`Tyt=BBkzatD zZ$uCo&P~$@H9qvf*sEB}^<>N?_v0ATu(vNZwhrqV~fo zXomeUw9(loZLJF$b%TlEc5$(jHGx?Ecbvf3o=`Rav70uNNe<565Z)A_?y;WiY0qzB z9Sz^VQXKBfl`hI1QoPb0cnJoPVa9_a$p|#Rbz6c!2vD0LoSLkx^2N58_+V*BPz?gB zUE2A*2DIz%4?&ctiLl{eWVTZbyuUwSZ z99yo+G$D=IavIG$W+ld6P`$DSbJ<6vGxAc5Qs{4W4uUp|+-TS?6i}8|eZpNv&v-`) zHi>u#D$=CY!+b|g$A%qq3~J>UJzm$+PbN*j71cSi)!BSL(}pQ%w5wCm^UG;R?3{E; z6d#)$L2l^{BnNeX$d8)$ceDdSp}BKlDPYs|Yc0{sjC|Jo|*?OF}g338x8XnB=1_ofFOs*&XQef^J!o<3Tt{ML0_(~z_922MWu>264Li_?7UYB*dL1m51> z<1J<8yXasTo|7*zd$7@K`eqCPwh|p-n$fS7`@tVs6BlCK{2ROfcPtY=TB3KljtQ~# zTCPqb%V%~!wG>Ne5;8OZIase-onh7ZHdOWq(^m%U}?6kQYD7~q7&vBVP=`k6Ip$u#ZlC(t>V zXqLv6OUToh=`DdzS{zwPev54}_dnHe#Y~^Mc=tuwa>A}nnjSQF#U>yg?!>=JnZ9B$ zKrp09w{udYl3Caye4?Z?GOb4h;h2R^LScAw9{WgJj3Cix=;HmIoJ}wY6t9Tzfq{M+NWNZTY;HicAn{(c zbH;r%W2@+@)InML-g^RkZeOg!g<_|g+O}3v;;Z%+&^@XV_ zQLbwn(h^fR-R~IA6Z|zDHG7vza>X{2q1?E!Q-|n@i5Lz4+#$r`twejnv4c)(x%zz7c6V(xOhxMv3X?ozk3dND! z)-E?;3(jPO-wXnrJQ$)W^()8H-cy%=#poTDJaHiMxu%4&7F*JK8~dn0nc zD?)8{2@ed=5W*e=Jbot!Jf16Y4EkUJ^Hb!-Dg^dKFTJ1Yqy-9mJA(b2R|vZO8j1H{ zkQ$!mSD_@ssr03v2JmHMpR2%y=nE|Z$=t`KTgKp^FAzYPsZc;!^(Y2vrd2^P8)b{R z2cr{aF(a|eTU1jYITG#4L|}7_f*T}yNmNmkl-)2Yw$}wV0>5O`e?4)6a71c0kRD_c zh|Q4!Hs`$lNLYMXshbcBd$9uj3;Mqw5U%`Z$vpr#Y${D~ zwV5W%w(!GTXoo9%q=iVxZ(vdOZa_sMzrc39hV6fCkM|^MQkGpZ+c-A3wQ!MP|Aq(P z5EVkh6XJbpVQe8pjOD;%Mg%{kR6*mvV4~70!sCPeBT&ReP^Fvy4i{)mqVNz%{uPa^q$55%&7Lc;7ItnKs}=RxDKciff7hKlkZnFL^SFdxBV3A?}} z@x1iorj=j-Fq#|D;?ao5RZx!@)Wsrv)l*sCLARnwJ+%ipbCA1D?V21xSXp2VK85w3 zXpq3)S;xsf-naJ_bkICIKV@TH>P_T3^zT1R_}TT%-NS{h?(<{5)g z8c<`s7`cYIfN7I}%Y}CGnXdG>47h5^c3}gDfW7iwz(jq~@`oX+`_)(X_lfXbI}nSo8*`b@MH9)z5voUii4<5mIH0AcPg9DU!%MUAi;0ekJJH-4C+J~>;&3QN6`;_ zR`bzRaelDufJaTw9zWTFyeyHsP5$;fIW-iF0=2FksSKX8e|Gq&inEK{0QX#kjB^o6 zWh7ji2^)_T8*cO-(olIx@1T;5Ip(t@ox2k3n~GuI!|=C4sOe8VFt)2%acZJ!)mEp-Ol%uwB}~IW zY^mV@sIT6Xd2J)wyL%|)`50IHg8(r$oU1^C8qv~E;#;ZtX8?wFOxG=un;AacBw1`q ze#HPo)I&)>Iivn`^5;QH<4u_F5H~6;S$^pfk=*^jRe#~JGmGy6&HQH4$1w#18@F}S(x?2%*?^96{4mWGbb;~H_dbBEdf@!AJ42* z$V+!XvS;D0Z<{AiBW|}PZD5xkFlyRiZc(!mn}L%R<}x&IRBK~~DvGZnl*ZOHxB26n zSJTszb0Y&Prt`^nmmu*dw|474}I->wt5Q%Jh zg)22t5Wi>mj_AdPlYMf*Ym=-tFAI4u-L|rY>T)H>kFKjIxaUIP)!iOIbiGWPE_tSa zw|xIjHibopTU#1_5?6CJR9`W0&Ru9dpz^QKUDCw;50~;?%6v<7j_X z@UoUn8Y;uaS_+XU*@3oK8n;H^Tw*_Om`lGHi3+RLH;8JdiVr5RTX+Bs&wMaZW!{FC@7Rlc#dIL8gq*(ghD|c;CI`h8(Gczd{qyT((rcSDHT5yr`$gD}T_yD1a6H*Qg;739lOudd_O*3RDCq5G}jk)a3OTkYvefUD&Cz_>uD)BAh zClaq6^VIeLD&Ov=;NzOlMgn7UmWc{BqnsCnj}S_H*-jr-yNi^r?ZO!G^;ijM|vtFHRaO=C^VlWZa)ZSQVzVbc6rPYVM#cNRzr7%=EVqDWE z9@meimlo2qLYai zCJu;+4vYr+Nc7x!)n*Q%?S;(`TXS4loYB@wK2PY}8_A_LsJg zaPx!(XaeHHLJ?}>s{y9$+^(+~09l9-Kc*&CMdnAdw zvi44LShr&cr=@PyTRqrabb3Bv(Qif~$Pju(txk9vVvJ#12_?iLttA-S%e}1K~Mp{czqA? z-VQ3d{WYOUYGpOYxYj1jPAea>n;C2&PDFRgB4@&_OrP(Mqm^{&6VV+}w<8P(Y!*Mb z24RHXdSxVdQ$>+*Ri$@SuLHEoB2=!AX8rG=!m%Bp!*JRU!*|d*Q*c~uV*s`#_U0{1 zjD(6^tB(c@!svJL-Y)n$VtBn;@?Y@;IN)`v@9WSdlet^XW(uJ#UH#NS$@EVP-WGM^ zvW&KoW-5J3ya?RhbfAx+3)m#-Y)+7nR0E{zl&)@`PEIywNfLZ~u4LWY>ES`N{%K*` zZ>;4aBgH1>n^*N9!spSJFkF<|7clCHPv%cAHD|I-#12j76UAKLrLyjaD=|x!V|`2~ zSJaFdUSoj!bJ?LOQRfBerxlsP@Ul`Bfwf{~7Kp+s`rBPnT~x3A@6_8xy)28{7;6T1 z;1R|V8?4E~6#P;WJLfs?5cG=|;46mQ+n)Shg}TNqA&)HhTc{V*lAvU@?+EqtFV`X0 zod-)b9i?JD+YzaMk2bgv7)oF9^^oV4C zXTUT$-OoLy>s|n0=3}VOS!wXAh#NO75YnH=efozSqTB~i3*u4aIX!Ga<%pF5M%JQH zQ*`~<%vX6UB$K7R-%^2Quqk!M$dCS>Dr&y`=xK0MLZY|PCvxtr zH~ipIM}u_j1f9gOy7mnB1{(!hl@E6N8}TM<#(90H=5JMmokpcqVfYe0cxq>BV-Q$= z5?d~hedaN}mufPf_G%aB{{t-sLgp?tI}eTx{Nxv>63=)pv3jFP9$<)2^#0fO(dT4L zE+q_=Fi$o7Qb7X~+okxSxhKqImTa>weSX>x8C^M8zfmdjQUSHmWra@lqfatKJ~qz| z&9zw=uKX%vKs$EaR@M?@2g!ET4?LrH7%~^^gKY^P%hw_7vK#^686XD1 zJ_Yr++)lOuv_+pYoEfN01=NYCSKsRf=N465afI<9P@*M)ToC-A3Oe}ua)g?jiI4BL z&!u9%XE4DPsY(mZWABMUUEjbJ1ti|$hwvaDoCvt+r`+3R^x&?ln(wV z)Om$8{@SrW$jPPsw{N7hir&m0EPfN<`-_Iy@~7}&@+Gqysi|N<&Sw~y`d}69CLoAs z`Uy+BFm0HlqxGIK>?F1uxKI=wXFQm(jVa{lFi?FX?D9`{%7P1;v zt}yFub)-BN7$-`YX}Rx4JLX~$1>>GR>u)_&3)=&$Tf!EdMdaTQBL$;}8K(oC6A({Y z!bX-Fobjc6?PT^+_vEJ4Q?&(w)Bx-Dxt~8*3?LezM0LgtUlOhTu&QRC_VmiuQc>-Q zhvxYbJya(p3?b7;GyZq<;5op)7Qo#OL;Z!+@H3<-)Fm{$j`ZFk_-Nvv?ykgjk9G+@ zN6JYsn|Hqjz69Y=0=_q9{xuww{=IjIwbVkO3l_*W?hJTh#@eQET8-tpRs?)eA;@Qq zlde;|2em~BqAT5QZ7lrEHv!Wd8ppb$aRRW<5d(pDam}k3is@;YcYPN8*U6?^O@2)s zqLq4OhUc=csLYi^V)@g&u7`AH^G7&NW^N~m=Su3lpS-qzz%+azE?-Ew!nC4K_z{{C z^!j0^uy#ZwMBAjB3bZN@^T0m;Q=9#0Dw9lem!KLCI^v*;d?=sJ;{ygY(LVU z6P|Zjs-kAJ-mNWe1e6QP!;q`*-vQPguedS;srA9JCJKV6`3~d(>fp7hTU6JnS8x9* z+jP5_GY8#Q&hva-SQUW*Vq)TdTC>hx1Gmir@y zSF>feeq6MYY4cAK;p;^v4x4aaP78kV;U>HXWj;G!sXL56v!N!%!nsHoN|PZ62%bBx zcyk!))TwG6Lz>vahrQGuYh~KMNH!V+AuOYXg6J?`)5S{yGO%H9&=UN~n{6rF&U`>qikU8oYOIu-ICWG? zY$-x17K&P%W9;zT!Tbdtn1@ZLiXF1yAK=l3#j`t+%o(@u{bbob@=JZgn~XpiSd){a zmW>+O*(g)$@QnAlU5g9Ll5@goLa}XG4vaXriUbYVL>8w4yh!#>Hm49y3Gv9g;zS-o z2@j#>mxBV4*~UK(klmH7TzE_o%81dZJh)K>tQBYgI2At4>!A+nw5sQ_bB?K)%@=n) z2tXogTAYgFj?z_5ZMD4_qD|{7*dgfEXv~$#vr@tbYA1|@0fnjLO~9$EiTvb}Qde*` zZkt6nc_&}~L_am1f&#;a2e{-SzOooMQgKf{SR}IvvY3_?ASP@U!cqOUk-uLG%V88> zQzeTaf!ARw_X!(dhluqT@!%0~eb)7xMFKwI1zjzSt-NQlob%9~Ov;4BV7?4-yESIo z576fO2P&E@@2QgKj@RqN@idkt2&we9zjG0XCei-bmL}(KV5ojc@-Ym|0^7C)c?1na zWwaj-Z$$I7)~XjP+rsyHf0WQJ(bJpZs(H2~j^RK;MB5uLu74YPD8L4D;pq&9c3(pD}s#iZUJ(q9Rf z+mor&Z#`}UiAt9~7aV|X^JjJ$fk}aE)^tmE-t9OKBYj`^%l;ZCL8Rt2;wQ?jM=6q=U6(<7Q= z1qVk`xBe??ID@dUs%5^TqL=Ud29EuMWJe|(7FbIefGANOaf<&bvoQCx1DEtfZ|q!! z2^1a&x87KxT$Wv|I`nNL?t3UgNEL~Y5Tn0TEC&7sB^-ax*Caq3 zlOvBIeWGf6V6#dPFfCeQ{8Knqoz`a$5xq{-pAhyzX_OAtp94?i*Vr}97}Zu}1t~2p z{glgI7;I`XSTWrw|M;L&$C4svjWtKXxtC3t&t|6LgPZg!Ru9||f&;@YS$pYbbDsi! zx1ez5m7#}FHQ7eZkE(L~Ie#&5TWS4dumzyGXh|$^Byf2k!8nDWSnERWmTC=|ma{o>8;=0^xSt`r7?tK> zy~FgQDB1wG{Eb>E?x3)t3o8L6`g|K;X%bYZR(UB_oup7hA0f@`G6c?ocaD?G0qQLw z>G7?w9ilvuey*l~OUeZ@2;@GXDeg(rUI=QI(i3^%JNAK=qT%Z$$+ZAq4^vr*h7X(m z2_OSbM6F7^HSbOpG}Tg`%|4AlV(1m%%48pMUKQakDqj_b;@5|z=fgL6O1v^7|4IDp z1iWp+<=3j!n{rZgg*s6?^Lkax=6s5z_7BI*cBmaCoK`#PSiqhne-nCreW#keB2nwg zDNLcxziJ}FrWrS})jWjl|E`w(FiL@9RVF=o9oN-5(TnO!XSC6p_s%(mkb5J}Cw{a* zdM6+xQe@r#$~5TS3JEvhLV{8$&0%L*+NrEPF@nLNZJ=9<@J|$(9C$UC0*c0L?&DIa z;B5Z%r&gQEHZD-D>j$bUo3`)^Rxugk+RzqO!UsV6C%ICfF?-*M8mvxPbciG+|w;sNKQnK){+bkNGYBqbnGRyB(Q0Z%2h698Ds zeO%B?e6!Pgnv3^^xRK}lp5VToUj`2W`Zi=2M%`~1PM!%UY?w53drOJ$2XTi)2E5?1 z`j{nmhiShk`U7swK`rMoG61PewK7+r)B$N0pP!fveeE#_Y8=}StC>C#8ujR3G3eJ?= zceP>bx>l%#6mg>bu;v+#>0eXla=)ftxMDS*q{+(bhpLZY9>Dc~w|M+}a-lX(#yqT2 z+X=Amoe5HHmLu>Ap|zu8-Vqlqe_P~I{!@o!Yb@l8jA4CNmPlg2+ft@S2hZ}p21l6}JI!GogrQhee{D$C>xFj#@m3}u9(my{Y$kM+}lYTOVrGQg=8BBX>&9T>`w z<<()+gunol_<%xwet>p8(UE;^5i|^uwcW?iI)QPdsB*}_`<$Srecl39DA9VVy|S?l zAhZ3GCKcSxy{n8ifrn28Jo{T$RObMw*-yWe0O&KJIuA+!JuN-gh!*3T0#96c*g`*o zPR(WS!N^X+_3QhkfS%#f5LE?Dwy}g@9FNsQ@cq{{ZOyX1QXhY#20RZJs9AN!A38%& zAFI=MQTss%r>_iG8Z`f?k}oC>OCb>tb}|2lTezjw585}fB@q*;&Lzy~sl7Hi2sn5k zPIQ%&=%}g+wF-M-dpj#rmq0`iR7{_*YJwpNx6}EoV!xHtg_mLzZ;^{Vb}1u4gS`)2 z%~Lo=pTg$G8k}R1;fijDG;P*~o4;S&!kKd#(vr?Ut62_Sb`sE-?-d!*cDh0`0zmWB z%@X+?8N~R2b0&LCI5a*TV53Qh97Q7^82mh64FXw+C1|vNwnmeyE`@sPk)67c16y zBBBF#6)Baf7e5a@A5=rOBC7!n=s>=?hwm#*Vy+skEU#9clMg+l4uhN>eQ4u{ZF!r_ zR!5RIt?Je$ijg}4K!K2P394%kr1cD{EVUz?T|?_Z&U%)Ex$6-a{?_@51CZLoYWE2j z>in=z!w)T|0 z^Y^@gP^B;r`?K=`uTbio?#I5xi22aGK#qrM((~BB2#^}!{V!C3(=`~%m||tZ3G|6@ zUx}G~WfV{?osV>v69qN?Q5Ml7RWSq%PXK|Nhjja=wuG@K8=NEgYjGwCOz7T`)pGuW zVZ~ZeZ_$Bzqj#FOp3V2rN|0dx@9e;^kR3Rh`0-VK zj!xXdduaZ(w+MDFu&`+kHOk+UcNU>U;5Y$4mIBfF$424V|EtWP$prt%2-o>(ClS79 zpXLwk2s?^1Y#AcN#KVpAh80OHp(9Ml3y^|52Ac)Ci!b~`FnK2%k!_wWLBbaVtw^;B zb866kI~dT^YngRmM*LAe<<>pCyU@FJcq{+B zXPh|l3{_Z}xjJJXIulgqGc?rs9yz4J zY+4dEjG$Qfad>thO02Yf32&29j0%yqg%Ml{yduO=GqW?xBR9m#1Y zI?Y#XiWW?BC(NXBPxF7Qk6;wI-xXstg4SQ+$~##f^Y73?AySAIrT|(1VJ*-n} zVoj8u$}eqMH3>&Q3u7FoHjMby%`7h1Hu^QDJ+;}gF4*onO*)dwD*2Oz!fyf|gB+WN zg-Fv(t5@USE8#PI3K|YB{%kEb;DNev57I8@2kq=4cC(o4%aEo0k_%;J3RJ7B`%|i9 zZ7|cEJ_?^a9Nt=Nw=D%4t0j{%y&72EW1^19JJU!@nFY8b5gezfq>b`}QdWea;#^~H zp`PCTCjqg|b4Mm9P)alfV#3s4rHcdjAD)gk&QpMu_E5WJ2yDDJy@xsq*I)SdgOzGg z9^ebKOJ4Bz6}OREsptUUx9mYNv~Ns3DEyOvVdv+b3Pv-Xl@Hl-9;SY|xlPQI)CLY+ zd$~)5-5NOh&b!fqWV-B0rTT1Y(mTM_UrXs4?6Fp$=bX)Z2yECb)C6S;k&wkw1{A0< zim5fYnNMbiYi2v>^IIr#rl#O&;fJ=_U?7Gx-9iGfC;z=Fb|!+IC#9b_5^QrXW4!Q^ zwTS%7F#3{nHW2~mpTY=yupS{PNBQ(vF1*b^*pc`5pbrkHhrFbxz$<>&GbDvnS-}}2 znpixjOAv+}!z@&pD0hX|POwj%D*4^R#dz@(AdB_`yY*885JFFYQ!gi9w+l$2 zCENY~>6(z$xjPN&M1D?7!ra@>Q%OMr;)8kSAoOCB?n--hpZ)umuE7-zH4?6f;>cxH ziN$lvox@Lb1j>u8aa%ffh8^3C#JT|Q1RB^5P*?S`>PPmrQ{}kgJ=0Es+Rn0#r%zy8 z5}J4uDE}jm#l1$?lK`@+jno9s!f|cj90{RB92~hB1ND?CpdihAS0f8@wwc@$)OUK7 zb=;}Sa5y_0cbGQE@iad|%!+Q2L;?QC)*8gmJJ1oaBa zZ6?AzYY-5+R|-z<=A8c|lmke)psY(Q0nIfgPlrwnJd4f=8JHek8=i15yx** zTlvMhmUm}lWfuo6id2Wj--llsZ7i4#r#t$eG1(F*RwRI!zB7#!#1DO^y`>DO8<4Yk ze`GSerd>-*#J<24(7)Rer)!b^7lOXXAcnvaDLJHXn%6MA2Qq%}YJUnV%HolY1`PGH zhfRbYI6w`LfmCIHy z476LD81@9kcOlj0aw@CdUS~qvdLCqP6T& zf=tV~`>NDH{`*9$&BC)n;l}Q9g|taJY536*)i?_i3|&HsJ1%tbo$!-QZq8+woFm+2 z4P%RxDCM7k3bOj+`3g{Z+w;?_!gM5u6aY7#vt*ib3I97v3r_!&ZMl_ zTgnT5WX+YGDNLn7M*~ z|A5Z^hpq3{zY9N&t8JxtrQ}JFwy$xMRuOc@>3>gjSWdwcneix1Ky)PDACq^Ll3$%w z67*QkkM{~@D@5dbEM~e!Ggnimtw{)jUXT1#Sx#lspf7|=8Hg|F5Xs61&6W2C;2S|t zq3&R1p0a)RtVtA{{F18iqs@v@lpR>k0A9r8S>TuX?A+^Vre|$9LU*$t<+ABojw5jS zj$I5OvizMTl<}TnXh4_XujWS_bpPn6))KVK=GjV3d7-SyrTCABySJcGXqhG}a%|8p zXB^<@(fga37s!gYWLnCg`Y_4q^3M~F&=EScLY;BBZS6H%+Sa)|#@%j`jUU9^E?Ia* zDR%I`F%wY=$1VAXgF*Z+)W^4h!iiV7)Zqy?^>1@ljrQC3l7Lm+Xi87TIvarz@~K0M zKo>dj3J(0hJK~D#}m{b)uDF1&tyC0!e@ns5nsB zpdvy-6@(%-2xu4~P(YcI2#6Sx5Rnm95@rH~@t!wUYsd5a-%oz=*UHU(pVx67>uTLE z+?8XY&FnEgySh21KaCdDsMHmLkihYFuU%XW*9c&?wtt{OoxaC2!^#DB-Lu}(L~O3p zXB6wxHu=0l-oBO@DlutlJ$C z8kdr*|Fz4u%+~cXjtcIMXzP_?m&$~0Bk8!};RT)^;{H5f*iat% zqAT@gmJ_@#b)`>(r%5@3&*gK`HQcju%(P97Dre!eG``a*$b1?1AKJ*PnC>)@jQeW@ z`2jDB?{nIOOJ6VejH_-p=zy?>2i&V8y}%blT`jpAquvgImy6?yaoO?V9glqCBx^|L z6PK8UD2n1=Z+j3NB3Sot_Rnsx)Xm8$3Ux=Mf6gY9WKIsX%dHvCGi6fppKu2F(yv?Y zJXvIu-&Z9|`D^e+2hW_7z`lUG5I>_j5@YT#@x~zkr=lv+J}ZrYTo8x)K8%{ih#}B> z_B$JTC(Menx|##PpE6I<73iUN(sjA$#x(_BuC%r4XBUTd1O%hbKjGYPPmh%{TurlbS*WuM!%i1Gi*1e$@};xp)3SSOrvQThr*(6G0oC$Gyfr+d5DuB;+hdn;VR+k#w3t|NO-G zlF}I}27TR?^iQNhc?*+9MJ5E_0kTK^?BKa-;!!q9E32*)4xy=;9rqWEf{(B6j2-dG zIcvH45T&OXOZr~g%%hldlrmt@Oua<)L}8DqAaBlKn{i&YK($&@&ZYO*H1J8f_i_a< zm0U4kQn}>?Zj6tli41%vcd{r3Wn9|EGHhAI*q&H0!p4yEw3_yT1LOS)h4&3pn#q)_ z`WojQZn!#ZN;^7!4&bD0tSVx~^W)nb?~wl#RhBwnf-o}vYGP8l%r9g=@2SG~NhSG- zeGMY1KzdP@Qd!;d9KF~)L@A$}<-B@QSkibsrXR7PytjEGhFFOoAh$}zsjOt!D}~1e zFL3#JmF&gl_m|PJ0kHtIOA&Y*KpuGT=GQ1qE_t>1ae74C@C0pb&-7IC>)ChZf|ePP zv$4Vxte_(|_nS)N&02Ud{SsGlHdP#|*s0rQra2Br(xZ-7TrGdI5W6 zjc3+3vAf-+E8FK7@s?du7{qcuCScY>g6_^Ew}1d0iQ;^TZnx6RcgEY&|0`Dc=IlDb zQ%$Bt7w|*-!s^XvC*vUlvdH}I)k3`Rdr>iQPsXU;{QDW5AG`o}&b7)i9t5ift4(vt z-MrAZeM2#zLr{%jKhQackMOJ8Ql`j() zz?6Pv40Lw%Aw2UU(0Gz##@vkR9gOsd!PS~%uuk4^ul!1E6pG0N3d(~-VDOSMb5Y?^ zEj*dNKrZ>iBDyo#fh{u?^qWX^MbzH98#{_L(>0p8Rzd7Rrn~A|<~k*|Y_aYoJ@md} z{2lm5^%6HYn;K7^Sk-+y_**yeJGl~?IqV&wo9y_ao^@`H{}>ku9#`&B`kdQCQCyouJF8DP8HFM zep?l|Ku*9rm~?Kw8XxA6hZ3KUjRIg_f$u}`JmB_yDFO4irRQy`zo*}?I{fIPS0fxD z9}~B_Dqb3FysWr)uTbYHk~R1z=i=l112!u})bv2Nm_!aTM(A~gi^kLF>!mIK3#+W- z5*!U9Kc-%oTF=?V>b&DZ%5mXA@xw&cIJR`g-8ye#Y%y%hf3t(iPUpxIa>N@tIyH5d{3ys&g&GN<x-2w8cEd5@^k;!?H0OeadFe@bz0I41gn|hx?1>K~~XwavN6n z-R?la>w0CT+uUS(Y*ecMVr>~e$s-(Worq~%q{-bt;c}(1eDvzJbdKjKXd>VQaD}>;eV1p$R|15fE zW7y4|kjrTD4P;o&yzZ;@PoFMt9bC1Wew_b1H`4Z=^i6iFQI}PfdTj$3(^hh|10LB& z@NXkYvzvu6>O|MqDtihfBLfy^e@SF@zIuC!xYT1%+jGe@{z~B{d$Je9FotTp0STW1 z4||t(@PJiPB5fF-vQ0v8cP_qEJ5zG&37fc`F7J4xkBQ6cIkTU>80EVO)1J=5G-?%&%~N>qwG*Z=a<{qfh9Q3k*X@*9GIo zVzxZP4xi?ZHIPG8xVw!nlqMW7^LHOJH*6G-2URDD2M`Yj9q67nDx$Du=5iB8a_;ca zph8MdOFLR+_IR0a3LWHaxuH7dWELmy6TfWg(InfER+dji_do30H9RX@zH}j!tx&EW zoi=GXll(Oow_bR@+OGsW9y*r^v$l;&YvP?_Ni|$$8~I@zTej(o^WnhT?o?}s^H_ry zy4+QfmS0Zse>Pvke?yWu=9K+|?K0E!?Zm@J>L@#!GJ7aNSwhv}9?mnfpsxeXnmR-_ z^+iWPPx)u~R!1XEok?>_8Kvp1CN_18-^>P3IuPHdwFSSivTEWK;P{iO;#JK_-%NAZ zz6KZ&2ll1?RjV;0GSDbN`~(l*+YJ=Za_{1On*3Tz zhG+eVQ36hjzp=Nt_tzBcgS>1}m#<6FxhU-wPaT=MR%AP{ zgFb(`zOAzU2N#7%hz=~$>D@H_ZKYenD4vOd6wdo3E_PF*tzd8uqI5?|OkV>t@UmO5 z@=M8*f_!P-B{*|RSraQDeI2hK5?{|%FG;YO&ML^7vBpZ|AU;7-STu_LvZt7`7Zg3- z#@w8E2YmO26u(wo%9A_|uAo{5&d^cpvK&_ILA)Z`wxQ>-8vTCHcX*8Hsy13$l-?gA zPM|VX>>3Jwr`qiI(iLb2lz!8&` zNjkCEo4Jm=89v6mc7H!F(nmSRhrqZrC}`r+*6>~Stkg}#=%2Tdm8HJaj?cw5+hZr1 z#n*!etV*vjUHwi{+h(mEx&gUQK&$y^_Au&I1G7hC1-CdbORzL(#gYqltYfcr#Pb{<=hMs^ z3RFPa@E8-G#@tXHm6_Mh5J)G(0{EN`r8}n)hP61<4VeLE_%TmJxO z)3IQM{|2EPbAVx4TA8I~u6rKr2x&S2FIqCY?pL(h z63>BeY48=~XQ{?&y+PxB=@247g6bXKj7qpsux&uYq^%_-y~^u78v^WVTmF)R20>E) zpJ)0!2z$)wqARX>UX0prxt@jTtKiijq&sZBh5H3_>c8L)+Cb3~8bs^h(1j*|L|SEl zgF$W$;7^+;p@=)q7l$WXUIu`pnld6vFyd>-AuY_duwo7sY$x992J!cJXl1W&)~bn- zhDF1kWBwbG{gQ3b^~2sLJG0=-n~ls~gwWu>F(m5c*Rh7_YVFYP@gXydrmUO%c2)P? z=HzbzQ+0SxiwP&;k)_BR$o>DMMUHASmyAaepOl;J?StREq4skpsYyce>Y__j5A%^Z z2jw&V152si)ax6;nFI{a1747tv{|rKySI`8>lG2fA6&r|!xwWAdab}7cS*14l<=VC zV3G608BePmW}NsG*r>N)_Zscgzs)9|qn;{HB(7^Uz zPIA)i9Im{Aww%M~i__<#(`)_e(>Y&Ew4PL+^KF9AsJGesh^rZ+O3h zo`+hcB**!`2|mxy9iaPLjqTs^`zC&H$fKZ+M{nDGk9khh<3eUu);3E|t>P~En1@Ab zL3*v_w3L|s!lDIlkz| z1>vd1D#)m*!(TyO4M$;A>W_+sWGgjs?mAvZ2XoU(G}Jg~2@O7lBN4gSD_-_SvmGGd zC<9EQg1j2(M$i$W(Au1@+Q3ym_Sad%auY!KVtnn1G~M|cjOZuz$E`6SSf8@JDBZLt ziVC*e9#9AF%gatZd*#yHcq<@5J0k(=(3HseD|Wl{G(qYsCb#5F}xR|ekH8NP0p zw5c<$^0LB*?yy#n^mime+*E)Q!-(mnV==LgO%~m*#X0g2&1wnIBY5)UBpf_FS7+|v z-YYj)Zasai;8q9oqHFVLllDN+l;e?C9T$;yjC3P@x{Na)T}o-yD0$Rg<*O4b2+ehD zj7u$$I_<?*9+2)fy-r;$&bB=#2= z_gnvIGnK9t#!u&E4~D!gCqBki>aIZysivNWxNK+B zDUC7xuW)OdA}F_C|7I;Omv?t#Tb1P66+ypSF`DhC11`)2EB`@}1kIHi!otG|9|~R) zG*y|crxva_YDLCT#e=*_Hv`0D@%p!Od$w{T{{c$G%&+U6sxxv?CN0pPaU+cfy*dl! zTPWclI1!(2_vRQ$w7dCDPR+^a{zW{{dHin3}esRTc~Qb$&!3nl5adYfP$&29Ay144_>0vM@yOh>d}Y}^3}6_u#d%rhD5dA^Jr6eE;8RK=Wg}%OD-{QuQ|LjqJPb&mXi;7 z1S*FDmF@HV&^&Xd!ZFa7%omzbf{|24kTZo(S*|;gVJ*k13zdD7krO*Kc$ApIwN&w;bY@~X)%2l#G%Bg4iMEE95Csd07QgX>&jgAr zgpbzp9FxS3IaA-ZIn8-y)bG#!kWWF3CJ5;vUElQEME^v;bCrCG-B76(7SRMN%MNfx zI*!O19(>Syl_4}KG3$lWEbz$Ojy?)Z+Z7Grx!Z#1gKD$SA>qk4b3Dn>=gfTrWx*9p zX^aPK&i{0uK1Hgr4qAcp#axs5P-x)&R9-rDaZcW&#hsDBaWN{{;5})SG^akQyHicj z{z!jB9}2y`p65bQ{Pw~*DoTvvg#lSSz$qEoihxuEiF8^&2Bm5T1OG{X2c)<%F}ISU zu=YTua|oBo&L(isf(bozyWLv;CTKyr5Ac!(>q&fekF@>nVHD&@aWw+pgNrR3#SOro(G;U@$ruf$IZxH@w)f-} zCo4<^Y@(x&R!ct8A?X_24C>B@YEVdqf%#9NZ`0uL2eqV^6z2^31ZQN0g^>5zuWadC z7BQ(^_bt20hjM^f?dp|HxUr=Swl$dZQyRhDpn9z>0!uZaz zF8j{1Of}bYb#BHpnc5wE3zeFR=3=dsFr9{J1E7&&W;n$5@x3!k$=eG-N%)6Vg}sks zfJ1SEG?Ue5?#Z)fRWI8dc~{cS!zwf8xPps!vvXZTe)yp7nB9c-vKIMJkYlUw*@?>G z9fikx+^(tC)slkT-h-K9mfM;)oBlVWqBLY`2Xm;+$ro{~Ks;4StKga)vOyl?3IUb+ zDW=I=!(*mks_T_8|H7>(9^R#MWY0o#C~Ji?>H4O1kb`lV3DQSDcR98SGAk1%1f>K?mJFR^ttw3X*zJDN8^bf>J~M7 zzwt~*mU6_%U@*;SCM9S1nVxAdUAO3bPjI7(tJF;!0*WFRR~6q60}VPWWD(4!}K)F=9cu+oX_0;{T*~Rg~!3?AQ&Xo6OQLI zH4h7Pe+@9n@Zj;3gm=WXV=qo!{y&jU~i*S!gvzglR+PX!hM;;=HXM1%52$$s9lyRb+=YLZCF#TrU^_DxyiJVZ0aOi@g0R2&}9tZq{ujTP4x`0(73<8G=yerwR*V9-IT*t&tT z^h?QZOyQ6X+2H9P!|vd0$#me-a$o zAH*Wg3ohM;nu~qj#_n;?d+&8QmL$Gv5hdklT_IY(tS@GW~rcY*7f2H0X_)vz89kf?WZ>Pp0klHZft^?)Xq^tvn-sZhUD|mIm1Eq z58`WNeatg1n7e_^{E^foMZG*Vu&2Gtyz<`O)TE=yZTWPYPs}gqD-I$Ys;AWl*!4~5 zl`QS5w`R*C-ewR#?`bs~=z?8i92GoNJGQ^58xIbx)rB|YWNDamU8K-!E@}01Z0l}A z_FUL71c{ux3vl-onu0$xC7479sglBCZ_Pg)ya~_8AvWsJ+03P{;8KiuQ6??Wp|NOp zzE#z1>mu$Vlz-h-g!CF;Ih5B&Z86LxuN2A^d(kcpn*$b|6`#??j_Z6{m&S~mI2wx* zyGK1>Lxd7X$QS9HyNya1owIkQjqHXTf|~+o&X-p9LtvkgwdWW$2hMy)n5N9s)j>yV zM)BG+ldp^IYN&a8kEz9-wqh>oX?@cF>{)F8wp5H}6R<|vhH;J%d?lL_fD@JP%Fzf& zZ;cj-C&*G4#ZxlpRuXhgu^6Nt76{u)zP&bs?`rZT(21zQ>M8&NDYkcWwkxLpu7iAO ztF%N-_ZfvB%_erA(KhBEw^A_8v0o#K0(!b^OUQ}P4wI0-+hXiV-x;IH;1b+OO9y#Q zS#BC9KE4HuONG+8TbtR$OHen-0Q2`O3xtXFs(io5e%+?No(ZvJ@-D=7&&Sv zGogkf1#eSGkI7wi`V$?YAu25etX$4*pC~hL*X2?tix{YR%#!Y?D!OvWPxgCazj2h|9!56Kvy1Qmn~4{)lP&F3=AA>soz^qQrPL zo@gAjDXff)vz1f9rv^g{zrL{`>tWBG{`DoQD#dz<@q@q>rDhA7|DGh0dwGR7Pf-%} zoDENdhek6rmoom$V}pJ2m&j13R<^FoL{E7Q?8n5DPBxxle((aYjlJ7$5k|5FcLTN6 zkzut3vPou^vh7IT2%=r`q$R-Fm*@EeIDT0;m8j9IxsYJrz)C!MZeWn#WwNaKa(cZ* zwB(NI*t!{cTYbdUdfuzB3+BQ1)e%%Lxf!aB~&yL3jncwYRSVjC}cs3 zOnUQ=Q>!6<40Vpcc1BD7CR_bU773PB#9QV6g)pk6 zYjK+>CQQ}Ag5M5cXR#6be_|tL%J~~) zIwbFPN5|Tjpory%w}6sIS>QXbjSbC>E8E}GL`klS`aoP)ZIdz+X*7B1YYUMGiNoXm zT4RNq7L49YGfNEr-kAm&gbb)a*?rQ6q)J_MD^S<{$8g!5N9dbF&*LsdwXV(bpE_F_ zDmHa$Kj*x6C3kC29T>ia#<>|iFRE>j&eYeis~R^hE0C0OTkHDdf$QMCc-AeCOEFgM zF&nNOXfJ3YPcPi)QW%$lGHwyUC>p-y<5!~MIUS-9U0E+U*f@k#71~X890K6nObwjA z`91AlSR#Z{jQ7{%5mJFPi?qI#iKtZ)FDnf1JiCdjTmgN|%(j>9n0HB3aZH*O>n~sj zf@X(LXt(^vZ zpkdRyCpe2!az#!aqiybP zDR2Gy+zt&$>E4w3G=(+N!Tfi^$V60l-8Egtcdg4gm=k1_zHKhL$ijKJ@FJ5X zG8mQL^|HI zHMYw=xp9)RtU6Lt(D&T|l-6x9ir-nr8!J(bG7Xyl5<*23}NC^Fu9^K!=!cvwh_WF_g=ML!Q7QK;H zf_El4({k_|aG(CQPi<+S)2L}|*K7xDVK%Mh@IuS;&1@SeG?3k%Hq4b+ATJi_nuiM3 zLp1QCuBq-`q;lY6mp#%E)Ab4cZ154Ego|tQF7$2~@Lvh(R#@Fpfkt_Slo52UNL?c>Df zU&F%p4_R;}ZzbIuzM2kAQb#0o_BGmv5edesKq+#!pgy6sT zyv`bZy}{^9TEl_zV3BV=ejg+An(PH^a%y|ha&sLACkNg}dNX+WJV&Z{)%ozaTE2G#1NVsgX2jEf_xuXVPZ@XhRk(w> zrh~}Pb#`&@G55AxY~~kQ#9mfe(_7G{Br&Dt5A584PaAMyZXN$?OG+e^&80{BN{!WG zsdwEPrmknB=ce#Va-?x@eKeva8@LJ69s_OsRgV&iHkm%4t?!YTbY;z0wMr|qoKjbo zqO1m2x1Lo6r?#zQ@gT*g^g6-(&lEIF9w>iQ)IQ^?!)I{%0`xNse<`v0Q_zBbcj3*Q z4Dwn&QfR;b^BnN8BB`WbdKVlJ9M7tGJ{4THmt|XIxNVOG@TdP$jdCrclAhjt29@I9 z=KVx;HE=fdoJp1w`K#gVrR3((Rt3Ig^EN%ARNEqDah{t;5rO8vGC9P(c!f8+IlZ%h z8M$a%zPT|GeR5Z_hWz=Q;HB`rU{{J`eF2{A`2bG}UFc>sxnht_ZZM}sB63z7I9&4v zC>#3Pr$*--jKY%FQC)$YZ-yH%B+U4iT#w#EcucG>0KAeTk;FF|a*urv6QNc5y->~>@dZvd9oBGgvpi50Ig1`R z^_uS)_gk&1n2P>i1{=v^7gk2*SMLkgAV?NQEv=Nim5=Bh2wXS$J2gGiIT$skKw|wb zY3WZW8ZsPl3g}AyVjDwONKddoVurTDE9#vnI%8)%C>p^nnEUc8xhUh;cKz>Wf{JF0 zTfTLANgjMKE9Fr7A11uLS-7Y=axD+2>Dk4H{0rTSp%hW#Pj)_i`Pr3KiZAr3;^sG$svHJ=O1-8${0Sl!fSN5$k`@G@L`jp9lN| z{u*sOrH4GayG=>@yCDQ3OO+%J0tn&As+{WHuy;eqpghDi9a1+5adEDqb;94E;=(6Q z+gp$e;VGAQTm2_wC1052b9NiR?sLP}?zG}9rc6b2yICEpX7fbNS`O9C?FCZRNnsqm z;sP4Iw=g}e^BA%?apvqt_&veclC{GioM-p|!d(j&GRy&3BpB{M-juvL*uDP{ve<0m z?uSaG2cK$L%GhE|v^aFAK(h_EPLR^-bZ7YlU=GnlgEjHsNo!)=R{w>GvJR#0tqq!FkxlTQaHk%JXad(!|Ss(|B`kT$|;R2r^I=KLFPd{*zC2u z3(Gm)TAoJ0AYvYc5o=?Kyp6Hx$h;l~`7<41FT%c1Xi3Hl|-0dICM}Odfs-{4c$Ac(LlhFEliTowv@fG&^z49-u^bkSH zHW6f2;UH-07!2jWfx2yqAkUs;<15o|#y%;h|6fiUgjI25x+P^55D-}_+fe2{kd0BX zFL^grY9%ohOtwcY1vvZfv%g15gky)X3KMrbv!UH8ffxkChojs%Zg&fP76u#%jaqGe)?ix zWoo3acE{&~1s<0nsZ+W_m@vIsxOeOs^JEGm#1*Y+{jZkaa2`DYs+eXizwwVU6+e5J z`%;~Y){nt34bv&K)??sz(|uyZI^12vu2hKFR6`f**#Mjk>H>tDFTkK+jyGN+%}4X% zrBFly9j=jq!0ApJlv?@3_t`on?tH9PCCh=?Vf-|HMln=sKZ3TiV#GBJtpIsE@Lk6A z#KnyCAn%&(^z^uXMoNLn-)h>VP}3IOj&)_u@psyV$E247p8Z3aYW+bU1gRUMvv~#H zzFv6*q_YVOztC2rTrD$dqpfLnaq<7=kIQ$U_;F(bn*zNRT2xSW$nR{6;|IEV>|~XR zzngx^`QKLt3htbTx>p!_O1|WGUBv-z12Gu8<^WmG|3Q-MGw3PyJZ&B1rEs2oD2z7F zdMkn&n6moXL#Kl;T~)7h#NDtjZ|qy0NsMf>eT{VvLgSuY1@S}Y)sS_i-l zGygy&dEiRnxoB@@U7kt1IjrP@wy=Iu{>jxCe-yobq)cpnRPCaX!PnlXf5p{)^fQ4@ zXKwJu=i_)KbiuH9Xt&H_#HhYnVq0toZEo8VO!NpyBRXm?Jr0_io_3fZ+BsYdYp01p z5Ugr%%;bx6>GRPoOj3L6@K#q0Bg+*(xu{ghCtYn?V|6tS$s3V6ts_w-OOfvAVO*=U zIxC5)*#J$B?_r4}ROl^}h#cyj%{Pyp6NaU#;+bjMHa@kCenyt{(1F?$tHXE|s+ZJp#a@Zd0QwuXbDCMKJS#I1?qkX+&$4v)j9v5BKRgnkI zCBKhL>zw&#So&P0XC;kU9yto7`d<9klazzdCO}#*tV~{HP87ZUCTKv8OcFPW@V_f;cnKGBPO zwYg6(D_WiL{tM%WnQzSVp8XeW(sxbnpBR&P2i`eBV(aR_Zgx2#i0}wu(7M^Rn~El5 z1KfeNL2=-9_%t8=sYJAu;7T6qa%&t4anzoVeskD9Goq)OaFa>-5pLbFLp~UuoV>Rr z%F-`ZaNC#T%2zVZ4x1qlchCk#3PKgKsFb&J@}-ORJx!1JQ2h3uMR6oCx8N}~ZSMif zDUgYl1|4qrQz!C)4#~B=d%3K=$VFzKM576snu74o)>hC?0$O~|uzLI-Uo6+ySa*Bymd z-ASOJT~NaWEvp>--kWo&NEqLov`3RCB15VS2#(lt))lxzOy)Y%@zenB^GYT`MMbEU zt%}U|DQY( z)#DM8M{3`OXq`yLh@mPzHlf0E35gQ;=eMY`7n=EsI=|UQw_Dr12sqUL&Z5jQ;l(Si zR;PzV^`4ar<`_N-EIx`Sv&az^=I&cYPDlc%J&Ll%z7>FN^dgCk!;&+O1y|*Yp|09X zaiRoA_f+RcvgDGfLd|%Abq*h$TL}5su7pOPJ-yd_8i&IT=D@JQ?Iw3}F~Ze>hwPYkETXr&ZF5}z9+F}tFC?myohQwE zfcUv&K}a2=*nA+!GiWMwql+1E_l=b0cE0mLvfh|@7r6>f{+82c87m-evDg0VojHHw zQsmI1)zSpsJ{B3ipXWYMjygMcn$Nf-C5ZvQfse-UFZ7A?;l_jt@2h>gKao@qhys}STi4BkukAIbzCA7j&j)_ADDkPw$cBW#;f zeH;>+hDgei%S>&=6$~VbR6RYHx+@>)j=MkCmH8o^v^2HQ6a2FqD-@AqIf}5ci!-X> z?+(BGUo;BgPa0(xbo&)cr{7wToOC8etS+e_-^^kAwkjh2Uu)^1xCE}rGdUo5N?wPQ z)vrOLSlVOJku1zr^WZbPoJ|K*tt`9cY76D;5j%KMRyQXUH*cr+k%xIR=44NGZTkzY zWFPa$_Gjl-V{jh*MTWKHESN#xcvdGqi_|^gQgmVt!$teE@c(2l$iBAw(dQcBORrIK zKg+(vUGio{?zP=&iL#Y?1`RLHploufK85M{v~*@)leJr2Pw&Hnc84L;Xd;-Zln%eJ zv#LK6NMTx)1P)Wla#nFyR`J!tMCA>Z-rZy3l|9Ad^Z4>kn-%}5<@C6W+yCCI-)>HDU>PW-nvB$K6?@ zXZ~d-)Wde2bG`&u8CLk@P!502EspZyG{yBX1a}VEkAC^aVu#8_?2|s+vK6vaJ%^?X z2UgxaZ^v3p^B5>_agMqT-7WW8zjfNubFUC@7UQo3aVhW6@V5_tC6gn|QUn z!@zJycAg>aC@#6MeEg-@Vo%A03H-TN%PF|-XIFU@S9yK&dFD-rJh4sQ&#yLVXmANk zRQr7K_@+sI?}Nb69}AccHog6d%|cqO*>-JCz)08c*EaqDcieyhR~&WHozH z%sr`M{RS!@yeW)x#(WJM!-AjY@PBAnYZ&eO4D-{Qh%A%Ni|zdx@ssTfQ%Jdj9~$O0 z`xQlLV%xSYE})a)@8|!}AjoLF(wD%RpTd&eijnG(6mP#6y2pzT7mQiJpP{=%)XJl4 z@iufO+(XzJlB(fs8;c4HG$b;HQNwAw=;U|q$wlqsKU1^YHV-XzG>jq!GrlqD!Pr_e zq{Rhd_3%#F200}T8XiM^zBe7+GI&m$6h>qzh4SB=-&08T7MiNdSp|xq@%-cqu+|kf zZQEn^b2@dS$C881B~{e^hx7{sAVhOedkPgDu6E^I9Ko@GS5Fnko)f#PIxNOxe)cjX zFnroEH*y`94vgX6x@Q%H^;i4Gs@3S;&K2~{jinnz4hzoLU{vxZEhojy=_Hgg{N_^zkAO=-1o1I((dvQXDpT+#AA-gGB^mi4L6if5=ts?Yq)DZN2zP9;%R=8`ti2Yl9Oq58=xVSy{(c{7M zTZM~q&kUR0#|CYjV;CFNxq{oC*__S`3%jjV-1?2jR)x=nB=O4&&ice*EPoXHe52Ca zVngZCy><`Mw-=fZWUe0n4~<9*)JisK^VrtFT*qr%*S>)&F2s?J<%L0s#k0}xN_Chz z4InDee1*DS;}xqGa&evRhCm=v#kkcHo0R;Aia?7Ks)FqT?OmLu)&zGv#+<#8Dh^aR z>aUn43a?3Jd6m<&j>`p^YGvg8>6Itnxr@k9E^6LuVMBbJ>$t^jPBNa&WebyjYA(3T zmbsx(r`-ojJ1p{4GE9dLBd^M3JgxLi6@A9T$cN!#%qMu1K0fF4ZMDbF!r|1uW8uvo zyZ|OQUF~H%&&R|3#0DK_6K`kDjCNk)#Hon39pg`xw(KYjj*RxwJwLvD{HRCrL)?6c zdzLK5nV%LY*hC^8hgSU<2_>to*wB7ToW_PFmfq>5TSmU0i?S@^(9qE;Z_mQ*UnlMb zCwQk_qKY4iHsP81eF)k*CGkHtWP07TlEkn(W0oamQ^n`GzKrIGUigXb@|>*l`;2&* zE+%QYDC_)#7#^WY=H>tfLL8~JUMEofbMm*{YafRasVWZ}vHu~~Ux{oBB*ir_f}c!S z7MXf|KH&4bSpA?CX2tym$3u9K79%Ba*e z^ynid?&kxYu=TjQHoA~fJr*L3i4vH(P9_MoqWje`JpTizJvn{E&DHc?le`meVm{6# zt`Ea5&G2Yl8X+hla7$kGGBq;?#neEWir#JX$*s!rx4Ts;ycIVU#U7UTq+(#VyqMAXnD~RIF>jC@ z0Bf(eBd3}UBAT&aZwS5JE2^=3t79XVwu^Dln5Sn=yp~Jl1hpFRDC>DwB*gms$Q}7S z{^m=rm|zQ=Q2zFYt&+=KKHLSKP)dgu?L9tI)2lYP$2ZY+(&M&T4aWD8J#_d#uJkC6 z?qeA0m%Pn(+TwBCNm@;4>Z}YnmRFz;&ojv<&t6)S056+vwez-1fsnlP>&*ziQf}R0 z@(tI+XVLGGfdu#n;T||qR&N3O)>6?!5tqQQYb`yafw?fXqvKM+`PaTBS<{NPi~f3L zSk9i~W;@JoyQJ!m`FJd_j}eolUh0z*$DM?Ura_8bIkl1+gA2k$Lp~>_=V6%fjam== z3=eN+%c71sek}=RO4D-=5-f)TVjX2kB?~#9;fR~?Zl`=H zNfdgHMi{9%o|+z~8n>KE@#}|)?UA_P&AdFgf@ZC9#bn`rw9DjtCpUO`_N$CniT642 zljmvMYNLxX3}j;|MzG(SbePEI!8vN<;;MZ^xge5qDwXVLYfTg^TF*<@zpZu>f8Ho5 z@cX>F7m;?k*PTk`&k|e9zbm(sPXAcTQ(2F$$u9H8gm=pt3ULE{Sq+_$@7xVn51(=+ z*9k_2iuJ;06wg*J&f-D3Wude{ZgyJ({d*&O>!O_^U*`B3=?(Yh^}>DCetYnkZ^k`T zfuLGauf8uv+!U2L7h}h8NrUkA=w;?2JTu%q-J4+_mzIk)D{NjWS^7B4FJ2EG;?pG*n`3^Tfv3U)Hnb)+Km}r8V|; zA+53R%ik8=P7$aLVMAZV=|sb{Suxn^qdN6cY@;Qa(HeiVj~0hJd8>3fAO~7V%tBtp zd3=^}&S_w`Uu#yQni z-j8l7lx@~<;}m1Lx@TC*xzuu5yHS%kc#)jtU!8Z-W!lJ4W}ni19gcq0Ho@=pG+(5&N5q^+?Y5H_fP z@kFY@Upw1wvjqN0t2ouN!>e4$TURKPTn<3A?1aiZ>|EJPI%eOAH*pnShwaurkGL(o z7QCU26Gg%P$R-wt2Bi4ar-t^@#&>n0Oy5~mqx3`eR(jS-9Di|PJ=Ave;BS-s90oVv zh6M%>uRzZK<#glQK?7R2HVJca6>%pXgJ7cr-U5cU;PV4{;o+{$Vw2Ru96XfIC-4}P zmjl18tSWGv*=`n+o>234%F=0OBh5}_%0yVHi09-vCc%epjC!!=bTV5}VM%wT$+kyUqGG9=U- z-{uAvTCbMe$y?J?r5fj2xlR}XM`vXb&8X!d5vGil!ebq}M$g-|QuU}OhgoGcFftSx z-brHNcT&at2%W;CeFVP_)x2>#m@Ie0yo8D5h`ZUu>Ze4;BKkQzvm-PO`R|XxhiO08 zw3z(X-Tq2TJss2HV$5UV*7TUP8wnR4^m`r|xX|;JB2eGk(IzJ`@?AFXF}&UDPN?#4 zLyppD#c-b`MYTPzBW)kuBB$;2Pz*2r5DgQJOxfw0jU!bA!5f&(sQGs%-@ww*SuLJCjA_~JPpqVLSQsCny&3pP#d2WefCR(8HYeigJy*)I8k7WX$D zuNUz#;s)l%y~PoVY11MD)H>|p23F9EWb(o72;^HtUzqe#+@-++L(e9C8n8xvzVQU+ ziToD-SQfjz*wADyQ>Ul(1zR?^Ob`Og!&+Vj^l$^so6Fk6kgD@DFOwsmCW&nvediF8 zzr?EKi*7pV&w?D$G70K|{B(!m5n*_4S=coV*Gk3M zJp_z&O7|6ULp7b(4ih@r_eod~i%gSS7)t2drGWZ z^mp|Zg4wS)`G4N*RyDagjGa2< zt@37x`APghI6$^qM!^v9nS zt^5m%u=hN6=cw+W2wFZLAKMor+nUmi%n=$N=15vcAuY~P2sf-3#?M9dy6aw`$n#r| zVA5Qo#fR9$#j&VzuFe|%L2rg)4`Y!)eE$NB8XZmk*X{XBduR{T_Ly|ckELJG-jZBv z>F0uHmR~4d@p#V|B=IZq0(a@(Fl<@Ui86V;5pFtsW}Ndobhh&P{bHfa8cfmFw)Y61WULLwnOg;_)0o*Ec_-#(Sgt-T-D`J2&}IH)^l} zK}y{{(La_&_Kv9z#jM^~;--J=g=-Dw^shFu%W5x@&dTmiKFexzEzl*6FNT>a_Oy){ zU*|2j-ugW0kRfZ4dU#c(^oh^!*;9|UxSPcS6_q2J+~=q4m2=LRcg|8ew}Glr30Bxe zL#APDVn8S+JlwvZg=);pEQL8kV-gwK5d)dLhnEyTLU#0iM7B4>@Jp^TAusF4{?Kx& zcC(`~Z-2FK|J+!d>1~&#lD5NL!f?--oCzNzpC`4Juwg+cVcTCeEVGKSB}IoiOtx&a z(?Sqr>-LTu zwM`Q5w898Arf3CfYe$dv2H>(Rp6DEnBzg~FwR>`$L#H{{5s*S$$aNBHV5+P@QUv|0z*x>u!WX=+@1tyKQE_kxteK0sj`QR%wH)VM2%29o) zFyM%)D?M*~@1+0kvMcOJ=a{Tq>aTMUrlK9luyy0=y-OwMV{woZS}Slg;jO>S1THn) zSDVD(#frD%F~NWxjun3jP##^j-BlQ`gwvn7Y8tRz?>2t)YOGFvMLR{aXCX351aL8S z>6KUsZdAvC(_d#}(gjS-7bIpsqi!vHK6@mS2dk_+A9e(JXKPhQ?k@fZPZRL&jJ6k} zhM0sQBS1(ZGlnqU^TxJM=kNKyU;3%l=DzRi zx{mW$mv+I&4te1UXNdl+WH7B|_ z(lQ`x{7t-A9f}SW<3v}4)%c7*6Ekhs22~Z)@03{%z)Qg)Lz|ywWhg%2{2Vv@0)0 z3*#dvR@sJC*7tBL|7Q~f{UlqGg}%X#-0@*Tj~!K?)iUa6wGHBB7+0$4I2V*snd7`yBH zGR$mzy8o~9O>fvMOy)phpj)30ADw%!R|b6e;;!L42S&8>ZPs9dHb{HzZ}c@D_Ofw*W;}=D zS*gRDAB`Q}ZiipeK+$Wy1A#%MpBdKx!4Gm^@Ina(-LnVA>jsK_of8#04L15uwk0aG z{dlx=_d)*8O8wX`fyCJBMCzduOMYbdEtQiFfs81?D{$bN9Gh=Fb&u}=cP4oh2uZ_n zibI1bTF!=ZJu;-%HlYT5oH4LM-e8j4xqz*L;-xq$U^X)o}y?`CR%(#$r9M$r6WKKGnjJC zed_;V^lq;VD3&D;k9;&9Y+&@~>3jJiQsza?HDxK+t{Vf8)@1q^`zgs-Oguq0y{p>_+}HgKg4HN_SAM&BN~q ziy@D`HM074Z02|#v+hx{_;97dw??qAz>g?RNSnr`=);n!TT(TulZ%OTPTz)Xwh7YA z1o$-86z2+vyS&MGcx&IZBxEBC4Jg@(0~l7p#!s%J798dn<){MsRCz~N2JOkZL(|S9 zrEC>&!$2A&c~AS z&U4kIaGZ>12T!fCkTYcixZjdN__mLk&vpxpx2uwCLBeAb#o(?5+o#UGOzUe084OV-CQZF+TH?qZRjBCj{2!oYf7q$s1I9(CqK2Hf z2ON68*eo9@rbK*MRsFzbP*=_P!|IW9>XoOiCgH*vGaVoCmcA) z%JW3O>JTO572RG3aPCnsEoR|XYRoGG`Wd?8#qf3~g(FyEp~5XPXejU)HmGuCnPzIN z9Gm|QT)bNjlo-&rCSuvT$W7|vsOu5!V`~l7Y+>1Wb@B5}wb;J4l5h913O6Fi8q}4S z#5>eI)i|Dd321>&~VD!3l$$La zW8&}1hvYt?lYxkVF9i}GE-9%9{RZ7=K&rSIYOmy;Vd7Q#97LeKa}uCZU#U{Gcol)_ zEsai;FF12gyLDc?w=ZnhNpXnH5ow4(|k584#F>+RfVJ!xpEWxw`g)bfm&H1?mau-$t@#T3A@+v`3_P0Dp)hkN-JYO z<)+9N$QMwAwU3f+y}MU}dT=JejC}yx*$;rk6MZd2QeB-EokyAKPZDXtUtXX3tD?kW z;;SBJ1yNaO?z2?k<Y45@GcakaIgvFm z@mz{n;HWJKZ{1@VzCZc`_;toEnK*wcvTh5@58{HJF-&l6@HiZ$A(9O}@D5mm^S;OM zc^4BW%eTC$tx>#Y$UQG+YY5{}28GEc??UDs97UAtr?kMCs8!9ZJR1_fM5vXEwWb5e zc&=D{d-CVVBaaQ4_$9eK6K~n$B2OZ!L;d*G5QQ`U#I9_Fi^2}I>CGcF`ZMR(X_5sk z+L&Md4Yrg6Ebw-i!dE zk8B;FTp(MAOr&w6AYUnH)&O#Hma4#)I1!|s@9U`5Y|rSII3*6;E$%iNI>UKVSZFo>fg_A-`|Gl@Z(Z1N zT!-NobG846L~Q;!JK&QGzAGoI{XYHN$Rok$l(Xam?9;Oy^$E|W-4SMUZF!0D1J0gP ztUJXH$tHfVdwmCzz7Jn!x`fPqZ296l2_~%Bhj5K((52e{3Wv+$RsWtNy<751?E_@Yn#G=kL0?K5}mWFGyE+RKUHB9 z6m*O?@^v>k#hq8n&sA(~VT%G%O#-Ma?x5vxDXGwTdRS^(yrVL_`=$b_e3!N6Oqi~ZG!>&~WH9ACeGL?=W9otQB0@ed(} zg;b9861MGagF@>)_E4abt3$IvUbW~LHj4Z||d@45dk0=WOwl>_E(c3zC zVkgWUx*v_ww&o5y_Z)QmKiHIOvFY?h-stG^qT{xe|0Ps_m1hs*7j?A$;)!nI`E8?C zzT8NK6Wx{2?PH_cn6t#zeDIKHM}^641<{+MJ;#?S#d6-}FzP)v^qh(xSA5P;F3(e! z^N8d<^xqV&>gGQee>gN3J2VlO@s&W3EkdBUM~M`d1nceZTuOp4Uc%dM8JS7(Ft@Cv zN+!OUY`0H++dixHy|ADlc@>OI1}f#-nD}`GX;3cZE#3QC(ltv(RsEG_Gv%r%)MM(! z{OGC}|I2D7ay|YmO-^4bfaJeYDHm1Wcx?+oHWj}ryyeSt=<9$*tYLFi6eUEglZc`b zEK;0D(wdS*^nUXcG#<@O!PH@FK&5$Yv0dAQUX=$!Xsgh>i=uwzQXaPV1Rs55X`O{s z{jWp{|KXKiITVna<3;og#?j7TbIU3%b}bU3m3~ZKoo1|hfXl-N>+?+p$7Hbp)dSaKERY%!}Nd*z@KZ5zKK1uq>Eocsw%>t{N8_19Grsn4S(sACY)~ zz2}=p=V8k`)H9ngUzwAWW*j{mykZ9v&AEVi2YKBsXO23qC_jMdRB`bbvmgIZa%;uQ z0~y69W*gof`GL1d<6L0LxY0jRCJ%u!$%_5aMA-G3Q3gcNEdQ$t++we;+$4k*TvD4x zDbC|v&w$CDBL1`WWeUx)2|}~$OzJc>iXY{^kj)zL$d`Mx0OM($&#yT2$OAJj7-?DJ z_zkq&FvkMJOmulf^*1C(QJ8Y_K9g1KL5h%Q*%~Y+t+PRf^wGCYi>h1U)#EJ}T-frP z7l7!Ec9JuPbGfpfN$~MzR3S4C5GN!&bKYd6qJn1G*%U5` z=6yM)>j~NDspYL3WY#23W}szMe;1>DMZ6?;5dC+53&YHg5a`u~zMFyR^NYMWbLbqd zHK8eqiegH6LIXIB*4vs7z0qL<59r~IZZpc(BjaP3W6t9m9(o}tTR3*Ra~5i7YS4>p zuluo}Kb|;P+n! zU3>mX)p_DbheJefftpCm8GSns8-PV~G&9V>kTfv5Tjk*siXP{BCj5EeZ}V;pHchJP_{LaqN43UhlCx~!?9VhtNu|67J zHF9Yl{E+FZpnbgCf}M_u>>bm&ey8#sPbfq=xMl7UQpl;oA7U6o!6B8< zCi4{tXHr`^nT4x;l4K_C|0UYZ1oxuR3|LkWgc(_l*bl<99Y4d!B{kLIfd_=4sD3-V z46_h9M$@)<6Ccc#ENa3>`Qv-%R9njc*|ni1?g+!;?M#B^DePV_$sTyk+z|_kA4doVq+ra0a3YBEZ%ZpUHuyhwCAySv1BP z9?l9FGRLxWd9gbQeSpK`96uH7`P0&KE~-vaOgXicL9xVgo+1ow*DKSRP#Lz~8~yaJ zMwDS4^RzsyHT4PorVk$_BF>W_%<69d1C%`HJ>&gjE6T9yITA|Ds`x*sG;@x=%Z~KvKf!05n62R)`>DamHIJyoKIG5o zOjdpA3r;sOuNqK88%{}MFEZy}k`>z{XTu3*Y6!Bgi@?$i%`J%Ng%0ursKL@~zRq*> zCd%3u^86gKQ+QZeT|;DhpyOQ9CAWL%j+_)s6QCZQpYW#BsF9DXqTJOIQ zAaz^UN@Hq^kG2i^UU72W;HO_HvW_pknT_eUc_liwpf3FD_EFpG8(LkBI}jR#9dixJ zH`LLfk@g&&QmB&q{9;q_=L@UgeEgfwgrT>ie%07}s-R__pkz0!z8lOmLJ}Ow7cTfK zGdOx~?i~X-bMxtlVI#GH6R@XN<_(_YN;+FB2dZ&P8+gK-R+6665nmp>1y_kjE{ra) zNFR7w+|L6C;*9ex`ba#@$aT5117XT~2`vAWi*m6hvineE(zus7M)F|9pP%uO^rAU> zpGxXt)L+rZLN#DqLAQrP+mXrEg6q%I|F#zI1PwK^?q2(!IEr)f0RE#?IFxtg%6 zi^z0}cTYRQkEH0auVc4UQ?A0iNGz1J+9N+`f}2qdk6?f6bIb353;RbG$(nsdCWors zxY7->+A(y?&>j9VkUVAGK2fB075tluTU{B{?64deXj7n*N=OPIjmpweWYxM%w@kh2 zu%JZDqik~p$zfI{GJYnLSW=CUAE^r=wsy8;e z^gB}5uJY2!_AbT36Ae3XbrB0HCi^Sf6|HuQt}42kN4ns}-=YKuFnvK8)Idkt#(gM8 zQi5;=l*f?-LC6uaGcPkqq5ViB9qoL45?3q0SvWtL0!aXnmfl<%{>-OSM_JIes#b$hYry8iDNAEh}( zv=fgSS^eDZ;hO*=U0aRpBpur-mXnr=i$X`k@b~D7)oEl9@zY6n!f+eq)L3IBV<&W2cO>uhqmjwYHNgH=|38^(qekrrV5ExmbPS?haTT6m;!AOG zpJZ(RN^kV@D}X%i5oMNT*lkq(uYAb8E+4*jNPdinB6QQc8bS$77297k?Q=VH!k8wR z-s-WmQn^HReXdcu*f^uuXEq;Qrra73xS@v?H*R1PP_3)S!p+iQdlA@2k&ph71#u>*ZccW{MhY_JU@o{BOH7vi1|s)j7I!ymqpeo^99_(e4qM#?Bd?FOuI zPbXPc&Z%H0gZHTT(a^j3+T4d(gu$w@7k@)4KO~5v&l5q=+NGo~3)?~UZUw_gN3z30 zkzHqa24I^%*lPJpHhS2gjiqVRaUJcEI-<660(|!XbYxB%yK}*nde=$y3wSuCW9cccP4`XqUM@`{BoYzR}T z3}1m`i_4BZr=|*DP=u=Ing`e@Nshpn@WTl=RB^)$N;?b~Kzh_E9~} zvPODpv}&OVgeJC-A{;e(OG$=)3=8A4ut@|0e389RG8?K-SvwsWVpStlb_~ekjLiw5 z{$Cg-#*8DFD=}UHB=19VpO1g1_2}3mMKEg>|J1Mxv|-0pzsfq09@mcf2S;sP_%ZkR zDv*_TPX*?cl8%HAt#(_Ai<~%!sXMl)VxqtDUkoQs9ID`Ie+wlQT=VDAFQSo?`wdZE z6S0&Pwq23AZJK7BfNn}Obau9w?LaWjaX0gKF#Rk2#aWy7oww}#FCJ*H z)Q(vPQ0LDjfa|e}XRv}rB2ed7jeS{`$Upf{;?7Alr@-Zs`UcsY$j{fVO&8xO{NKC@ zDQq!zOt8k33vSK{KX(Kf-^fV;&*!T~GV!mPPIeK&Z}L%|qU6PB%=0J4X>Zlpk=n%I z_QM}gPmj!UQrMp`@FwB3@B9xrFLzvNK@d>9U&$qGiPQ)0SEo=N(`Wr|gj|ceFieiR@vuVjlGiv3wwRCTU$pn00?=h zhi|NV?KgV2i*@vmPFvbb@Ii5df75`lOT5ud&GI;!3!3v?9gI;))}a6i2FwVWfYU_D zhjUQ_etJRFVYmXp`8T`mlKAe!c4x^C7W0l8(-bJTHe8-x;oIH9>ormyerYo~w*?#9 zaX9{*QHfturE<|0L$iXc?;W#h(p0(jFx9~p=W&Q)OYGXrdt?DoN+y?6%sG=q_d5dd@8``zz%kj>dr|ul zmJq%ZXB^fWeKmx@2gfn11BHw^E%kmqK5fB!)`lxWe~MSO|;0H(bC~y zPt9(CW~)y=?gcN##zj6hzglOJ%}3!CnXnc9N99qd0nVV*NNoOGT;2n@o)-b!27IG zglj7{Nz{=g)?FSoON{w4dU7l(b7vyu1Gt3@3pZ~EVxosH+4Z#B#~G4uf231j(0*2q zLK3$;RW`fW-^c%nCbuyJv7r=0nb}V&a9fTBZ=0w2*bJ{iMCNkT$2h}JrVax>+1lI~ zLlaf_2W~<#Ul$t?S4m`lp#-Q#yRwQB?y0)2?i2keE*pKvOTFjerXo!{i{xVTc+2z> zU|HxAn2KH6p|@3tpXLE~F{PC-a0u>6K>YcPDNH`!X67q6+%&mu$ce+cMo4?3C|HY# z)M&>3s3I~GZH4hh?{vwN5@_O5f%plkW|MW+4soBA>MD(*HI2o`uboL1KK`pi_A8e% zYKtHJ)gg=a{87$~v#<&eB?bcl&Oduu1W?a)Udk(q4sh>hvPHOW?N}<6($<{`W}NS| zqjYbcLe#94@ojO-**EJ5DNgRjXNOTo7x>eDb;)YeJ|!jz=-XDZy(BNES0Y1DXn%aQ z&F9VgUFj|LRZQ%Lf-Kb~00YgnSUI+YQqn`Q`A`nLVT;@j!zvqJ|GaJuBitO)A26fWkl;Uj z1mXn0GVDIkd=cA^51eqk6_LGw;%`cWTP6$t-D6V2R%hI1;_sKEZ0S2}LsemXq#2H{ zmA(?Xob9W;8sC2M!N>>m`5>Tq!AyhJV%ysi(teCd9C&M>%>wa)EGkw#w`JfWIZ8_- z!sSlQdckybWYd_j_{h3LzFiH;_4`qR!t zwvVmr&MdJ8lQ(K9Hda58cP+%R^Day~Pr?m~OSt%j(ss`G*vOBggsyW`7JGbG#ZboL zAWF$6zK0{me*88j=jUfC9e$rqq!&(Vs*>6@m%qE2BNi`WnxD(@s_ZD5Hjo;7I9cw$ zN3X`xpCT(pbCcX5$b+?evVd@oZJl=yZ9@iFaG(xDpf;kpcRVMWwggf=3O;&uF=nDU zFY_=b&%?i5lNPKrV+6+Na!N&bN3d8uPZd7&G{=8yr>9<%w|G9vKCFE<%znpf|51&J zHwr)H78HbCc8OeZ*^}>IJjId&TNStX{zwZ8sDdAZ8|+koKb#>;qVq^YelX=KBCf=7 z>h>fviiUSak$;B9OH%Cv$;Rc+AZO_~_Lix+JT+otAJCGU>dbW6owq`L&F0rx?D-;D zjfvdQDihP6yq{u*Gx1&eI-JZP(SdKk0(R?^_~K3Ie*L>iY>^$UZO}*l$ z4N$2H&w};$Y}J{7sDj7{{~7qe3IMy>_e%fDpfr|rPo0cDCo?>qu6JH?*CGDRYj7jI z7)EWl?41@7e>Hp^4wK2!{7Gq@4cbha7TnayYGAwZ1Cp-_!88wXpUC`@8RU6MR)4(9#C-8@SsbkOW6szY)U!UN(TST8Bfb|_@$r#oyTha6VH+{Meut>j zWnQSXoNG5l$I^z?kMGI_@O~Y&!>8+pyUrA5t)uqTf}6rq9@=44lrUFyBreZT!`>=< z|MBLx--7>n3q1?6eso4K%rt_}^0*hn*ntxS7@)xwLW;YWVah2Wcl#uRiwHb!=ZPyk zWosAa76F>r7emCoJ2?72D+zAXMC`2LAC}0%UjV97xR4QAFkP}hPU3RPCb&Rkty!@vahZ78B-zuN9RruwwE)MIkA^ z_}Tler&*4;vxa=z*NTc^^0BIBJ53Am(^ieR+w~>U#Db z1KrbChFfLhQQC#(eIJ8A%H+I3D~1VOLD*r z0rrqua2bL-#22~b1n8nM+QEuf?BcVk9WUqNd;ba`MDq&dS8)lEZ2Jmw|AilR zcr&h?5&(7*&w>fwU!_FI=OIYJvlmg2Hd%VZc*(ztLe4x`5FZyHlgC8B&&$# zS>N(TF%u)(5R~n_e(tTNA_E2;?sEaJ5|0#=o7v%$Su%c)0jguXCyPLZ$mD5owaTkB zgC;sF7mgW&KpG@&FT4{8anguBG5&(T+A<_Ut)S$zYTCsY?eWa+zmLkRfGi5Y!zzS+b0iZW;5x|>}hyo{s*oCU~HFIKT7UaL#^F?WBC znEFI&D+_DGjvS~ss|k*0Brb1|D(s9U}sft zubmHfg8T(pd>Aba&_+M*oYvNeaH$YV(| z2wUJyd{lI07eDREXhFG3z$o)IV!$;P3!#ZQ{XEZ=k1p}d_b?U31WDEP1gJY zXY@g-x|-jcsrY5YH*$Nn=~`7UU!;P1jSd+@y5gsAN0`96I8=iV?0xm-kc#)QYg4 z9!0+K?tV>FP_E7K1c#?Jkr*%FpB>2}lrsXg?+0{Cs$;JGC?`3Ub?{FNN9Iltvak{* zm!7NfCC~1qv*^<|Bi@Z!a;7fiOsr1zOdhG1Y3M{f%c_Z0iCuVJP55jZJto6vAffVb zz{KFkbmGWkac7a(&*f*kT$uo{TIsXS0sY2a1dW9_B53R|-!9}&@nD1C7kY`JH1m%K zNOx~5caZH6EoXZf?*rQ)2(hWQQH0;-g1rkMmFL!_g9VJKgXa0a_f?hVOXLPR!_P5IG||26Y+lDygM@i2t>mvVolXpQT~gd^;ZmN@4pP+h??Az zD&aau(FD_R6@@F`V_P|qY%T)7im(|+^cb+jScO%#1hQH_-2a+J6!~NlXgjLEJaW0* z1ObjYb0WiXi>AUT8QAuaKT0*gx4P^0{-=zm$dAPD+sZK}dGR$U}anLWtBj#=CQ@(7kx;&gR&R$x!@k-7nv5&h}??tFRLag%j3rC>m zVkq?^_^*Jvz}=$?r+E9?lt9%}9h)-Kl<-%L{1ts9$Bof3M+*Ty>BV**n#tPmA68~V zaBHD74c<`6lR7P!-fFsTZpGZacWVO23i1g5t9%1tFlX6~Unmh1zPhy$XV&{B2!DZD z_0CH60aD$1gUIU>TYkEpkP?-(igQlUc&y4}o$26CL7j7O@117^0bUw zW&zPRid^J%Z+i%J{)w(A@@$dBavo>xC`^IA0dN7>Fo4Hm<$ymv2K)dNhE^_WEA7-( z;gii(W5)rJRZ4co5Kpk|Z1D$X93hD83rn%M(#CHpdbEg^nM@^phzO87>6W|vA6+4F zMkS*E>NT0xFNi%p*?mdpWbhf}`&Uy)v!$mK``aU%BM4+XfdAr|#P0&Am<`Y7g+$9~ z2k4*dzO^vQ+S1co%f+hlkbysVOUWNP4tpn+Snt>v-ZpFBiozG+s4L8R*`0^E=QF2n z<|HSy`a4rj+2+c`KMwj#L8cs(*KI@*5ILsv9?h>ZDJQd3O1M zG}u1q=V3|lZum&vu+>>_Tg*A%?L=QL#~_*v+*AuC7$;1MFLs7nSK&5v6bl=VpCbl5 zo2oKoY|Q0_syWgY?#L3j!JhH#Q9|Ot#hE<=$@v`tS3E{?Y$&>y|)j4 zgFeCk_?rucc@xd7Un0qa?rN7Mk&NzThI2!b^D|FfgFG!02#kZ~h>!h`g(jfAND`mx zxnmMxpUe{BQ_{1mG%kl@!EQSh|snkvabErrSONB_sR5 z=K7lr%C5|P>S;K znfBz)?52T?N^^x#HG57sgE7^IlA4En>cbW~ArkDr&f4`_|%sPbnXGUW2 z^Zkj!A0XBbRYqYA;7(7!JU_R{oL)0ea=;F$5fL%+uv@91i7v54+V2o^M++3945{rd z8)nV;Mg2E;6EPiAMgXC5#}zep()D(Za(50lK!8KIEOxB-_KJF%Zx{qOe6xM-IVuZZ z`Y%Bv+Eg%d9xhG`+B`{1IPPG21}18IJIQ7PIvfj+`Q`+LKDR1`+>;b{EsgUofytfd zsRZBNFq6rPlh8|8a=MS+$Xf_$^%*7GoEU!91s~w@@yeG`zvs(#adX?;Q2UVRJ zWG!8t2R%u*l~j<(3b@spgX<{55qZLD6)W7Hgxj8kJ7>-$i6M^r3`b+kY!0iX-z>aU5Fy50L4>(ArzUyLF~pF4Y&c7}d9_BT`LZ$N-kRYg#O z1kLbl1T(h2BQY^qsY1lJb5PWe;CXb}YaIjayfU<<3B6fUE5oeR(xZOrK0aPq0!-mk~#Dgd`|01Vl9F!+IBQHI_n(ttFYhtt|Kh`bEw3RrJJAGu`3T?gj z*tWyT3P}pBO$D-qi(8=Hr5Td0TN`*3xJ$(~Mv{26ZIj;eE<=FA zF1meHxVQ{+2}zL(E{^HI6VBQYLi-z`;JBi$eBA9kuCtW%Il^yt-R^&MVQhg;n3}kc z6_}2b^XjaiyqQ@6-NrFQu+E-{uJ;Cq{=R_RghRX)AygYRwtDGY2^`@oh5I!sZN5zQ|A9jI z!1mkvVmSQPinB#f%`rnhLhVD$jL*VkZh?r~VHryH98q#rVf$H-^|;ZREL^tF>;D#) zfw8l)5Z?3%)qOjnVg^_znQ;kTpI$om!L`_?-1?cKj?sIviMY%}h4N?Z-jOUD_6aek zS8iaPS0h7Z{)b-lN8S9UoHG-+mdaROsOcw};7sg7h45{^FbaqL6{;)!`crYcUd8^o zhU`zLw%^ChEFi&WpV-Skepqo~xKDp6d}>{-*S%yGcJoxpY}_tSc+dpwBPZ>mK^FClFDr z$!o~gZ7odM&)4M;$6rqN^_0z^yHhO+fBz|<2GEs;^@mC z!&X$E&BL<#3! zLoHdW32ZVHj4#&Gb-Frjn)4ga7Dz2#Ykz% zlW;e#=4-kEJI!3m?DKA=r_P*SkKpt&Z*b@!qjMp&Fw-V6aN#3}SMiceYMV9k`;$+i z(miUzEw@^_dK-14@_qo}1wA#frz^YE^7z1w@_;sX*^SQlZa40y;>fxTGjMyGL*K@$ zRne*~?0=7ed`jR(dCPWU)3vxxU>$zgYPsd^jMQKbke%q)>0_eJP2sVN>*}+hIU7eC z-iD*gf!F=LQL6Z`TH>vh=C~Q&%4WajR}+Fs^t9pf7N0BH1)fEi{G6Kx~nq|s*orIaA_oL=1>9SbBC zFJCEL6^vv9IF`O(BhtW(@~dp|mXG%nML`S+?W#rO=LDfif2 zqzWBI?{ZOL%)}_GGS={mfrxlYoQ+vo&ujH|uS!A+*@mNy9>6EI#SrQiwJV(*iO6fMjq6IF~G5U(-R#V5EBdbU*bl# z+rkyk{F1gdT&f&;sh?krdU}shnr!(wBX?p`{Au1B<+RbSx?^m; z%kTqhIHv7$v14ksxjRJBE(lMy7@1yLwkaBKt_mm;4k9U!H*nisq>|6AJ(f%Jk0pDc zEi2vnr`D)i$BTw8^jxycfTRyujZko-&f;g zYPi;wP?AMyG}Ji$GNiyhbRX|pY$jX~nIOim(d6!I;EokMO2Q7gLKOw%MEt@b?_=jl z`~c)m3}Q;&Gn)r7n!@adi$(RVs;juL2N-DAJ%XnOJsHk6CpoR5`ArhUSt#S))TpW? zf%6P1yuSJ`QRbg!Sx2%%p)bx+xhCg#3+6neu<-!KP^9dK?-lQS2F%xzJxs6wXYQuKH$()ajg&-YKE>-TXM^miwUL@DfEn;D5gSa^ zKS=J{Wowl0Ax-~mN{fn7ttMS6rMXWk|Fxm3;-)*Hz==cCb5#MSc9ACg0Pnm{a>xSs z=uI#?kz+u`Wh6^{903lGe|BpJSb%TtCfA z9U>>4CgV@%k;LLtlfV2JSk~zH>ORNa>}pPja3T2F`GrqrA^Twr#h6Ce`$3nbTFQ24 zI^%#p5TEpkj=JD#Gb0l~9kT~%d()ZoP_-j(D{HFM*Clyzemo{Gc?!2O{G{Rnp8k5| z`WkcY4A&ulpF?bCLzqNK0_U}Ws{KWnnx|*Q@T8G zJ$XWR<(fEUXsXK3^|*K;lj1OSTi|h-fI2HnqmM1NvJHtL@EoM@ z-ImaM*G!F+m2~zVQuUFUx)ewh^t0ibuFgRH@G#GE_xB3TaaU`n6+G&VHv_C(E}|z- zjDD!xndkUA%8^(67H*&)2*_W_(ku`$FCxUmROMLSFaD|8wK+-O{hH6%mrK)iB6NG^ z3oqBVc6|if9D(oO4@YjbjJWDK9#T>EN&!ad#~Ef^SmryBT}C}TA;QA%yR^fU^kY1X_^!rd zRn3&v>O-Gb0WKN3@c~y~@*(_oLwVaPk`*bKt~8rIxqf$rEYLVNI29G32C+9vji3Ay zyRp4UI!oFzyiroPE-YX~wNwTW;&x5VtDFGM5DCYv7(QZnnDD57tkUoi+-;2hU^c+YQ#e@3X2 zW#atw8J9tI>153D=@Y#&Z$BMJ{ka~IqaIKr+O|vk3+>p_WOB!C9;2!v92`_27b0~w z1EN${XAJauKqC+f3$QN#_7N2Fpscee)uo@e8PlF(Yq_SJ8J}ZJ6~w*>{*x-wi`>iR zh)jZcF{SPEf_3f=ecL{j@I`R{v`n-+q(g0pbyy>*BxKH%tnY#MgNi;dv^fvg=mm9o z~)${*ues^UA@Fx&sBBsE{dY1 z|2_Lbo`s;X9WCbj25jfhA9(+^AgW$#&~*Lr>426o>9|pGNCZKY??Q^e)zBHC-N5ze9>CTidBN<}Dl|7D@F4@j2<)LXBk>fKbVW*+`G3aA+ z8`je1nFVoyi4GSP{FcA)TeB}|z+m%+fFYy~w7O1EjhDW}<%7EHRabyC;jCi2p?H%0 zWB>q+@7U_|SJb9m`y&7-^~g8vK9dA|cAYZGGJJ@4{GX5iIdIvQAyf#axm*=|G@0SA zp)vMqyvC2!btQ>xGcMNc?me(>wH7~5irDM7E3FTe?o~&aUX#-D#i~lK-+FhLi~tXX z5%ohqm9oxM>N&(Zq_O{|_!X};EG9Y+5C=0!@Fi^Ux*{^zt>ccS&mt%NpJ%_QpAH{> zf-nv`dJ~2JiIHiQ+BdR`cfQ}$<&(Tv1ldlkbs9A39)O~WY;ps&NYVdhi~c$O&Bn@M#6jAO+@}EuX8*^c>4WxJEj&1^j_(PyOPz8O<$63yf z`@?#k(8L*6cL+CWxP#hBTc2eoxu+f^zwfJffrXOqTOXhl*V@f zh&UWfLrA?n+aSg$IkW-}VpQ9+RAKh_<4?FPqRRma3y2NMe&`#rU(o=g=WDY>@S_Fp zKYvlUSYkgB+-Ha1_P087qaGI4ugO?6&)FIXJ%3OEOf)&VJn(guWaLbZCm^kIw)0j|%4Mx9Eb$=aL zcoO>Z82pkQ*FVnzRG7W4V(@E;#Pzr@bHGc4Ze|2vf=%@LZX(8_P-tl6GupE(E=w^sjup1!2{rppU3!dkEL;6Gc_+O^} zB>%)b)OOkqYaC$b7VsRyl)k(gs*!`wGaO(x?t7TF^vANI+glrO6@dde7CRCW1iji( zhoa6v`Q3GH`SIziEkjmLmLugO&>##NRg~uRH z_GF#K>Bza7dqe8g$ot~sxll!lq&Igm$4vW*G5uN^w_K!JXliHhfU~OQJ8L3F`MxS* zxeJ{KUBp6E4$X+n9tL92AOw1qn$eKTHi{9I9qxO642 z1p>>xuc5-f2IErYzK3LQDp*?KX7L~R;lsm`i~4>_CcMx?bNQ_;cR3{+pQQ_1OsW1O z%xl2l{c~v*w)u^A!8F9Bl2B6-{mVPg6VZGhzRiC_4#*S`yc?mWTNgkEjf_|IW?T#a zJ7&h>f58Dpmxt>vcryCUR%ZAfpZ=v~NU^ByoI}y*dlL~IDu@h6m!$8U4L^QMQ12O_JM9E0i)HzBKS8B)rAFN1VV zsLcthy%Gx<%s{B$?JwZZ^kpIq5BF{Da~bbny{aZ4WmQ0du)rb$jQ>|MU$&E)eWG(7 zLV}+5VO?C-;by8ow9q{q2~kihTaVY7rN}}!k9#b z_qB;v(9>t0^+sAr|HIo0;llD;c_aynnHTUur7QbR@q>{k+MnA@lGV!&DPOL}>3Nt! zKbB*Y2~*yb9Ek{)$qK=<&6}!`sx7GTPF`GQuT$%rz5^YlTX(<9y#1{${;}Y)kH0wt zEy5rnMpDd}A@k=1QM23UNq!LdBq#8}Pji5!E`E~n!q@*bVg};w;aFx)$6qNnTovE8 z9gyxf8KFJZ&q``<{^kWB^j=g@mU?v-L3r`#y2_vzNl9We8%(5b7d;UM=|UO@rX`*? z>_fw(8QYXhdZ#O6F0LY-NWNpnsR!=auxTt7VpV&#Seoqb!IM&-iNZ9bU$`Oc@vw@! zufPNzZX+h1o)~Rpb@3^kJ*2$hgH}}`I*HgOaX4*PzTOh&dZLyi@yX39xMzuBSh2hmaC&Prc|4*krOOw6K6Kazf7hPF>S4td^ z)HZm%v^1LJxM^vdl+gqCI3Ei4-8_8|-$0Sj2)k^7V-o=7Kf&XFW zI!2!j|9EYW!p7zJyAT*nfkZ`Dc1rQ_uKvS*t(!R6zvwk%6GTKCnLCD}r@Ws+dM`-3lF$ z>VhYB?NGavl>+wgnL4QC#5e0NnLFMXzN5uimQhrF9}f*j+$8HS4{+2|Bh~e!l95#5 zUBzM`M|PKCUh6gIz=UO*9YTEqxxCfSIM~=v#XM-`e`PryJ=LzxOSg!IC-bM$%0F}Z z_so$R%ELj___!uXR!XmpUtJp6-n2f9e+#7HeW=3E=pwsa;%y-1ZO>AjoL3@2^EwTIY@Z`#-C5DdBBfwQE zw%CradiQIrV{H+3oZb~N5O#~`cEiF^3n?qHxC9+XP*MKaK)rgBK&?p~_{>KlcpYE> zc3MRoyu9h4OPf2n-cAc*fGVI3AFNAwP2i4Ht zGbB*`|3})l$1~mc|JT)3I?|a!Dx^{*mBSjHoDw>#i&0T?MaW@`VVzaZR4O)=q7%w$ z*o;bH(S$NH+mgc^b|{A}hW%b2b=~)M{~q`Ky{`NF{rA4^%j4QU`@G+;*Yl|UrVH^N z{s*QW>SFE;7kzz1HsCXK36%r(PK9RoD2%wCPqprKCz!I|q6sViWzRnZ(xvC{1Ns-z z9*O|WuHs)F@Z_IdGpwWOW}U0?GvH~eEg{4y?%y~Gkbxf`q7WdV167UhqwCc47u^fw zo>=Hb@38sfg0Bqu6g)!c9)i7)eUJ%Yr@)Dl*AD_42>Q_mJIz+pBKQ17(bXOCggSwEq7}k z*}NeiT+n4fhG(Tjl>od1l)64wZPZzJh@}2?wW2*51ZJ(G?fM1Pia@e^Hgkow_A)pK z_Ba+8By}JB7l_~DIbsmlo;x8o)>|%>ENFLP%Cf+0L+&eZ+DK#1k$}Wi|15tKOEz!n zUG(L^)TB;;?EbXqPnJS#Q`NRNjR(v`I$CMgFB`vaScdz<9}pe?{dAJ&20o(jC=Xio zheg13ORk{h}Lw7=EelFx(r{4ehK2(Z>YV!`20uWmumKL7bl+>{pbEG!{3q96#kPS7gKw!KEL z5jl7jiVsK#;9y3S*0+$>jhOPlT-1)R3i(In=SuXE!LX%$s{g-@@L#O}e9<O(&S7 zQ@ZaSeac{Nk56>}zH9(IK)P{q-Qb}wTXD*-ACrpDLMO*{Ce#6Jqu~RFeP#C2QBkiX zAb$Zy0kqZJqNhErqBApyul5fN&oX>&FWYgij(Bh-oL<(;2d?g^^wf!TYB?S)?LsGP zcmly(rX4RjW#|xst~vLzCE@}&x!b)UGqJ}WNoSI8!xElwQDE4o#4vE@AB_}G#U3dPFR(v7qZ#T61m zdZD@;dfgg|P8HhFG!4U8(LDCRZH%s30IfIn7H^lTK?I zbSrE%>Sfymn6~Qe4{NAZ+l~pJ>{WY7=T}rdd?zf~n8=~HxNxT(m|F1}=_2^dU3peu ztCF=nw#)DFSe1_+L{KoxW-i2AgRgr*SG-L=U5{(=ngJy@ll15xp<1A6v#R`GVSv)N z-<__$`y4i){M zcMXEEG%wM0X`Pw@S?`vqoyjA0kO6puxBXMLzy2wAi$GO*2`NW3s7rmS*eZeutHWlw z%H^o+K1y3_*zRS~0~}JuAy-`FRUV^-_)MLqyc#Mmj)_?1|2D`^=Z26Ez)m~Mzn8r& z!!$~GS;E((O9Izi%(lzj8pIkt4ctL|Gmm`q&zymf83f(|`jO{mMg9IbhT+JW2j7-x zTigtU8RFivNE_&(0I7V8?RQubG?T=6F;nn+f<{zLRuLhiu#(TS5!u`?FanpVg z-EeE_)7^qniE~)sd@rxGZX)sDzy@j21C}si_kB@af`nZA2SA;-;9MxO9;`s))(i%I z*|Us)YU_?4c#~H$;MSm=K?q?BiT4$dwt$u%2AsjgYI?!hjP1&O4?$7%Lt(Mia}J4k zkuHDx))VXJbDDf0uV`bDzc5hR@C5zO7It8Ic#buaC#Be)i9zj%jlzo=id(@*i-Ry>uJvB7b7-( z(=Vzras)B7w#AGNIH!AM(rnB0i<-oQ6Fnmn8aRDq9>4!BPsh8I`xPttHbaL`%BCxY z{an*?q*nWkMV~mPt|y`gO0^t;q3MZNMdsc^-3vkG?7D zE~2|Fpk+ktJaK>C!IdL@q!dvoezAAU!|bF|)uCIpZdi*5>y4+My>ePKQ~Vv4u?;vl zoSCZ*?!U3Hs;nud1G3fS%}B{ubn>@71#=%d;M5mtm=D4{B4`sjw9!DY2ds0c_zN%) ze0y*Dq!#{i7H$>?8l_wUUjU6Yqs2p;zBTus6ADr>rujdJ57a~(%+y4)k7#ds>V<*3 za5=_o?DXlUl`-w+W+a1IXKnr*{dzc=gUzhpz_{yR^@Lit{X|s8zDd$hDM)nW7<@lp z!StLE=@i1h=`T=YS8vuT3k%{UxCd>m;zhlFyN?EQE~WEdgoBVphX@B%+!rtd2O{qo-IFw!ZbTB`fSV^ql@)Er{I3l>1K&QXPX20_cp{Nrj*R}S=fRpsVKV%mFp z)MOUPm0MranwN{;B%Ygeep2ElmBdY#^e!(>wqGh-aO0`LI6}&-9jd4t z$)}Tfk_x(fhf7|RVn&T-LpcA_NYr;WMcKD~c3P>!$TuGgE+^OGikXvTz;tYQi`NR}w`VVl<# zmlc?k6Qkk5R>hvCknCs$*hRN>4sP9I$&m@hZ%Ye;ui)O^Y1Yg4C3mkjq>NaZQ~i8M zV&1UGY!)JBsUog_yg66V=4a4tZ$N*P?QoJOIq!}~WQs^t(jFe4nd_LV3*{9a&?KJ? z=0~$>LrYPvbVEeH5D&U^ElHR;_vm^0YNmgLc6_TYf?wEwuz*Tc^*BK?Y8}*x%|rMK zM;i7K{&0AU|3UBu-4NL55f&A!Vd1Fs;(420n+FUK9Q%Hd7++kHOp>;8(&8a=YgbfoPt8WV(VIfwyYqy<6h|DO3RDV8MJlxtP`hSv zOG8$|BfUv9KWZ%+@|~b+!QJOgw{w81&MTe*d}@!oL&0pwot7?+&Og%{2p|R~p?%_&OYV59UbN_$>%m}aBfaNM>jK=XhY5K^y)#bBu8F zGP(v>+6S?8TQH#qYe_boSIo5F##PE@9M5NQTVG3;)4iuFD*G60s0@s=C)j(KmTBv^eBYw!UzWbae+q|5R#{2tv13 zT}Cv;OS$_<)`&1c-GcK?I>f@Is>-+iwjc`?Of{93iTtp3avKkGuG*L$VdHDk2TsW* zYQUzMl15}uP+$Gf8mTK)ur%MMUD=f$DTF~mz7*gn!AKKSXyEvh`8#93ydDdStc9@1 z`qTwuVUZFV);aev{~0>c>s4M1f1-AeAA1S!;MmuK6YuR%P6|Pdyc8dPmrCAdmHYjA z=WyTnyURTxni>L{-jNv;M(QZPDRl1O_l0Y>4<_7ZD34#rL~q3^Uhz*!Y$``vp_b+A)lk5b5goy zOP1~?G2m91UNQLD&yH{3{LG6HR9z9@QamfYOBZjE$q06u5%5Ra!MZv}TY^}#kABI! zrgeTfhuofXgSRj{VDcjThB#D$fzE-59V1Kw6$iv9N7yH|blsNznBRw|1_$&%QqlFR zw1*dd3t_0X*#Re`mNrhIU`aNk3xvM6)K*uG5(Lo&bCSgz3oiX8k9WGvIa{ZAMPE)| z_H7GO74d_NF@quhN2I|s?+EEK{q;=pg-MfKN@DmNLn1U80rI|}g`7%>Y^=n^dK|0$ z3hSCT{UHVO<#>f9S20;W}%Webb9B2eU^YWAW5$4c^B4Uc~BH63cPLq@g% z@6$Ak{L?fzC;VeYJ1&0Wu&PuZBl5$#sBeM2XWmw=@>CV03Hf)Lr%55>?|sf@Upc$0 zqA{_BB_qDLy=Hf^7%a!D;QBZ2HaL?P^itxF_$T{z@e%_)tGc$f z`3ce|aL6~yBImQgFdzZLK=e1;@BEKl4}@Ewf*)wMcOz^$D}u=oB-^T_bRw! zAknC5!9ai9$;i_{Dclf%xPVJufP}~9c`3t4ZYS$)K=L6N+z8vJ*B8T5JFDm4Z@fEE zusM*53Zce?ccJY|zH1Kc+Td+Y>9ZbpwE&W~Q3c<=7`A2jmMpU*PJH>;6CNV}d+2Dg zXg*8kzn$<4ucY@PXZ+v2eSzg!riur{PKT-{ND8O{M~0Tp#uD%d=#bYMl7M(?G3zdJ zRhy@)1e_dCxNqX0Xgja=vk%j0lscqV(XF+BJWuH&I809yt18;(q&@uPY zUi_Gp5QFogz);9uB7lUV9Hx9~X$3*3yr_Uj%Pm+Z9ho%P_{F!QygYvi#}0PRZt+8U zS2QQ_j-#)%Zm?$LMl*+BB-SRJ+isiOW^5SrJ<3cuLOiZ=*4>y)VWe@D=1n0A*ZI%x)Xwl44REf!=c13)P`D>SHr?BY9WJ7U>l9T zl=Bco5$~&)br`M81%A+5-I9B>l?In_SD-LakU4)=ktCuGZxN;Dw$00m3+O;Cf)1zy zI^Z3%#My^N4prkx9O(38IuXh048or)wm4bqditLI(<%cIuvcMn_cYCV)^sgN! zIm8S?-{jL>=<6(;Wsr6Xt8oYV)Siy>eOb4yFx$p<|BvG21I_2z2lLZs{16EkG14%~ zZgVcDX9kCL`5Fb2i3KUVUNgwi{I^j9#;wkeG{r{fIL?w#|F1W3bGq1%JyH=07M{Fk zjJxb?zP?UD>EhhAIXt@wS7l!+ zzG?Xfi!FO=j01wp7kmgGG#HG?AShie=7?4mNnW%Y@?Qhl`gJUEQgtTiX7&$Xf5#upJp}NVgXR^lhpxdT>!1@V2aIPt|vg_q1`JKEyoS-3uIT2ON=lz#!nW2nJ;h5>?ClVyep`lHNmj(CYvX(q zs)Pz|bb-*GDir!jkDc-Nw4{X)gev#_mFq^%?dBy4Z98J|MR zkX7p@`YGIocA32?8?N}k$1m9A-j&?|u0)C+ilAoMY*^5|U3s(Jmu02dAPG68f+C%y(J9t-~<$V z!(R0`iV-|EgU_Sz@j_)}X{Z)5eLgaaNQsL5W?nle+)5CPe)hw+_+bN9b>3f{C>pj# zYn<9z%#2q~Jk)VwM91e=eUA0WszL0vnwy07Gs7i$ks$@vdUOyNo4sHzix5Alz0Xw} zzPp+%U#L| zr5grevWZV`!7srir&MbS#c_U$+FC0E4@P+44mB3e4s&(wbGheurn+*Obga@N)?z7|@N1;zOvuAy5KY(L#=)km})Av)q9G z`JL@|8-J*3-iCUO_#o9^ajeRhG`}E;MWN>L34l5gbTy|F7HlN9XcDLU`-cCanOr6jAkd*Nxk zYrA|zM2YUz=LQE+@ecBiexG`=I?o(sPbIW@*OYOb5!v5)Zo4Z)0Woqbaf7R&R)7IR z?b15lJf<_ye!m~vyN!M$P|gBBWBxRfIR7MC7fT3_kOmhf?A+Ey>q`=}e@FYxiW|Ii z(%PIGZ2xbs?%E}63DwenZoXiM^{jJ~?NN@66U9jV3%%^L9Vyb~f4=xxHCX45Jq&E0!hi?tW80iBWC05=0f58sy&eV!SkTz2JPMY9Xh5kB#)UK@j2wRL0z zOX)@*DJNwi-4Jw$tv;>{o$mFA16({*m{jORo2$w^;$yvV@o(8(J_bt#2D-~JIEz7S za?S50qf=itwe~5js3R|8f3DT)iK1fu9c}^&dj-jppHuUeZ_bHJ7pLO^Q-r{~SMfuQw;a3#8l8-fKyE%S5Ab$BVch2#(2cEybYss#y0If+{zjsTa|s=7v~F!~ zz1jR>S|{cM+^H08MMAJ`iEDlrB_mmlTXIY?nwO-u&c=QaYdwu6+mS9_cv-&1S74DC z@hu}c;ms1&{5~aF=@;dc;B62>E!#1@-8WZXxvJL!oT0c;X=+W4l+c(Je6fMUf8Sd3 z21!n3jc{VK|IY60h3wABs3s?pm|8Q}2I55^sq{5spgdoYPfgg=8Gk zmcR@TioO;?bZ8R=`}13|Wt^O!7Kiw>`fK>lP_e-b^tmS2>0 z(ahh?BLFTo!-ZY?Amxi2#B9qKo@9hlDe5M#H3e5VZ941p z-fMCHn)>)+BECdWDkG*Z;W)#E9>u$H{I%Kjge*EEGnq3GRyHNf16U&{m2@nZ`|k!_ z|3RNaU)$)NBt|cOL6JuYmOd@|$88>KR2#3?yaMta^LelqoqQo|_mk>2)6Xdq4a~Hi z)}4w*_`9(th15iJj7f1P^H8;p#sDUkf6L4aF8ZHYrAv|${6=nrQi_HT$-eWVl(Y1}LMZA2_R+u~H<+I2nmzd{UJ7XZE2fceq)r12m&UiwfuSTnAtBuyZHvc6*64(WYej%f&0 zr&8;xY{Tcy`%VoQmsm9Iv)&ncl_`UJSL-$Jsvqb-@>=_s1X0zrTgVHQ za8CHKwce&JBbi+^WqdW!kkdUg?S_+!y=((pzMtSQrs1BjHTqPHOpj~gne&pmbLnPq z5?1;9HNY(i>x=NHZ7wV+IsHS~___oxdD%`$_)YGRb0Af*g@&(?pPJf~VzvoR{r*Ef zi@y0O*&q1IJ*RuEqT^-hByk^Ov@wHe?Hl0|F%mb<&6p`CG*rl^*vr14xb&jd(b{`l zHP3t<+~^AlG(G+06%MBypxBVs8v=*>JEl=#{wy*SGHh24{pwgajfn%6A0|DE=IB?P zs80W1Bcti(PDXgco2)s-QV1PPcfYv>!SA2VxI0Vm`G|vj$AHlee9FwS7qj=y{aexOCW1Vy4QNC361J1QJR~D>4jg5_YQLB= zxEOu!ck$@T=h@N;%WJv^p)!uDmMHxNOZZUvIp2GVUVw7q=l8n3@Ht2HSsET%aJ_r- z=RrsB+=Jix7C_nv7kl9EX@~5(pMZZ?T>dFb#ZS+vWNz%8U*kp zxta8=r@B_tnDZ=}QISIvkjMPS)i_fpXzJBo7uWYni}j{3C|^hZrD)re-eyaidxjTD zQ4i7v3)&_Othx81r>ajG#-F~k>3wV)93dfXgaH=4(%SV(;*gixgyPUGC4$Tiq?GZm zSjj!AS`zzY23vSrTl;&sfNB}hwQlGeN(%G4!wvqmx|cKm#-%U693hPBi~JQ}wv5Rv zoU1pgHPE#!F%u3v7KCCqa`+4{8~x@zUZo(+u5iGS7BQygFsc><+m)=wzQClGUT7c_&&xhyju_LY zB?D6C@o01Vb#A4#%az3M>ZR#QMdQ)IC}Mb@{b{E0*Z}Z|dkiVUd*bFf03ggC?Mmj^ zgx6hD@*$4rfF1o2i2Rbiliul6(l#xT-!=+}SQ9HX6 zExB}gjLY$_^6U=@f-oVC>$txy49F$O=~=ZvKzDF(%E#V0^D0Gp7cYA!INCP!6vaJQ zhw1RqnV+wnnR-&}ht0cKhUiyxxiBitb|sJj-l?^!R+axZTm9Xwx%3j&WL*8;L|(`K zAw`xxgyZM^ZjJx7+Q@CYm1yqj`&Gv5U>d|2bNqwRNM;dUj8Yb@QOtfW!;FJfmIQ+R z%6Q_m97gt{+l`JHoIN7I|F6SGPxZ^Vyrg7wQg2PdmV13=cPkcEDiw7XQ`ARwCLh5n z0^5c&Y7&tTpJq)y`!34!FP8ml6m)(tl_KRssZY=h*;*GpzJf?_bC@JjQFNjTb9GbpSt!DE44~tMm9hG|^hv5>W0e-1AJ5 zcs)Z>$H^64aT_&+9rsKFIbd}nzs;+#$4`N>$Bhs_G!^{PRIfJfD(=3mbfGC^W1y4O zxg0*;TvlmG7L;WQNviLa64VR7A7((i zWC?IH(C8T9GF@@zM=AgyX?{8(uoFAwD?~mOqnq|6l_Bg4kgt|!0HEwkEbD}*wiSoAr+Q2k^9b+( z)c_Ri^Iz3Hz-QlAyMvB2hPPxAlSQ<%zTq3!qx>Zqql7SBIpq#|0Ck%4KBSFi$C9;` zxhxrCUTDiuw{aM$A^vizM{|&99Ii|qu}obOOvTsT@P9o;=mgalVZs8ntLT$ZsB|v{ z^Qj&Z{P0_HQAjcX)sZBA=r8q#R)!=NE{=SkGP21H`R%jjDVX7$qj-Q(M1RCiWamlBPqUbWC{w6M!*{{EBVFxfp$(=_mRcMqt6JPNRTo z>C$9$LQf6_Js%?WUc1-k=>}Yn$E_MPqNPY{)wqkY2P@b1CS^ZZfr&7Aj+ZRlg+OzqjVn()&SGIpcbWSC#TR1RJW@i4t&dU+QEL66~ zh8e-83)?JOu0i`j-B{D~zYH4ChP&TXH@NT*3SdVAOD56Qte7c*19w6)rqeGquE)ZX zYm$q*?x&+^IJt#&`OkE`j)??#Y1JQV1?6W}kW(zEbUNfg3z`Bx-g!ZrkrOlSH+Hpv zFx#ipN@*6b>v&r^2r<6Itng$cM~GG&zuU(;*G9r?TXHe{ zTek^|fPH$?o+OFH1Uc&bQeC1d?y_F};P)nl(YXe)exF6u=JsUKck7P6fW@5Aydk@x z6Urbf<-l;BvS)%6HEL#$8zuONhgE#UR{o0BiWx=@d!7inB9mEU=)C&Kbyq5pL~uNF2aeB4yqS86d-8V%p+< zVi=1cIs)(a#B6uWI-}q8P-jDQ!h6yG&5%Q45WIXa#6TZmd(dfFYafxa-f)P0c?Pl@ z&$DqIZawaocOx_vfDUPMugB>ZP(4YFbn30fGgUIS2xCoee@n&20Bh$E`n-&h#f}W3 z3M0MjNRE%_lCGrULYAz-AY*G+vSX+9oT*nki|2jdf1h?sYVGD~xwP?M5bsPG=A5^6 zqJ@v$4(sm&`lUCZzo(DoRkPPVU1ZC`v7pWi4~(os2p$oB<#rDvsYUckW;_w}a*Ayw zUO+s(29)M~C62FQUEXgq@)O_CIgC}jZnWw!fz3t%7{>pVoUp#}V0uo5W4SCOs$tUi zr%lQlU>lzS&Q-7sWL87_o8{t!v3owe=O~;!wR?)h8&2i#lRh?#2!+-w2A%Pkef1V8Jmo(1Ew z)-J5gVTN+Y2AxDqV%JI9$vfkIZ&vTzseYMdq0+G-U_2oiBX3CLQ4n+_55yJ0bB)9E zVaU)!1*gcZ+`qTH{a7lDxzQw*jyuq|@0Qfe&A216r!3XlYX35L33gQMQ8HCR;rH@C zvKBDN1OYTrVlZg&$0P$vI*K0sGsBeTJ5vHfZQ8SKkl6t3i9*ZfeO-UaTl`O4MX~1F z543lIfT-Wv@G^e;aV_a+j~89Ee;ulCY)1+w$3wU6NUIw&8WR0WM8EVd@j0-Y*l+T+ zoD+|GZU`+W_$^c~Iu__HP!%aqn2X&E;$kJ*XKSu)Q`p|T%*RcJXum&y%Cj5%j!2WL#k0+nF#%>?PqRx^% zYocQ82bw{Fw-SUHIo=;{?iKF2Iq8608+j%4T*&rTlV$^0W|F7~^dZM8Zry!qJQ zfxrc{Zku)&h&|S=$mNm}d*W&F@CSBd36H?o0CU_uV5x<;QZ^}J*r-B!IL4>iE>;06 z|JJpDXW5Rd`k7WV_MTs3p!WxxQSp704KJ{Ey+_WEaM!}Bg5TbM{@?cjDkNZS9 zTf+&|3cGO*tNdU0tUAalPu_v= z2*Iy;SO0S$SbrT@$n}I{NR0!J05F(*lM39iRlp?0>jPmYLz~m=xZ@k5NC>JOCy305 zTDcMJc>ya%(udlCNirY zPcF^YQhln_opzSNOhnL+g?frJ)tgaA!UfinmkKBRwMzJMdga-o=oy;6=e+4BQvV(T z0<<2eaaTsuYrF|b>Eh$BF%F<)Bm}tYOwi{z+ZNg}5N_lDIv1$-bJjjLVjhAcF{@!% zFn#T>7B|Zn$w2aMw{Fv7XFs1israzsV^z&jHi)WtsAz^sJk z_E;Hf{rciRx~6OGjTb;5F|xrhz&rNwM8YSECYL^lS!;gX4N}O}9dkkI20s|`A}*)o z_Z0{#lpGBu%5!G~-<@Z8d$8M=aWWk`0(ztq)J@L%riky#&th_(@%yjXp6uWOr_OkU zFDMu+|84S+2L2{tbXk*BKkfR#M6pdERYxNwg|lq<^W7CtP?zWa?Qtb}#}6+-Me;XB z+SQNHu)R=YE#jPU8Uzm2V+}oT*kOg>5=}1;-aJ;>g6O}M|ow`VzG*89dpg^ z)}Q7kbT%NIC#V|?D{~isG^waw`UCbkv9rpX#MACx{)ZNz_tCz@h<=kJdU;FeScES1 z1nGxxIfxaz{9Ka6%r|yBOFDk*6(p2h?eO%!KeDKK@>QIy@lg zQlTPpPt!*5Z_I~!crgU@9Mx!&v-NplQtNe>*Q45@kfr!vObU!j4hxsTlr2R>PWUB= z%E7LYW3{2Y$ZD1(=`?t}!3tS_udh5XOWkTxD@dFAFL@^8t0x<2m9D1aU&RkB1S#85 z+Y_xuMN4<{Lgg2|T|+r>@55JrD%ckcFUA>{$BZQRZB&#l&+zA{@Bq}0b&;crdYZH@ zVGcPfiaVu$Lfs`jOS!wxM)}5MZ+UD8hz4kw?T;u7fA$NQQY8mtVb(AMh8!&XHrzX#j+PR`#97@QA*(z ztC=@12to(^!JAkGU=JFqIqXXcpCyZLGuC#^kZ$teJs>HaEf{x_owSNx4_U#$h zxThBXo99KyWtN{~ref4*VpDU_aWilQJSxzB2lcL>v9PdQMm*e0P`Fp5^EpFKhjo;+@ zgK82|bK@_Uc4vl59!{oJ0ZCL<32pYMXICN`W$T00v>mON#T|O*ikT7I(@=K$%UdC= z2~<~yeBqk2YHn+Ts5K|T)V_G~w~Z2xADBZ5R@KwYm~z3bqGJ3G>FSL|@ys@v zrB-N%-r!8KorLgQbotL?!}JwaGiB&JBm;J_-m=Ljd;is#)g|lx3Fjg=7RI4h#<$;IdG}_PQpy5RBL6!E5 z+@(tNy6Vd;rO9)u)r7AdyWR*4R3|htYEK^uSldRM5KW)Nj9QE~P~73m6M7hUMX#^z zR{h}i)s!NOzm`V;Qv!1WtO}5I1N1CRiCr+KNOkI0SIP#Tn=WbA{fzjgSGCqmmuMgTvGib;gF3+yomAQF3o9Cn0}+q z^;Df=iV3eVYK^!eZ6q^%bqC(-EMw{SP#(GDTCC+9xQ=2Y1mEV4u_r`}9e64Qgp*4eZjLAgjdOTC=3RE;li4YDzz>~dP=mZ$YKrEdQuxQ zCzPnzz5-dZi%=JoX4C7f0`CRm6tGOXsKyFpe|7MJsw#mxS&jb=JB_*5o$nU zN=saIb(+;}x`h3?vQ=8hPsFe?zR-#Q(&BqYI_)TYTq!#f zqw(qmR0%l_gIT-wVfI?cUl6 z$dP=RXtY?>Zq*%~G78JACgZFRzCQi0W(D9%-yo&~-rhN_nQ(d$&e0S7%tEP-?&2_5 zE4LwaE_!K`{5PCO85DK-+ur~Z0kVBKqgB>VN16*B+NWh=K{r#nvsN5VwTdarIj zb>7XIjo(W<2)A6-&edJfNm6rKqB5I=U-WTN#N;L}e#nj{JPAfDG8po`pp;zNIAOp} zIsN`MLnhHWb~k|Klf-zUixPb&rJ!`;8nlgbhVYtc-mPWuxt%MVO2zdw0F+$Y=$P3m zuG?>MOT18oiP9}W+VDr|#8iDAf&GrN$O5*1!9fE$u%acfSN`k7kPEzk&hQHx@Rq!{ zNEA=RQ43CJOSa;5BLcen_kyy=9mKw~GEcQI@uEu!8iO`S_7R|$^s(%t_So>De;AN9 zz}JNj&J;6%0}(ZSe+$xEj_~1=Sbew<~o(QYK3x0%9=q6q04T%OUlNm zb=5`(cUYNUxR>t@!jgOG+%-xzUHdrv5_w4?kmQ}h8h(iAJ8>ys`0eWqLK|^3;ee%e z{T;@DS({+m{QM4|(+r(L15O`wlhZ0W{H_Em^zh0t=b2yA-eBR6UZdoY8Wy;kb6W{V z8r6RE8VOtdu!`I8eH>5bVG%_=$&3$YM(AWYu*e2nu%BH*f&ast{hCwq!OTLhS$8}$ z_kXF13(} z4~|ASg|uAQN&MpABjshNF(vmY3{4KQQ8e%<8Ws@W8ANrtc6+d4(gS{&`Zgiiaa1_? z01*!Q1eB162`}%6PI>92i%E#XGJ18E&KnA=-uTV05R(`m0?hd>h)Hy=47Ect6mSnI z=uhzfgdk~PscOLogsn$q68J3K)f7zNQQeK#C_EN|FkY#}0IleN4}aavu39ii^7Y-; zTF|CCqbQeP1K~(-lO;F1F*iI4-GKNQlRsNM0kJ97NPfs08;q^f%sxR9A8c+0STkob z?JX%HI;#4s`Tc1`dn>C8m3xZX_xt1?oVI395E$D0F(0PkcKxVKxgM_W8$>D+i|Kd1 ziTY*=0(A#7s+MHeDCJ*c21`9luMbm{JFRHGlS$$u(Tcjq(VqIj?5#&<|67+sKp+(> z^aC~{41!Q^-Mou}M@^rGrTe*qWim^3nO%Jw zgN5gg_Cf+%a|E6_;m;n2%+Z1~Po-g@NDD$2Pc#Ite(u65z;gE^53M!XPtND$(zKGb z+x_gkXEh;q2mBOSEkvhi!vOkU+6-}QdD+Urr$*X5!K1AS?$XhOiPfDX{VsCam@tFJ z%8|+A4C)g!$ys4iHZ%Ic%=hV`4X;lXtSNzob{f({A)6IUEwJLM#tA(UX62Qrx4oYj zb#eN=zH>>3t0uN($fNUH_MU$5Wb;!qaMO&j3eiRn7nzXsIS0X%C(m&^-sW|xp-9Hw zW#o+0#iE4Zbf+UgDGdbyWbo#X+Dl3)m^SZ<(jF8ya;X4JwFlv;pNH#>ZopmeI`UVN zIMNI8q)VxBQ{K?x-_dw`!K?6? z-01EzJ~i9e^f(u%4Vys?Bp)-p=&^fU8Pnh;B1^=fp}o5>w_?U0DsHeYbSr9nrYzjP zG8dHsLalvqa;AJ7-#k64?d!T%LXXesksJ0B3Bt3uEC%t>OBNspprDS1Jt0vfCJ}BA zzVn@?WZ0<>pC7GxHS_m{HRvf%TkP60`l9n?r%vBQkI+(=0II&0LLV@`_31FNOEQ=Y!B9lf-Qw``!Yn^52i1En^U` z+9gSnmsdoHG+3IiZdwJUnl_=>AHV)lgJ7e}@P5uN0l!m4&lzM{s9D!(7rM_#<#f%X zH49m?sbI`~RH*VI);y26V5KWDHR8t9XVuC2J4d@#J{ajbY)>tow)4u(XT_>@vq-lN zfW3~S{c55fB-b&NRJrr!;P>2}458I>Owg2(4D6D^RhX&40UIZLZJ5%Z@r_pu4iWxI z=)?u7%=Hjysc^*aV#LgvwT4kvUd~xR$`8Gm-}z44k0+z2&6rM(0E2+*D71rv;nEEe z)58AX|LF1x$a^4|#ls2>jPT{hXczcLK2XS<_G_14!Lnuxrjy;A8GLYeo%qpusPA2K zWV&(q7z7!q4)KWZ|A5#dDk*AX%Ttm-T8(~I7cJ9(UXraIN4OQXi9DGp2~_xiLtgX z0ek9&uV5%6<8;x0<{d_`t5QRP>H>RR4D`NO)4!HEX%fR0Ju0PZzGIL2ow<}X8m#x` zm6S3q>X#fRwIMm9BNN3-9%Cnf;dU923v$X*o$u?srMy!!x^>Y9UlvCh>rt|=L&NC; zo&xFR!`5rYdX&fsAbL0ld&6S~T!uCzZQ=N*GOocvScpJWoRVE11}4i7!;BqwGS?8$ zO78&8Isa?;L0u13KLgYp0VBmu*7thauFv08t=q52dFx@HJa6>I+t1{XVfntGKq@{HJhn2eJ&(5Z#E{k$3~Kun z_pki8C|qM@X^A#Mb0D?^B_rB9rS53zRzkf~TSn`Iuz-D~lB1VMVv+~H{xoqT{z}B$ znw7xn&D|mPYZLutp20#i5lh%W68b@%A~3!`3>l|ZV(D>ZkzS9Cr?O;zpxO$*>6E4q z$h#-2QtIxeyRcLr;q`ci3%|`Ux*k%qSNgjDH7_3&17qh5Xh`*WZmFl%-0kV$dnc|k zegY4ngbt=kQju47z1reM*fHh0>yqbPg`W)zM#5jI2u=;|yTR>MeO@5Fw}cCLNJJ2W z5wP&LjNy458~kr7YlQ0`Sj(^vMkPjVeS>8-TJN{dM;v4$~1!GeP(fn2GOv@yGW{aEI+5KzZuyC=D z(Wd#@LO(1My5$gfA~*ZwPlx5dlW}UQ0|Rr!0j~$qjC)K*PWj)E=>~u1zt43naVrO> z3Ag^{VB1Tzgv>=-HafQ!RHUdKSQ3>L^6f1$LhY3nsdu|r%>d?lbMI*MhoK`X(cU$O zf5l&89`p$iOw38J2EoNipOV4(A2Y({AD3GfZpyB(_GEmm;Gb;Wqr}hr;=0mIuudt@ zgdQMA%4BwGC(DQy0LNe_c$ml`iGBW;DPeQViCauW73r79&Sb- z1x5Gc@*oVBzRv~DK^D$A;GVW*@(%(e$R2le#;i zp@&EqX?*5Z_isWGrv7McFe&x24_yUgyD5$;A25E@R#x<>b2MVka~MM{nn_6_BM0#4 z<#s<*ye;eZx+Hwa>v!s1VtDWLLF)9o(~RA3x1p?`zZl}8?#Mo5+#daC`XOQ<^al6& zybfv!Dnni^&04*t;P9Mk24fLy^cOocedmw9&@^WJ5~uEQwwzJ}XLjkPk;~chJNue+ z6SfSLSZ@NNWJ$@O>&_C1a3`(z(I7FyaEYZ*Ye-qWWolZtcEK-Cl#2$11DhI%I){!~ zC;t-=AF*`Ir@%x#GJ^Nr+H*qLo$v6y$L>Wn>2K*Odd!b^Ot^QqDMZ zG>9qIcJDx#@_Uxoz1dxE#2waGPLaFg4u_~snKGs2zN~^f4v44W;PA!12@`HKzls&U z_mH2qFVN?3tmuSO46&Ut>AZ{810ggu{Wow2Ij&y2)z5kjHG4AtSH!ITQzN>(yno8) z2sO+IDUU&$$+-6O=aVPGH#DMjDM0P;KW z8tfSka-felz;y`$CY;scufeOnt@_kcYGdVh;r#jYr&8`a-Wlva-dl6bzae7YA?X`P z0Xdi)`ITW>XHR@YI?w`-ImO|LrrL1p~~Dle~NjO*3(CfaN8wr<(7#W}ijc;1Kb!(eP$YaLxf zba8WWz9V#^2@s8$M$J;YRUEZe>27dzLp76wmivm|{T15zn8`43 z72eZ87L+=C15@&W<8g%cIg5Dccnfe>|Clajaw>}!o~MuJAQXQ~aG@O%pwRV92ZhVF z{7XZ}FF#t^s-*}tf%sASWic~`o;B|?8h;wUI}_#jLw}BlK;G7xdqp3Ds54V6{N9) zbRiUMI&q={kfIPG1#SX-_R$f-*w0QWEX}f;9^W-$6}-G!-6#jXiEd%wFjd5#h-&bS z9h?B!Cvo()EB2vmo+hNsVG>0IOdAd*f+LY9m@#=MiEYL;1_7^}LWhWk&Jp*@n#Ywh> z-?ym7;-Xt1@cb*EM*lEL%n53`y(cre%FkU zKgSaZKKoS&is8O6Z$3xSwkgC<3jTvfsEPHfu;6}^$ew!~qmU`QqB7q9WTtcnZxMWq z)s>-f+!Eqs6}fZnucu3w+Tz)u4Fw((pyCkam(4>h_ZI)&3|`@x^JmYVoqYIi@b$9h zR)Z8Ge|ujoscmjJ`5uTlL)d}gT!FjW5~yVThs+S&P1KyMAiKK8%9f?V7(fJZ;iG5n zY>xk@J$m$95RaG??1Z}4_C(QgEd3}nU0e@IohkYKESw~O4?pCtd{XvbUaV8#0P5t^ zjPK}FP~N$4$Dtmd%I8@OdYFhHQwDJVj+~$&lzN@o@`(<8a?favehky@Sz==1O!f-T zlG#nh$dSMQmONm~Y?0GNBxneFdha-9+3mnGLmO(1P7z1jrw*=>Sdw%SX(zqb2OH1< zO6xPyra49qjUZ;`tW|J?Ky zi<$BG|3})l$FT= z2eayX6ao@WPWEbt8SnkT`Ww;+Byf*avuSinIR9hbht>R3wzQ9JOgEM|%7TegvlYuR zm?dx~eT@H@=oj-XJF(r@Cx0QO#{88m;*X=q%297~5iOX24_?!xkn$bv_YE`z?YF%s zT(!62#>}j-j=hUg1Am&ZlfBEwZ=QgvXIry;b7~2G;r62QYuML7&|{CQ6|V-DFtu2f zd;}@9*<}A zHEFiFa_4HmVzPPx(5)64mPQ2VN*?aJ`yw4RbC>c|JaN-}xGxRtdM{9vrzkyMKF zpq_T)VmK&b{NXw}9*%3m@eM$Pb7ao9MS!nxkV0yp3ooC{#p<-H|?zzF@__WIO)S#*(}$_H@L zfe_*V(Dcmy9$4_*U5Fn8^Q*xN#L9%%baIYdtKq!fe<1a5Ndu34?elXcZw2;L+|=ys zEWaDpYu{0R*v`)Gvg6luy~E>En$iUaPxP;q%etdVf|V@oF6hiJa5Z9`WfZq~T9y6! z>|+78e{*~m&I<*8AWV9mGdyeRgho z)Ur1|oi)T?F4t*#{SJj*FP-2nnb^+XoQ*a|NfVW0;9va_I$zBLHpEP$Wz7NT9#q?) zH{YfR!Hmdg=tG4YQh0P)(V8fl-o#&+2!W1qbsq2{42ojuJPV^utCGfq>~VY^2lmfkVol@Cn|z&h?lz&-dlRASQAha^c>U~5 z8{E@o4gMm*Xovdf8^6spY|0iOT^@JH7kzMj7JBkkLmFVee{$~jO4-}Lh)Rn8;r}ZE zp`mk3CybmqX>enu@=|<(yW9@U{9r)2-m`pFApP@#Y$CV;phA<0qDYU$*KbpABka%4 zt{@J4+1LxaWs5$z<6pq)=(Ls$^$Pyyu`>8J=kP#^#6pg9-CVK}Wsd^p$(8J{Ip>MD zFLqu?>uLz5ey|gXoa>eJXYcN3WWX4>Z20^}ZTMj-+MPt``E9tyI*2Qs{cl6yX4w#! zONqrX#Ia8O*s41F;RNVsi~U#Jsb?X7bUChE!Ai4hv29@SuluC;jKwTn{f6#`71gr1 zMh_tIU5PXRW|MI~-SPZnD@D<#ht;OdAsJ`)8(gIbnuk=u?9BB?eFQjBL7*dOpxs>x z9GuCnRg%FysA9iI^004P+dv5@%m5~#bMyNtOx2g;lQSNiJ5`3Abwhu8#>5vW8Jml* zIHxY)DJ$tp&3=#Lm91J$Uz|}Wcx}wa;Eh^;AIYw?4R9`+>SA3qFmnIXbGJQ(KQCLi z5&{4{z6Su>e#P?-(jEM2p67P@=rh!KFJ$NvU&s`itX#u(kfg@^U*!>ElV^Xcj({Ar zY$WaF6o4t)L2ab!U)lbE&t~`8e|QDt@GA~Z)+U>BYB?sLj?1a!kH4=BPF3Z}ofRW` zqmwQ?5Pt9@#rZ-jpmpm+wq<*6d!>c+#qbav5T$R0@w`iNip%)D`=7Lma-NiGZPu;- zPriDuS#CZUyvyi>eV2@fM=q9zFPvjf-|sC>(Ul&z38tkPpCMup;5&|I~g)nvpV~N%dKUe;o(>BQ z7*W6rOcz-94IEMsi!HJdn4i-6#vsY33kt`j^)Hj1W}Uq_J+cSsZpIeRc(`_KrP~eY zN>asQ+Yj)euZ8t~k_^7dS)P@_q5tT}2(;&7rKk`i4OYmvrSrQsQ0Ji?WrLz2h8FQR zis4dF<{i2ljNb{VJhz1X3qRta6dnX?gY|WsKBjbnHnCwc;X&(dxMeRhO)iFILQ}U6 z2hN}~pJvBtN_W@S9Ft?at=7cQ-nW^5aSwgE)BFal^4K*|dGXlR|8=q4o>!)ge*xYU2k?sZ%e%3;Vqgk-{_4{&&M#Jv&?jEYerN z>KlGis3+dHhoFrlVR;~~qZsUF9|PFkFzwbf{~4dAzF^y1N5C%c22_J>FAe6ZuWOH# z&blKCi<}Cq`q@u?_A`%#CKuCmdzswl&wrWtm9J@=_8dX=eMD&WX$&sDR*YV9EqO5X zlXTnvLM+R+!=d5b0FOL;8`cOm9Q@y5fC`|x=*-6u(%nvejo+sOd%|2YSJ>WN` z^U7hiMB}q}oWd8wT>E@{`>VFx9r>1tyW^5Tc@I3Oq3K#HwOF%2QrL!qY5+6Z$Vz=h zKTJ25Rm!_9swpxi1IANqmDdl(wTt;nKS$Akk>Mu;TM*i;AL|Tb(O+M4}#H~ ze|ql3U<;M?ew0||yR(>*S=CQ66jXdJ>@0rL;VHo?dC#(5h@Z|;j9?TOE zBZ(y{q!;NHGrz7cb+YIJsN-z%_%Qk2*n!1k1_~6uHpuJe*a|eTg&wIqw#C!(M&>Wm zU#8=_9bZ$OXr3}P_+R_f{^7L)I3vrL!%O7_ZrV;woCJdG@o$;gmBqwy<0RFRwC>kIt7n%7c21)w`y|yVDyCg;x= z(_b%2br+0vlMim&D4&!DM;7Uje~nAPpT@{L8v9+9J$0i9v)MEYza(;R8j{_s#{X?| zDV|Ka<5{y)K2o;@#Ns#0K2(muckT;+xfnJl)5E~x#fz;X+&%wow)F4tv9O|w+$nog z41JZ;{jCO7Ku;t$M&6jxYP08eiAI64zgy2&RbXCXLt3i7}XhF6aeO*N2AZ&%2hFq=Wcy zW+cPm!O@fWdVqc!{%%3-2B20^bRXRRekz`SALeQZgzNra3MwO&_w-`vMU7??t?v|Z z^uA`%kHWAgoUL-#hk{!}%8SM*M9Sl;w{nC2)oMlGChdHe;7{HA(^91CDdgUYRE-bK z@)bLS_>58cqcGO!J>rg|y}(~#0ux6L6VAm(3_eoO4n3reWOtuTe)hH75X|JxFbhww z+C}(&jDL*K1&6l}l7bT#^YalYyE&GRuxze{@$#GLFK3+G@(y=qm@^b?pHI_lsW)nxF(|w;s#Wu>^Jd<5Uf0rNIL4_C z57`IY_Q+MF<%J5=mUPEllkqfS8%HZ~=$YKtXY+urXVN?&xg&D~31GY8Mi%_9H1DBC zcM_)xm^P`Z--JMYr)}L}2NFQ_aOK@j;2C3(Tn-=j|AkF1;fkV-(RTRepZUlCL*e~y zdoZ(#&;4$S6sKK-e9#{-L*zY#V_S`DL4p+c73 z&_}_}W5K+6{)z8jX7A|k-u7!msqu%Vb~)j7^3t9VGQWg28GBiF4aMMXK3<)J=1m}> z73ALspR2DrCF)~k3!}noa{krZuHiR$QU!hMNU&94_AZ0Pu&ndVEnXV=Z8W`IlEN!t zSKm*7eVP@rqK$vmrv~_W|9Ld^a792S3aSgg;L$g=7aUXJd+z#6bi7M}?x+WDN1dB{ z0VMjOM^5&_>>*p54m7y67)cv<`60IR1ht3yTyLfziG-&ZFctiALnj=FS-UyVH)lv^A0u} zh(MYy+T%(<=tB*(6YcpaAKm675V-uFahBZ3`gke`Jf7{Q_rRAq-;xaS-k)o`% zDs0(^+STh-LE@W=u0{9S-qmo5j^F4$EpJKTvo7;b7MRfD~zv`e;@h&9_N^%Ue%^FB2!Lxhh>5 zEjkjz2E10$ZrN5e)?FT_$?9~M477>XB= zbXVJg8!y3OCzYnvtYt}(?G*lUxA}*$)j!SZV0QHleOlM(f}aydI|LifvO^0iaa3y7lSVhVhrXOC%V_cPy_4g2<*tcGuNNqtnK|#0@z7|`M^M+0X&{RyP zpgGWHU5WzlHqN^?@W|nulVLQlA(e7|f@<(XVJ*NiAjs@xtUqq`OAKmRVaC@vWntE6 zac4i0J%W`v(F2@#c3M;|+qYS3-FT-~QSS4xO11%&fih#C_I8vB3~Ln1X8zpJT-5a3 zlU8248gJ5p%r2AQmdmm|u)d`7#DVCSBhu-0sWKEpmM52nrA_q#H>YtqORo&fugf4c zfXc*~%R0z!#}>#(OTQ8aqaQp-;jMHgob*I8;ei(*L4uSkG>?Xbn;s0`E5Ajx{6AUL z-@IW!Wd$mXz%{HBr=FfBD}AwE;PY6O)L;DQCs0}~A5B?W6VcLCl0w|H>K+U|tAA-E zMu%O8r}jCB81XXAoHQj0?K&K|+ zCpOWPbr63%-qY5Ey^)*Ik8x zi1-kwHvOK?bX$dY!g8>t>DDnh)wyhd^LeE<`wZ=OhHr;YcgY7koCvOND}1+)GDOTW z5e$f!y_PaCjt|GsoH}T+8FXXFmX-MOeBzRF*T@bpvr>4)tp<|bcGM}WAioocggZ!T zkfW8rTU{4UzTg9g8aU+x<9}=R{Zmv0*5xi_fy5(>@Wj!=O?j)ddFEwWyQ$@a?k=Ck zqJ!mpro1laO{q(csw~;}`v%m)(?;oYdEK#Vr1TUQ>eQ^G zxNTd1yGD$E)Ipc4^`|O__*ir|sXQF;UIf;S|3Brp0g%>oIlV`+o9rJI*&MVo-%w+1 zcJ(~G{IDAG^ZI`ugqGU1OLEJ+mBNN+aB^;Bdo-ZR|ed=EBqqw**1>}Kqn9AbPd>_2H; z{$^2HLC;aM&QFdJLM{DXqn{?{V88T^mKWLQO3!p$`jHZyjP*n9LpIwoSb9MPPIE!~ zmex1*8hpdQ5sl1af$tTI6JAy0?TQwIQ#RFL<;Y80$&!4G!6jwXw~bHfwOW^vE*r>a zvcV;*Y9W`Z1#rfKZE};d$JkL}g?a(4?RU-{!6%q~lf{Ynshru*rnQwWWz|;8cILy@ z$IdFvYg=3TmGE(@y|FSPy({gdyTX^32^x*ITKTopsT&(EBDU;8rSx~L2b69^-&wJ? zkN87a^WlA*zJDv$&|l!5&wmu^4;OqYfWVv1#Qo)-^`Big z_=QqsU>Crt%|XC9?BN-yc4P$KlQ~lChAd7{pculvkt310_O9i4%TbVTdiXoK)Xi4B zSC*a&Yh5r;qvm$@#&MR56T*60Owv|Wmf!7*cgjTu6@q&Af?go3X~$_VcgFHsriMPf zM#R3?Xr#z!>wl|GgOA@q)UFc$@2IoPV^M`wN=#8}e*Qn!uiZd-s*Zo>HHp{E*tnq}vGCvI4Kh^Dj;v>U+RxFNQTbk}8@bZlPx%CV2b)U** zr3o4B@y9o^oR?(IWjNR-kR!WNMn|SsGI5GBQ1>us(oCBF$`qc&T6XIXF2KJT!~+kR zgdTYhkOsRr%i7|IvKcQphB$1tz7BP*A7boqAK3oIen)m$7+>6wnQ`Ze{`|+c<27nX zZx^{s&`C7uZ|53&BU%zVpDvZdJvG#7N`?PUY**n2jTRG0^~>eMZOz&dXEzAn{6GC; zVMreD*Jr?5yPM2AT}PM3-T^}?PiM|Ne}QV_ZSGpmTSa{L|ES$aZmk}ot>Cm`Yx%O; zq_~wL*l|XG&tE!xz4fXCSOfpdaTa#j_fGzHl7n?s9&6L9h+j{$ai3nSf5qj`r zU@Yj7iaS-#ZCu||ksWVoua24n=|xT!*DpmG?>_aG@oQP=c*eExB||>;PuH}sK%d< zkNEiBm{I*SQvSI->HE?XqbNEZQ3Id4Z)mEUi&US zVE?_)b|a0Dj+MhLPHr958FJ=gvepIqZAkcWq>57dqfH$^-HmGyheb?IB!!tZR)ZYj z0y^F32hG%=C%xA0gvoao+?DC`Wf0is4#L~Q0;1ZB&3bjjV#crin@OB+ z@P4cZz)=bO`M0Gb!BeLvcl_eHMoqI2H*#eY4JNV~TeYoj8#+b;^WyM0Yu2YSe98Mu zJ%5qEoIb)vN_bmPB6T?TGn3g6tJzp>Ljazy4DJ>S)I`eOKGM2V;wPEo||SF z{;u(At@eVGyB5saEO+cD4UM*)ORk?`C3tG*bgD!ugnT@}$$m_G?AS1g%Q@H=_?hJ` zcqw!f4}?D!D)o=_@iwZSKVcgx>39?zNG0=y8^89?tm6bF`B-Q+KLvXZKvyQRJAC|1 zn*5KX3^+y;*sR!k^K*IiA=f9q?u|%hd0cO^ESu{=#C&R8Nx#TaEm99%PKow>JJ6%u zQH*<>(0{LDB}f0zvqE#pZ}b)T_9d+|A2jc2tf)-u*$D`2iFALj!sCF?$Sla2@{&ya%Bm94dit?ztyQ~lntY{YR>V?R%v(<@Rg9WzUr zWcXe?0JCkbb!jyEY5bu&v(Z$x{}O?A5!3FfXN|r=FY(3>rZB-{Lq%rjM?&O*ic?|P zb|T@^cl=<8WLwR50f0n-0pTMY8yLueR;|+<7)VuJ&4VCsYpZ<8Wh|nz*T=}T$scq5 zE371nw9Gv^vfmN>fTp>jG2jJc!r?W?P97@ZYOv7s&7wsCs23OraN*qYNago?b;k?H z<*s3+juwaVK5$CB;#v#<6OF|+>+;ed3!_&FjD?>+P8m@QGE_iVnM|hcq$l=w%kH+|+$X8jq?WF$2DZI0*6|8dGeFO8^lT%+8a7TtdFcg9q^iC(e*B2|Y zi(_%8Ae!`cCcz9tyW!d`YN8-w*|~ZeT(Lj3og4h3ov*_R#Jvzhf88El3c0)Ws4pyj zUxrStxowoVjo{7{N_C3o)T#qfU5kxo;+oosQ-vBpLABMQL2lc?N$`2JqNdw{FKq&E z>?#&a7Sz%!3d<(95q@u>f;FvUY|D8Rtvz<^fywawE7LBRm$s0>@1s7Mnp^~` z?v7BevOBt>I;95hpbyeJ_xG+Q^KyMZT-m2o(!<2rL`+3TBZd=03xBC7o@lW^yhHr_ ziD1G}rB5_$nrL-6D(qC2n<~TTNJG*joZ)M7N>dwOIR<{&X3TDURm)t<@<&*pB3mS_ zSsn7l9p)niY&BbgDP$WngYs#iEE?`HZ&i4dQsNKMg6A66c>dV0$ zj$1%R2N1Mq<*DsHO8$j;6pEVni2+5?S05!Ew(}8{A_^yd8HMd|RKP-sfXP=K0p4Z}oTi=%xBUhtCwdxZqDoH7iBeDD>!So4W8el9gJ8TI7WOx|}4G z_WF~yx*Cm^6eAKkbUH&k>_Qo}95dxaCyL8L665>pQWnv>`^#B;%{G0m0(M|+Z^e^< zuSl#n!kDV$%6??q95BIUBIrwW5EC)$5uwH7zC+JH2vp=mVM|(v6<3utM!Ghx>Q5(n zD!C0Ql&i2Kcs%9SHU*rTCt()^1NJ(OJM(t#(B_Y0k5_yIZ(bG(ID(FBq;)>cRHw0)0L1a<7MtxY z_T{lQmYL$oFodg-`%Wv0>}epD!6yKPPh9pj3_Yj(kVy-2knUt5{<>a~|4H7jCUfy)aWePl1&N zEl5`S%FS)Lo4WE!dHr4$oGlle)G~}sF3l(4Y-7gm(QkWwQsgb!ho;%;HlhX1+^VbN zrelty8m8<>hR8pYTV=4pywuKoUmkm-l%V7pi_>Fp4SOM5m0pi$(~D;fl3VszU~kSZ z?JToc`XHTP00-l0hdj2(PV}Jh4HFqL67MR_QC5rXx7aNW^b6=OTHAQS5m!V>?GDOYNIxmO;R(ntzt0gP zzDzWF(9gMJ8w=(T;cUK_6GTt62PpyGf6tQYS3rXsGt{{RWeGR!+E}3?BbM6;6mUGe zA7ISPt=iv;qq^AP!W^TK_ytBWt&bQZpH8jhHEiAbz#qAZ0!M?qs&^y6H|qnl?S$r= zL89dNZZ0Ba79*{W<#_6Z??y!0W1?WrIa}v)ilB$NI~e{zBTajq5v@Np!39xubl{il z;12@$K8(udK2~*`k?1aM8nyH{VbON-Pt=_Ay=r& z=hrkaH5IBZ;w+=|Xtp3}7P;Fph?1o9(-8{O=VOW*=1kSE7{Y>RIB>{b-xkeMy)~SejN(X7{38BP3U6wE z0JUH>&v>IFF1s8q4R`lwT1Aq+`dGnj)Vr1Dqu=g~@R(YcBsyGy&ISa#LshYkJ9E9W zS3w8yK10l0xkA7=n(0;`t{jfvd_ax06s^d_H6sh=54KkK+U5o9&7GbM%v(^zw_Dd_6jSaBvN8utGk?a~>8?cG_3SMROqZwu1p z>uaVrUzc{A*c2M5(kd>jm4=`W7?sSyNv9f*3EwKe`HHM@oE|yaE?_#(Fbj4n>nJX! zaI((7<_ALuRBIt^;B{!3b}LR_d{ynvIzQ2A_g{7tS{+_3IQSya*L%!O2 z)F@<%CkUd5i{n>EJ$@_V^54rzo%Jsb#pp-Yy11u?rKk_kCl)>%VH&*|kIcKoiIeu- zJSMq{kto#IO*a;GVo8ZB{tziV;VfBX^m@Yje>LrG!syUaQ9IP2pWJt%tT| z&py|tgO$Nqdj2okeS@h+p@n4hu3SSI)xL~^a)f(>M%blG10{Mp){iuxp(xseqqb|! zfrg?{lN~n~54uThYbqhG{g$h00Q%0S%Yp>gI@DwC?6KFKinUuQoAFmY1zMC~sY;l?Q3rI1I;46YF_pXN6C)Ky-!?8$h&z;bH*9b zM0r_5c_PZFnTaS}rGp4#+>|<@1TWA1?FlT#4`YmP<2Zm*sF|)wL!h78jWA zmQ;>34_Y@7&nz-35ox-Hh26>`)0HrU$s1(;%jfLU{HY^`?j#f#!RoL% znKWO;YL=rZ3teOlj?8>bHj2EX5Hv0S-bysGh&Qrx!(1Gbx&wZ&nFzl==kaTOJ9AAa5t2~^d#F4>BWg(8|Hp&qUe{*#Yu-7k4}{)z7`7Tn1tWl};N}jbt_J~BKm|2n1!Z`jSEK)YZ)hTgYpp^3YW#AyIY0T+1NG2yPS zzlN(^ukQ~{KO%Qv>74`4frU;@;ha<+)is9SO`Hq2!vn;J_a_L~B0{%Sl}^q4LhE%t zI(0tr4RcI7-^MTe;Bak9vAmx|h;*CRurTk7bf~oBecAS;>4s}Zr*C%ORN9EHKu&Bs zmn{(dv-L=3;3BVaj32933g00_J&}aLe!sH#FgrYl!o{ll(!x_>$Q&3U&K4xd%+Ge; z?>Awu%jYyyYlXm;_B~`tBqG^?nk`U1+l<-XLIT9&MHRQD>U>5Ef<@ulTFn{pJQwtR z)Gdm{(Lou>_Fu&nd^x_DzYRl3^aOl!k0vQM`Nzo=Lt=rxI4kG@mLirTG zB4VMARAiL9V6=hYPP9f-B;vfNT0zNAdS#4}NY|F}BVUMO>7_nSUg2;zeRF1n@a-mX z-Tb@L72R*X(oXDdd59ElK9??)OBgUDR(Ob@S21AHv zTO33cllnL7!Vty`EN;ByW=PnT4>73t;A~2`Rher2m~XXK1=wtrp25EWfDzK$ z*mq}DeW6+sD<0;Pn9*CcZYej5_G=Rmx1UnfbUmV!94~kx;wh3NeqBq+9T}s=EyJ-W zBukwG=)jns{Z(T;-Im$VQyQq=nv2gw)V@E{ym5Mh^=kw#WRtXMB#*NruWTYkQh-sL ztdB^Vt~jhm77vZcsgKWm^>A1BX-q=@u?%_@3`%b(tV?ppUM532X~CPclzI}tN@-U;n!o=M}+_A^n^b#hG6mYJ#l z{U!t&PGrmrXuE3O%EoorHY1}5`b=D82D+YAS{dbIl)w+nE~nd511tD8|22jofOYy9 z4PPHu*H1(kk1sl?!*EOC1&~tf)2HXXdYi;q?!! z*cO_5OGv;^eiLK|MnzDggsY(cIxEoDBh(Mb8vh+qkpM_VG3;Xb^KX@Ntn$4{vcBtk zYcaObkmb9k`3zH-kpMC$KOBV;eoT|?w1CYbesMypwn)52R@>n$F>&K;AyefwV+aYC zMDueum|>U1G;ukkWsh<>Kx##EZryZ;8v+dvp0_#x^+ex1f49Z1JaIU#R;}6ts1hV} z)7s2piY+v{0gcTC`f|Um_)4#2 zR1NYL`i!Qtj+->qo3NJ#KOl1&k~0fm%iM@h{qrkKDa#SRp?z<*op661j8J(P=+A4O$^E&PKYoM(#clm!qY4;!GEC4 z;7hi=@}eQ`qu;XBamSd#knVn6$K9CF! zXw$a5ti%ykV2~CgYgy2~p3LX$DHbJz=cK(ZZGAxxcU2wQleTl4;LGQ&Z(uy=rm=6P z@V+!~0}26_k(jcT#EU!CZ8EyI7e`;8{4`g6(^aKQa00&pjd2DSkegMC^!_}Ls4WBl zH5x1C>X+~gHgL(rcy3f=`V(`jmlfpr{wDhbe(HSe3kqdNse720)R~&M$KnmVuD%k% zCz>2nnqop!4W09QNQ)_j_330OAPidT-2`CO>vkI%eE@!=E-i+l zmd#7mWTDl_{XOA!Ox%Sa_v!i#6D#S9@$zzJR0lHeElW?Al|{cTB5F!jI_J6;jg=tX z<*|Hb)GYB61&lbsg=2OHvXywEP&q{GHVPm83+R_0Ux7yzV2#INK5Bcn_Ccn@d$vdZ#7;a zl$=K%%XBNS$7=WwpPRohS{l=I54{tb{GN{D{#17I;l=LR+$-i*7{aCr^Vm;&099@& z8}az9WPRk0(4~AWhjR`w2B>Y&8ZFt!VJ$Uf7fG&o$Q4L-P5Q&v5YX>m;fCuu)pFZS zEhl>gDg2$_?0}nAH2jCs(J3dSZ4U+GAJ-O!@gnyI;{N~ZYk>(2ZKmwnYS?Rj>DxyC2nWYRd6Gy}KQE^rU5Ow9eK#7aM~Ap)SXSfpAZt?xb8_ zY;HV{6uu{wm-#`0=c%H@} zbvRH??D66iL%}n8eOEW2wUJsZPw|R?LiYa{@agUt!ZmEo`!>Eo7rel6%Ezh%*C$tH z6l@~E-I8})82=bB2b2c&m+QYGX z;E_-%dX}@iZr7dY(mMzE}xTiWmi zox&UbJ(Iv>;#65_V58ECRsQGPzBC{GRfcbGe8Z`L7U@MhbLCqFr_w;%uy>VCF(NMP zgMZ8I^m1}66Szo?5RhZVNGHt4h|lPQ|sa@gkBd3xsNFUh<|v`;LiHmBW$oz-Dl)|e*2HsgZl4RPZrYNFf>HM|icjgr9u zbBR>~@EIIQ<-dk%i`dE-G107D$i(5YQ+Ybk1PA4%=e^>9Zl1t9j-llkIqsyAqy81- z{|%<{&^H{9X1poe|8Ic%-Ox9xael9h0K>zbeoY(wZugM}pn^CSBbwVSHu#DHI^V1C zRpjt3bFpo;IT;1jwd$=t?pn4q?-wmJ<49HWTY~6}={Mf#m-Hh%6k-NUkbk36GK;uN z;R4lzg@tfMK08WG4VT&XCJgKpUG+3%J$`pfT^KQ(CM? zCCnC1Zii1ruJBel^bN29<7&$e_9KII13r9crSGTEzy@opqt%%8C&m_i(odTvJB3=D zt3eT1qX{{>zerE65bu;2B+yz{M-Mar|{-C2|sP*?Jl;R4xL3%ewHIEOpoeQ`;Iv)c%JFY5V~{^65KfkO=3^*5;Kbg z-O=;aypsrEVp?rd1IW6(s1?Gf#^D= zh|c#n`vv^4g|9#%r`r%?(*K%8?D)+nu1lRM%n?W@rSDjiP40uYMzHMXR}wr09N+_W zs|x0imah4`82h}SMgk`sp%K8zP$2VMB;Qc>=TPd~;PYAZuW7DvQ)$iuA}Tbr94F&S z;Z_)Q1BhcNwIXKEe>3Ll0MB@-HtlIT*TG`D-&f9Dxo+GEZ2%bvxEjLOFVlG^rOuNY z&!A`y@yGq-%_h^MiMRnTL45zVXz}%yp)YhBMNyZX1)NW%2;UoF2eSEe1mbmP;C_AC zdX1)E1T?1)U~-jBIMcJ0lC8}yip4p@&0#xAGe8SIn*}_9d>A&)mT&|^Se;EMq=YM~ z<%iQaNaacO^Pc#zML_7m!tjE^(9Xlp!j(`Ci5`WgW;yLi%XTdH%FBIZ5W_xydts6K zolkatD!jLUwzvM9ZN^)*A-meAfW*I6w&4bWB>uRhwRfIDEZYuuYTxfg{iuKkLDb|* zoCjYTe0Dqs%FNG_O~2*3n$VFGxN{Y8Cw4vq1CMeWF`U?AZfAp(+$0qt@U+K2j|^tG z=sI7XTAyL8SrG|Ir=qG<9!S+(H&6fEf5wQRZYf``+wusXBE+i}LD^64^QkzjYB(Qi zC~KnthLcQMxC4U~Ya6W0VA^eCm9E7Wj)d{9GKIG?)Uw|)_~6D6NUc$M$5$ z&>2MnTAFE(%NMxcYu+Erhn6qLUzN<;R+p;TU`cS&rd^^yy+?;Tf6mE~Ohw9Nb8i#3 z$Ubjt+B~dCJR_~x0(G13keh>KpCU;H%~E(`$$IGva@YYQ4y6UFKHXp8v7W)DQ8*27 z;B%e^r=| zZ3*Wn;W4XupS&VkcS`9>=w0SdlKEqTqPb2}K29B;P(aci8o~mYtNk_$ebLpqZ;36E ze+Wa!h(@xY%K!`99to1&K8nTAXn5urw>=9>by4HHyanc#j|KHakZk=$g>4$Ppra|i z|41h7FSg<`AjJ?%ReibnVt`YGLWX#29ZH*^*{IO#V;gRri#OF3NlQb-c^7?*L)9*cN|wwle(A;rJ) z8G;9MdezH2bFE7Vi+Q&uQ;rEoXiOX9{lV|9qinN=~ zM2UCjVYWZ;zCJ?h#$em`B$Ac-9}tEFuIG^a=ISV~^cm@1qTuHrE(eQ{I-f&+hdbF) zyD4KaUrV74Ksvw*XL80Ii&$BLCHK|JMlK7DeA^%bRXpR=nly*C}c;&)3P?-zKeZxGeIyA{%VnVz6;mFDlk>4RxCK6pdTmYlhYC9Qt+T+E~Kz`>C32 zk3|CQ+SvU&UmycUm%XB=%N2IAdZQ}>I=A&siwoq4LXM41N?K_8$ae@@2OYVlAUJ>Vor;E0~5HI3Oikh;lkm+X=7xDb(;deh2FA)qegc^(a z8dgZ_LZx-pR!HXcE4bZHC@soQpK}tiM$ibq3BN`x=sj_KDerNV`0)BR{u=hef@d9D z@2in{#tXHPS&9B6Ud3WYEZKqTLE?~X@lEk(v4Th+3?LPSEgFr>ZH8V$|7#mFoQr2X zbc$i+iq2Jme;WF27+l~Jf37*r0VhEL8=mdf~0%{cMO zy?qbbNjzf%xQLsw__(qT5`WxPAk2}kv!k}F9_H?b9q0aW_07zR!2Et)>-?JQYMpZv z28?ZE6I>^Kc?(J5QK9|xaCClZx;Df7E;*hD+o&jPqYg`~!xjfn18vUs;j8B;?M7*`PUVL?l6ct*BrlZPh+7KtZ2A|YE(D5O zm&A?FNL?j(o{VlXX*agccOVQm?*(>Hl^S_~={6KP7sh#d5erUGg=x4lUZXh3&3c#bv}ZdGSFBl+)Il~PkAGVFm}3FmEOGN0#EnBAri;FSj5@b zVP>5V{?o%w;{deO`jB4+X) zyho6wn<#HKt|XVJcPCXgnspx1nqt+{2EF}i;2te8N{vQvOy{T+sk2#n8tkIX&@x9+ zLm{v4Yo2z#gg`yL==JGROC!p9iM$Hr9o2Jx&ms zrw){ABcnm7&bG9No?Qgk1w**4jTt~?H}lMMh2%?nC3-Vz_52HfUef7Fh{n1j15hg_ z_zAAVD64)F3fevOZ)6E2jmDRDqJezP;*h-YbXxW=)AwNilMTFjmo2qrGXV<^dvY7RS^&!&Eoq!=Al`~Aj z+Pv9=7Vcys2EkYH>gndipD&0&-}GI8N=IM!4{ z5^8w;_0~w>f#|=|7N;FJNekSPSR6e&2viepeGzAg;B-<_T& z<4FNz(lL&D7-%mN?zzHbtgDRPIIeheM&aYqV73tzP0LTPg|pSSneqyFoM}at$uAFqFJHoa@?0 z>tu-|ESlv8zigCa(|WH2Hl!?W53gYg7xz6C0Asj?D4vxz@@|At5gg`6A6jBIG^l<} zHnjQr=MzlW3k6F^D07x0xwj6MX;2@7sO`|bmy})sHBQF&ciMglDwPs$O-)|S2SU_2 zSD=g&-)(-J-T;Acb3_!iH*|m9Vo!o1Q+Vhd$lL2AXA^z!ChYQgqBBH@B51Eo4l|08 z@gW1Rk8!_qq2K|(zyMxUti9eX4s@`Yriq@3I6%f;1i~}_c8G5*eJ6I(?X~R+;E0be z+;k+S?`POI^kL(677Id!Y5K5d*J@s0-l#vlpf$}xVSFgCE-tO}{aAQK%QI<&cc~(F z;{HX?ba+-yMrB(f0no-lfwX!V(N0S`4XYw^`8z%p+M(Lfv~mVF+*TVInuiozKI%7m zhecV#z9K_Tpm2|Kl5+9h$90hsu6mmqKwh+TO1R#d`u1;xsuhgVRWEDBpT=Q4ttE83 z3a&OnG@$q@G=Q>hP=^hgg|r-~3dtN^DJbC^AkC<|sA&&VI5AZJRNGb%<52D;$a$pE zvIoFWMJSMKx7I0K7XqQZ?)mMKg!5jyAlXF z=MDa>S-v0H^!?AyW#Uf7rp+vrQed##B$<08*R_f!X@mvFr-LV|HptHmC#UjkGsPK7 zyx0AP2P$3fHAQUWfhd$Ilp8KFW^b(&5mR}lium34#iXIlcyTe3eWqiw%b0DzfNi48 z^DpN)z1>p;FG-MbGhC~xEKT;%W#Y;0Od%z?&V7v%dZ9 z#AsJ%zzzZHRp0ua#$B6XzV#%HE58{uN5RWSfGgRBG@VzJn+lxRo|xMx?TRYB5_5nD z&CQGMZ?-qzl-SRu&A3(I1Q4fIYF-9vOM$+;*;KW}eW+}kWYdw{l+WnB?@GFVRiRMW z55DZt4WO>iPH=T^$bMii<4HA;->56t* ztXMzK5JNhkrfq~u<8YQVYXdj05 zp-oQ%xRN3KpMzZvbpaz2lXn&s<(UZMdo-NDBe6Jx3G+jJ)RfDU!>S{r?Exl}rN7F% zCUppWL>e5}Ef%utK)FoVZtg#`wMsn0H{{Ud>ldyj>Bu3SbLm9+*5OX#yW!@5tv=aU z>QZ{IPnmQ;y<~WDzU(HDA^vCk66oF*Oi*9vf+*OKfy-)R(H3x5I3zL^@W4gnkO>x zfS|FrbX5VGzAZ?L;oD=7+W#Cl(fHN83%TiA^WusHvf&S^Jti*(z5DTc_>Sn-#d$V9 zHQa162S^yu7GelKbtp_eY}tY41?&PGo)(uQ$vk$T%whWrhh~}YtJ44B?akwwytDmr zt#zvkb*ZQ<5dqOESll4QKow;Xg}O|sg-9)_Q3*RFNC;?M&;kL1iU@&GP_$O4M8gsi zRFn|GAfU#FY#^IJ7Ew%q2>i|iw$uBaduM9z+}|IquW{*^C(q||&UtUAm=#(A3Jv7! z-C=e0Dc(Whfnw$4sR*<8Vz*s$A{!OW6A~lqZGoliJpc0EOmhVA{Fm6J<@>!( zIUVh&6g8$i?8q*8Ct1|;E||7klNFni*87sIdnAaPFjm?BR(m#3Zn_HCf(R&rsZ;ml z_!d^HVKHAUK^6a6So?*ec!7WpUw6)qt)LcRsYZwuf78FH`NEC6HVX1unRL@^)x2*0 z9+9@Niv9(l<%QMMLJ(E}ou2}c*sIf(^AM+LK%Ooo=~cc#jl+)6&p{YRsxqscET)#O zVcsa%vEVLx(Dxp<%iYd*t0UJ$b^i_I;6J^5xz+<(6`sy`E@6#evtb1Y4u6WQ+;H-N zzR~bu#{%8nBONxomWe2>2bs!m+iADmx*jA*s^u!QcNshaYc_`Bago8QbhRHesk7wau-ugCoqV5M+b?`ahd~S21}0D zt+_~qY&$3Ws021W?kw3^Nu?#dD6?MIYz??0y{&AkoE19SH8F>8nB2am)1h#~Ia1o1?<-1DRd(4bizmhkP1;mlONpF?c{-9= zDLKlU;g&~zCZd3n1C<M_lndK3v=@*-7a;LX(VOb+cJPmxsPfc$vzV^5mmg=E zJ?C0-%b?>{@n1Sh>SsO~uk0!X!tYtpI9x8xR^3SIfcmWOvqeBAACmma^&UM-0c37; z|5B)0)bHxmCILKZ$kIi(UARk8brwoHz?dK4D6t!pgOAAv9+|lHy!`(CPX+N7RlTUH z?RN>sBExS#YPow-fnU_k??q_*^CIm}F-DFOg3O(d`AXwFsZ?`i*ndmq+TkyJgX!va z$wafEo{{<@fd#0A4g*lCrMKl?Z->Fpp08Q*u78B^qkH|M|D)pWmZmf*23BNOn#$?8 z-VrBB3A*h@`Ps7&d(Yo!)BjWCABnV0Uz7Adkrf*fxchGDo<2#{pweeJ9bD$3?n$mR zP@$)(=Us%t?&LtC)tTt6GW=3nLpAW%->*&0{*|R7%5P`HeQDc81zB76oKH39w-ro# zJ63cI>kG8;bgBaW{kM_g{$oL9`(!s(O>ua0w`#QhbgfZC>Gp$rw{~`tokyR~lWUKH z@Z@bLUYFd}>N~pg?)Og?H~X}e6tVF~Ho!BS^%~eqE~5&>@qA)Mos6#rKCq0B1@+Xg)?5=^zDW)M%e_FR+JaZsfGh9Gw1v@*dLcR#@)Z z2Jq4gwd-;H`gD+WE=88xZ2t>AfC)==&NntZEpCHtS3Jh=-s{}13C_MdBo{5PBX7RK zvwNEwyqK@%yK%o&D+Xy3)T7c7%}0APfP0>8axW|r z({+j!(IVq|Ys~X3YL&pY>V)9R$B*E?__HlRgnn!;_-|T*@hb#7SB(lq0LzPlbPX<; z*>XS1V2^_U&==Y>Rhv*^Sr``k#pw_429`xF!8C7oUX;;PmSVeaa2R{1jBtUhQ<+=p zZ_my~_An^ffXzzhlB|^8xsyvri*)fNuP*evpk|7$>k~L5AGI`$ezYKYro}*#LM(4k zZ$!~S`+hf!^w{W|g2Ovht73W&mv%h!Nc_gWtQi(YaLZAiRZ<3%TO(^}(`9f8G(QH} zu?C=QczKM3{N*Cbssvi%T6;(n#`}|S>gTOa3rMs(SK+C$D5cPk{XX0aA~~2OWf0sU z9-I|$%nhj1Q5n_dvHOEI4H|*;bd~h|{ZR&RM~Z8qCqN)+j%Z(iHVQ@Z*R@eYH%qhC z^w^2D@wt;WlrOr~=gz29OK46%!G*gDj7=y|;vC9%?k|~OEzgddU~6>vyZCi?kje?s z?NfnYRwsN9o{B?TBFsSlG*0gQ-P}ZXZxuNM3j0o;e}Vpxl=8Ouak3@% zq9C$R5Pqvo9(HR+dEB!Kryf3PoeH)@Sb(eAT`PQECeqG_X5uEEmg`0FXR-jVv7`m( z>#sOU0#a2ab9oy}^`*_;i(KDwKidyHY zZciE08v@kvZ9a{%2Ru}Q%|`pD3Blp#R&Up^E@FuV5;QpQ@qA6)cb2wBT~0B7!@X%K z#Guqmclr|9wTgERcdGm+m-d2Ut*YamW}tVXdeHNT+ej|$J5o1ceUcw4UPOh3gCP$+ zF>fCBuDaK~OF!xdIsl<|_SVhJL=SD!&P|-IUb4=*?MAba+evKmbx%TJom9 zDzt1s*LuB8?>&2vWeks^T;M(%fRTBKZE3@nBZ82LrMmQlDpg8OCS00s3e~EK4)jTP zj>Q{>sx9wOo?`BrK?}M;ZFnBq1{a45^U}p}IwFGIA7wAV9YfYF zks2MZBK)y!c>5)ZCIGkCX8%bfoS6XIu5SicgF2exaj6gY1g=w;dq7l2D<065;&mRB zgDAX5V9u?#txKHyO@;HZjir9^x{L6kGkLbxMCPr~_&Wq?zGZ-c3;6i?-3+&wGd@!W zFcYQvo5KnjOgeWex~YGk;5d+Bo-*>?Xl_-Cy{i(xHZqT)fPqb%c06}>8}9@;rIn1i zt&dov|LTb@{zZ$+4xgk+q~71O0M5Y^fvW4<{nz@51P2Lq2PTOiCNUmzuLzD=sAEl>v#{A%ou0D78DxL=7)hBGEs&`6c~OEGWTV@*)bU5Axh81_;o5WlYu5 zdvq2{CEzq$;GRN%RT47!Q}t3pQsH$_D2pO)gGr>d=a4q|6T^$mas(JUaquoV6abJ8(N~P|MG@nmt;mNi zw*-Dg4O@^GLY|4mQ07Feq~6h0#|CJwN*|RE2COj10#Xs~u^?#M64!AEX!=j`2EGFX zDbMw=m`i+8P)!!ozJ#lVTlhU69NDp`C-e3$RLG1zlJm%klBFWbYc&uL+H;0VUZ-1rAuDV~oYPNUUpMxI$ zU7u05Hw<>`NbC^4qeUx!QGFXu;(fFhak3U_cbyc0ds|5Pfuw&mjk@8*)W|~>8SksD ztx6c-c1=>enz{{;>Ic2%0L2-RaQ&d94ZoEr)ZN@!(y{s4jEGIT2S&a9V8W~jxtxo| z1tqo2UHj8q-lcLI-I-+h*ve4`m@<)op(Qt|6;ZCkjs&&qmb+{JL*M)(Tm^4bp~};bnvMpKR`$k!in%j{Pdwp@7YLsnBn9WYtY|X3z2-i8b_NP~fGRtKxx_kI+LVF<}Vj zI(7dM#6+2Dpkfn=ig_e%Mip<%1!LIi>|{dXrbX%^OLaYD!v#+xfOs`ghp|*q5oC~n zS(~UKKkDlQbkRCwYo!7u;MM;x83+3alWTdPM*=3}qO6r{tuLFtQhxUCRo`F-9Wr_4 zDBU1*bgv02vQb-#&z5iQnj>9<+tBDAJF}&GSkada+M+JS#OM}Ju=UPtQR^mUzmvhw zS1f|}OHFmJd^=fR`DRd&FgiHZnV}EecJMRi+mYB*asGID3a~p z7NsB7K{wmxEPG=qeru}U2Vsj)nx5*T%8ROle2QiPGhrOFtt)0FP}-($+`spd9`)v_ zxla-KOIM~02@Ehw@A-+U!N^u>$-_LD+Egf@pPAWIVM>L4Q=^YCo_kH<3lK< z-lOVjT*i?D8KvlQCNm1k0gvtY&lx5Q5YEZBINQP6W6VcWe*aQCjn-FgzF!__n34|-GMSv_>x;do%z|2JB z+NoF1?JD&W#qpkGyH#u8Gr~3GI%`oqPF>NT$O|vSxcJP3U9{Rx9BdVzZ=Lvqp zU48Bp42sU80N)2ADbV@Ar~qaYAE;WjSK}zrBJF1g!$ckPM{)$_i;_8N7}GYyq-(B> z*)JG3k-wVOlsNK)7h>DyC5R1u9mS?diE(`Qxd4A}8 zoNZGg*LBsp4A;&5sF>wa?(+ly9z*34G=+nL{)sDLaZ{tj+yf@ouIlX;GI-A2rb&(V zvD*}_BO~5^Cut>=v!^2u!X@~B+vW_WtAa?hH#fRNG3D&x=U>x^1u@_WT+tfb_~2!E zGssUi_;3*<&hcmV@S@hZ4hd;dUbGr~qI?|A{L_)~NZMiB4 zEj1J&W@`j-LMw5AgOnD*NdXSQI?SEo-^hBHtGV}LXr?O?o)s3qYtn{_k~rv^%S6$D z+kj|(pG03*CAMU)O{u=Y{Kv71ABXOk+okwYI> z>PZIZCecj8{r_fo624BQiQT3-b0^1dX?i0$IX*AfB6>0r4P-gDf2s97({arN2-GsF2%G*} z$;1Q10N7zLlz;!4{>zgf?2ev${lJ^H>o0>VCO7W5P05~;cXGeGt@4PS`EYMQ6Z3!p zZW4P&`}>RINpunPlmAZ};+6CwGB@26NCSFg@F#|{k{Q+v&ECPsO+}*-lXFLV*1vn} zLup~)mL@s-$BVQEH@)ciqfLMnu4Ac&@^Ra*c+wszZ(lTo4MvbZ1Fw!PlfElkwbwv5 ze@r!}56xD&Hp-e>$H|oXXV7}M+{44t(cid~97tuYZ{-JR+NT9Cs+>fl2u!=c?Sdvt zpptuUFHQt^oJ~c$5&WVuTh$oox(p=2F3=Kt!O!xtY6ChZ?XG}%ocD>bY})DNEyh@v>V7!((uD30-*-*+#QgnqNnu{pvS91rGXz* z!`({)g&-crK_5fdRtmGl&HYQykl_e+T>)L|a4B5OR^B;B53at)TBHJ-QJ=$~l{Q3E z_8kKI1S4e#1#&FNWsl0JAKm%Ecq894mRFEp^L85^>~o%fRzK+ zOwjDeRy_IggP-RcMI=!pl~j1T4`km;6Tt69p*u zDmIgFwGDvRX)aRDPJ5+xALV%#XVFfv2|WjNVWn9J zg>*XXbOXwuQDpuUKFck(2Nd=8e3{$aZ@?z;sc&$Af!FqiQuq_uw3ql_6XBcBL3Y4z z%&HzVeL~P&3d>$lW}h4hphP|iqZ)SCh8Ck%@T&<}3F*sp)%ndS?V(f$gsVA4bkjt2 zna)-wgN9>15!YY^2=MY^(=kKzb|tYuA+e~aLV^#2?x=n;F~%eTCr0E;5TCsDF}aHr zv+{8c+xfM{%>kZXeNnr`YIL!g^9@f*SHa=te))gUVCt0y6pfhB} z2o4@5IUrj^+Ghhn=Cauv<)F&?xV$%Ig@|H4C@+GT+g650r2p!@ox%Q8P}2J;Oi=xK z*t2TLz@@L_P_vbVQ~(n^fZ2a2qMU5vt@$~3A>g3D1VlO~R!9EiC+Lpu0wiaV31Ikz zt>lodgQiKM9WMG@Mc_jZqjPcH{8N7)s@60t?{;3d1*he~4#EN}`Bw%6~^ zA>T^b!toSR{Z~U{^Jp^-K-4b^Xr`&I#iojy*ZX6-DB1UPsbNmMW31eHLJ*FnbZT$L zwl5G~);#;oO(M3E40v}|153_+hX zeUWAzNXdO+K(8O5t4vjeeR1>Ulk)~z9|`44AL-Q#v69=S>QZoOZUb*WS!^vkxSG%$ zxW8x?{S+|Mc_@=fO;cupj4r&i#61FTW?4cT@G5H1do2@bkL#u|Q$M z&vLSV)xTEk?-o1{Hx3IGpV?TrBI>m0GMMIA*k_v3@}QZy5HXEv{Jdkd4e}JCp|u2n z8M_AC2#zO+TCd5An&|6-xiLZL(ET{TQ5*odf*ObB$pq)Xy_hJ)4an27XMzIMn0tP= zj}iq9BmI+~=kUC(xvPXCbIEchKE9FH3pdVOgkSE5mQc_a0-lP$(~3&{-WN}bzEn=( zl)P@wtUd)9duDfA)t1Pl)xI!0;>X;U@R6WSB0p?F3lHHuz(Df{&F})?>ZdoH-IY$% zEmjzfQZr+dY)VE--ce*`f(Xx5OxE>+eM}|&(B6|devPsV7xEm=vYC58Ah6Sm;$xKm z1OcfqpyOV_+PB~({S%Twpp{^m>C2x*loXRQY*x*8B(4QLTQ%h#ba4R=lD=yx|3)O3 ze7Z0*;L_B+z#Uy6hZADv0-$jGKlko6bqsnjK54bJ0>df1fv-S>)RwMV zn`x_B#}=Oik1-BzK2a|uwve#RZZaLdUu4lReKr19ss|;)FpLuj1({d@+%JmlGY3KOou2SWRfD2X?oB*)s0N(8NQcwt7?zef9`pFKwL zTDx!&dpZ-|k3qD$1~2NOensUaR)>AxE?Fdr@CyeOAkUtpKaaSC-%~zB3i4oN(saGn9()atXEFw^d6FLhGvA)V_ML`Y9$(BCB7D=CnDWGKAb={T>KaSfa4#E#!p3eN33v= zK`qXWN>Y;=&U>ZxI+$t}ff*mQs=?{WLal4M9eEYKgw;K}0yw?+#n9>!eC!mE8p6** zg9xqxk|9SwOP%r_`oD!sQ5#npAuiE-RbxtV$1|OL@`Mb^!ar3io$8+EWU%pd-Fv6z zr;!Er#TA+IGSh-rcw)A<=DRMC^#dH2S4JP>?YgGp*ydnHwD> zryKSv4**Tl<}Na=Jkb`dhVKxbsq_YeA|<`!Yk}&EcAla6amTw?oy3szPPz_=kjn;C z)EK!Gfp@bvUHymiOA~{Y1UOlD?RKy=Vx_+MWoS+aOasOqIx}tws?|fs%Sa3=VJ?Eq zin#`8(vPttUxGd_8O{Kl3)5CMVZTf94D`2*Lo#z^}gT#1?D-1TSDu`4N z|LfW8hmVN0@d%n9soM zjD>dJ=C$nH(~rk^wEeX=RCmix9j9HbBAgjNfI=(TjceGSc41d!-iDl@4ye-`x3W|Q zDA3W>LR7$C!FgfGQ@+FMx(3_rrX=ohqCYJ3+fp8Kjtvbru%@!J*ZZLFDKJr;1ese( z>K?4*^h^o|w;CLNWB#&2whUH|CMg1`A23c5)>v=$DNUg4>l5`?L6=qmg2IM@APeY4 zU${75XSmX&;sup`)65)xG8{%Rp|E%^Li)SikA^Cu1$|{PZ`JBJ7C^i{Q!RU4PnQSe z>lUiIHrG4jK~Ff=hxXCFg83Q3MBnFsfVeVp%-BpVdP^zfqT_P_4%OA^Che*cQgYbz z;2t_wk|GF0v#YB3qm})DpnuRv39V-U3Weez2T#6VNGuq0mGl;q{PJkP?7nG!g!z=5TknTq-7O3D104zm!KDJBt7Omn&3%%*^ z4cJ$J%VB`{NALzcS#O4xI!g91v^#WkL*5(r$RD>EDhW)P)CGtb=;PWqK+X=x;{&GR zyzVvRNZ}UN-N-8fqn$?r7g8g~MoN7uOEssM-m^q1wDbD_+WWt$jrdnTeS5|4zVC>5 zCg{$?{s*)dpd4o=nAYkc?aEqWciKz{Gj1_e0Uj=SuL!r~xiQFkR@P81c|vc#izwa1 zpZ1#;05={4`dsK$S>hI*z?Qv+UM6=&O}~Qys6%;Mii=!>`kmJCjoqpJa;%v9Vh3t< zfl$wPLW+_oAaX%MYV;Q7jB#o^p@kgMu?L65!D6lBG-$T#p9VukVW>ent6D;$r4y}d zw5|`QQ;op=68($yhe_l2Q96`Okbf+DfIS*`D6_XI1uoiGKy~ z7CATP`3tP{gXHiVPc||n%$);`F1R*dU?o}fhvB6m zy-^=bJFgk@b0wk&I*GsL=!1kr_@u}6O;)D}>Ur1TFat>qa#j8~LiLK5h> zm~D}U)Jpi`C)C>()L5b6p9GGD4>{kN5NnGR{=vrfDNBW7WROI%1hI#IcZ7zdbxtAS zxQ38*Vkuh_R<3cJMhz*(`@krPsxfBsJWJs}G(ACI?jR|!ekar#w0bdG@8!tC1cwj) zd-)oAa z(rXLaEpkbIR%ixOVj^6KzPNz~5E^7k)$?DP1#r zjWG;~5NX0*;^?>?<)Agg)nlc8(yHSCFRzDCt?8hz+tk0AdibM6!+E#2VTXN39&L*M z)8H%oB~4L}$p=c$T^wh@CweNXy@&#^_}i!#Qvcpn2JI(CqW~EYdZ=v6Y@@&@rMnG7 zr?gMW+}uV5LyL97ar9#2C+eRU1wv$2q3ihUL^wYtgc`G0QMDf22#BC<9L~9PZn;s{ zIl=zNxhQq|Eu>oH8vhe_S_pUwrQ_y?MATCja7$B#IBnv+9iHhGB}NNjO>_@rErW03 z!{p{blJ0Uuup-L4qd$WKbqIz zii~b=D_f@9JHdfu{NQ%X{(m<`?sJq}Q@a%=VE>Px)?$EKL4UopHEt$dvYC^Rs=fwg z=)M;v_BdPiGE_(9yzx`P%7N~eKrA(Yy4v0Y61#^VzLeM4!mf4>&C;wF^mC9^33f^X zWK~Yg!*78Bfcn!{AScIUv+?^G!%WXYU`lnJWDL-RUgrr|D|9yn05|1wT?h?c^v~d- zOw)CF9!d0Z3-@=UrB<;PbiF{GMAa&)eokP}!5Y~hgo!5B6^QVv5k+3dVn zqAQ%Omc&{E)%ii(X1+UR7K&FIL7F}dzD-T%>)g(60TLc~xOUZ3z_@MPxQ`I^pM+im zUqUc`A)5tJnIA%1;^!7{A-pKOG*PGpKyot_6oqSKI(zu*Gh!IAj#tqM*{Y_weKnMj zguldFq64&9^gJQNdp3xTFt+fGh6N9vZQj5HD(@O20m1W|I~a5DWGPXN--AY>xFWA*a08|%g@CB&w>#{ z^ve`j-p#>uoU3Z(Z;woAXKKv9%}@&8KJEv?c~2%t-9f)h%78)yqvgJnsi^0vAAneN zO!FG6OFBq=F*~o*+l8 zw%&-JYOUYz@F4=FzrkXVTghqwVV6L(52LODjjw^TzX*}T>JQnL1#ggc+IT z@h_(sUg<>f5(TXiRiba}zcT}k^WR?R8L|nTl6hSbu+PIU?)udq9zFnCXIUe?h4i%H zK#G1*o4wiHNp5`?b8Ao`c8I-x=33WR7g^+dAU||ls*BS9O3}oLA?ioU0_z&=dzFQw z#tX`O;SmT2+90rHc>*ni>^y@8cZmvchYgIsTs_?)IaNfll)CiSfvTYoqM(?_%CSjP1jp`t zq{4Bi{3Mz`#6=ICY#S$FtXrj-OT3q$c={|f1p40ytN)t`lQ38+qF@?_kMi2{V7#t0 zTs6_`!ndw(x1}tBu!XfE&EM5AM#*jWYj_9qp)Ih+>knw$iWAaRy-KoAcquMhDWh&K z&eN5@VNBDy7G>gR6tiA}h)_KbqH&YEV@j4%ikmd5*>Y$%EA+rNf3zCUsDc4JBu#mJ zhcVAPSu>^4lm~e`g>VPFr$CBLafls)ZY+8Sco0T%C`Gv&^CO#g_W4}~Y`&E%KW??9 zj)|u8AP{&nw+5o&khd%q?S^#JA9pg3^DszMF>4>lhmC+5BQJiT;&t-tl_(aZz|Rt10;P&0UmSbY=S8h#6#;zT+M)ui6FxJPz4y9 zVWYvVHm5e-ZR#yVvt;WpD35a))P)F05qL zXwbPh;PSA#(^hvf_r&}tTi2NA81X;W&OG>7lYoZBWvj1;NuCC}04aIWtf|bb7T{$; zgYCVsj`LwOoJ_U7jg^2@)6fD_+*{h|9>CEXFBdyIP<2Gi99s80o9oZ9KS zD{TA}1PDneod5@h$a);4-iNu8uIi+&--k_~NDg(nZkhqrdfXs=vxW+Bl&}&+yhO&X z{Ry=NmH(D}!T|bj?xht4OHpeS+5w5(r@;D|KHHT}H{G4@pOgHee?I3NwXWrp&!7nb zTgbD2&?D*LFd{7m7=7xPhbOdH?eb% z?8V&);_wcq+s8X>B96Sl!^}R;Wjac&+8pe{Ll$*IRq?2IYSyPITfvp?D7pMG?R+{< z&v2*o@1@FT-<3ngBnb$A2i8VlW502 z1wU?1`{B>gMG5pD%bzyHJ+mtZpwCnTCP!;i7$_iM)<0Qkec|x@h88U5&jy(M5wV?1 z_yj#p7^#fb?e;9ZW1Fsf^2&IJsnM&Kbjx8S)S{|_I{rRXncqcWhja>E_1_Rt)uUA# zh_A}paa-VH_8zurOP~@{ko#zFud_zkqO_D!4|) z59p0*k8IV>1THQ^aiIX?Q+qZ~9pmss^sdXKWqJ1iZ+|{+og6ALq=Ywz<@V{DK~c~) zys~13YhP7XI&b?0olN`~HW#6i%t$CGZ#}4g$T8r-el@sX36}aR4icV;+NM$3LMG{2 zL3p1}Tk1t^1O-enb?AqZDjxMW=oWvH&BJp1&86bIh!Z~T2sy+71RC0^o5L?(!@D>x z9^>dGGAgiY z@fqC-Ps2O>s9*5oDHCgbNfV4FTXL_i5e%97lmIYa9Nsj#f_VcQ?~E}_x~xr6E>c5_fIKp z#tw$U&|};}51SbJJtqz%L;qq5wYJvB;68K;ow-nA&A8<#ErG=(3_p8F))Go%+`-BP z-j3npAV5`lb#5vJo!q0%76Z5coRSuusWpS)5C>nly?j-r|C7}nQ)28VtgNh<;NUc= zlx&V1V`4jL$qHlF;_FF6Y=?gq1;uVfcPg6cJ}66M4AAxWq8zNIKvEiw0_jn(J1N;f z_u1W?`$$|xJh+2G!3_(lf@5hcOX>1(5TwGY)WA02#FZEFasM(23LdtFZWRU-^Z)VHAJ04Wnn*o;~gOXMS=DKHLe*ZoDIW~~) zeZ~J$GvfswQfvNT_eW3NVftK_YNeb0s-B-9KWyo^@yb-KtuR<^F4Dqkju4WbL)+kw zMF9P*(;WUS0;2=UNwH&SvLznB}s$(?rZEFuDPyp~~MmLTSn4c9v zM8FuU3$bWm_y7I)yYi4)rL11H_u`54lq($%4@z-5&6*kCjD#Az za>$7FPp&s8CIJ7-`X?PNy6`eb9rg47^=zsI1JbaA6u1@N)27OSIatXJ18VwpNG;^K z+yb(3J9DgP$s|O_G}CZ`9gu>7X)1HbbcW1~|1tjyNX|2;l;*c>2$#6>&t4C#9sUXe zzmoJX=bTd%P88KWKA&^=Unpo_q6%6pC}=0uyn$xTT=BmsoIDo}uJPp|e-Z*LRUvd*}C9frr%R!zo~W~=I!MEeF_)-eEMFYF-vLnYbYaxNYKLO)GoU=}BV=l`-u4R`va`>ZiLuc^ojn;8x^z2qs6)5ffUgOUse^+__5l5r3oZM3t#Y3CMs9gd$nGF6gqV=Q7=e zDdT3`vN1=>a5%{$;BIW(a9Odd&Om_kqi3l zR7ju-0?63C+~pG9shg4BEhWsQ1|boV979u8C<*#1qVs&XzN>g{7ksl-?RX4{dp6Sh zem4VF`&e@8k-b0acCb`6&%!y*Ny_Efs>-Q2ST`*}_;Hai|F(sK=&;C@TDmLcjZ_vC z`s7^j^fFr+q=Y?Yq2k7+&L?q@H9?7Iy(+lcv6gL+^nsE;J@Gx}Od!nNFl_5^4EgcXp51 z8H3910D);O4oK5n;N1!V>VHeQwb+vwNI6R0?>Qd$X;kw}IR|-oW6bFZrjycjxYcE5 z&s7-vCX91L_?0?+^1;y?cAX8$cA6s=`X~8Z_PUf8--Lu)tH=q-ScIO{0G?@(X)x8x zu?Prl3#hkih0z7t2TiNpa3xWIG%<%i%~mbwjsuGSVikS8h~lqF(d;JSIuDeP|3=bp zw!w1rCaQS}=qA{1mk3UtW2OOOfIAZEyqZL-e+m`~>)z0m&^l`%U2zM;Sy@)a>u9IR zpN@gs82seob=)sGUw~V!nFzl)2f094LTlgFN>13!{Sm+iRSKsGgO3Q`S%c@s-n3JN zlvGzd#KvJ33Jb%ZDDGp`l@gh8Uf9REzR_-=+=Z6;9Xj+jnMxe5P2T?S`%5ZpV}gmQ zq{gdq5=+Go7`zu@nV`9}-Abn4W0BPuNUUEDVNP4i>z6MQY1d{e*UsU4mV@YgL3d6z zTQ)n5&5Ax=IZuX+)C`Cyb*)a864*3SuWO>;gN1VishX*6@bJ(o?GOil>euC#u@p`% zbux7}2Q*^puPxvaH~rAEfBjjap}EZbnwJ&A<0>@)5SFej-hf-}6{oBdde~qp^K#0H z?e?dgXPY`U?=jHLqT^E99tvJt#vC)z;N0|f*{T`8(ws#vcI$W~5-vH3RAJx3+bAbk z(qesR6i%Q~`XGhW*7NP2Fe#bE`o#vI@2 zIs-I3Eg@fjmYWNenLyO<7ExxmI&s+adBwx4N3OJzQ#7GElip+0lDj*6%h3+EecZF@r?Ags^ai2o0o0>BF;IZ#4anxPzQJ=#lL}bcJu!JeW9mgG;m$!548yM<` z!(~gmN4ySRh_CU#bRqp%r&B<4(Yh=21A%pcHEH_i5M)cvU8~NcFA&;VOTZjwwzZJ9 zzH>h&*1(ZU6`b6a2GdmS17hzr4i;2RD-rHqqylaKcT}SVd;;ZML^W?8YiG1*EBjff7s|8J*q`8Gm?KY_Cn~2yhuJ3wD&K0#9cxWM` z0Ae}aFC{ShHc<5-5FoS<^*Kn)g$7)X+7hz-1N3)|JMySgZ2J zEdpGv?!`16lVb(%Fx07qV|X!0L{2nPqORS_Oioh*GW~g(Nd7~7Ub`ceYHacJGH#C0 ztl0nOZEs4Zo7hE!cV0;0Tp8XQRM&CCE@TB3WPy}Y`+oW>21U^qXQ4>S8#v5)sZQ?< z&`g5WmFq#JVku*T_L}VdpuvC&4heT{Kp1B#R!Yk+1DCt}O&G`5L$^6weU(l4vKUrX zrQPTuyK%tvwU6lCjUsLW3a1FeIs$QQQn=)r}ST2rXRon#L$sfj!M!v({op`~@g zOxj3HMm>D2!$EaVAHDj*sQ~Qz`C%AUl{*EC#DNFrwD$Xe;n;YoR@Gd5!;<^McrsQM zKJ?ZaPMr7_Zvh|2Qn7;28;=vb{#s$_HIde=oA3PnRJ9#TdC?Mgf-G>?_Iv0qrprnI z7EVa-F>%8QTAg5QbuF(KA#sy|QT_5Bp#f1l73#B99~aYIMcRk1rGbC3Feb)Q-}?W& zW+(Oau^+rd<{kaDK9#ZsZ)&Q~mx!0bUM1!5Y+5)8N3Ij9B}tu*5AoA($$beTAXVod7$b^j4jsRFGF4Cr+b8Mz> z2WiI8<7|~5VcX)?IHE|Ka~(oLbYMde=$_`iYAMW=)I1}Heq8zd&)3IL*nCp$PF)Lj zog#d`{>H;wimL_AJ3HG=zE>k1o>ZyEe(vJue@hw4au5ttxwL?_jFyNQ8h1=08Iy>% zs-md!0AK6dfA`q4?H1l`2*{-Q2;@bvWz?1a(Tw(2gj?70Y0iPfT`{n6>L0CX&dGF^ z>%9P?9>OhTTF^4Us|HRTu&=$EHmXn0sRCm|JTVr!gHQ}p)igHeM4Pyos#&1W!ks0G zEoFE6e4+4cH*aOL3H%kMiN8Yg5>W!t*OF}8N%rh(mb7Wz1|CpK)G|15@Or|56JLh5 zMkM?7E={k0)GrWbXS>uFeA_f~b$w^O@fz4?XreYAqL>NJrgV7pPr=G@HK=cR@^c=B z6!x=T&StY*tJlblU&$A1Y?*kR1nc(ZU^d#7;({=FY*zaL|CtJ(7MANJ3u1Ywp$A2O z4mzPo^x)m)o+VaZR+4o*MbD>d>y}b4DUAvCOUN$w?jRe@Rs(zCW-eLP76QjmN7N5C zz;*xuqpxwiN8JwRE!`aL0X&--P+jsJ&l0oVSy;wK&2)6RoWo zM}4vA&zbC$aaX*kuA!8ECZtH>!hX20YHbt7Dk7X=UeK@af=~W}p~o*|(yJ5*Vm40) z3m}M)tqy5?hF0QhUX*72{|#MDBc# z2H=VgR{WgXh+@OLSSmb|9{*&DCa{-#B66zc*ns@AV`<8H#ikZWleOexx+zn24SEI5 zW1*S2buUFb?+>LDWIJIvNqqdKsM5Lpt0!Fo$3N^lOaSTtCk=87`M&-n&^8jQvD-Fa z%-Ny@bv}1m;OA(hwbKPQZ*j0k#{C;o6WGlJw8^h@O?Gungo2iTlIZCAYlMmVn^Cx% zQhq3*d5Nx;g=7@1y+Z#kur86G=kP2`>VbnQ$lz5`D&}T`j+Lf)sah>lncO~T z!h%;(YA$qwXk!7?(f+Si=X3=-M?x@=pR*YWXNl|+KVuzd)8ok)2ZXMfh8WO}DhWe(VOTlJY9hxVZay!hKUN}0B&vKFFU0uk1m+cA`LPr$F)yOtY%G@UX~ zmVb@Nbyi`hqmzeo*YxG2ukmmqZqwhWz7_v`(VOOZ`FeN3J1ST2P=#w2ECEoMwrrs@ znm8OQ_OLmy0x@8RRv_|g#_Qh@!m}a2+AAc9XpNN^`RZ=QwqltP3KrL;c-0*>Pq)TW z(w)pyuK8rF`H%SNB-_;aTtR!J23WdqQ}|3e;eV;5Ic-ClG%Zeg@sHIs2ZW>BOL2@g z=z{-OwX_z3o~??DZfw)5hO+NGbzB;kk9Y1=WZl`f#+qa>7#-L=dNsMMVqNErSq@C9 z_Aah@lDigq;+p?WQJn-neg+u`*Q%PFMp*42<9?gz3CCER;`JqmYNFl+*0SR`N>YY8 z_*fn%(i56pK!yu~$6H_)jF!~3;Vka&CmCj#@*VIGf$(|IKD5$e^UJ9|6?li3fLxf@ z6#F|fZy(esaxk@u`V9->%Is8C#sPbK-;JE(R+QHU1UAJkZ|cWl+hfbusZs(1a+;@k zXlKQfNVKn{Zu&2n1TPK*_|h+Jk7BP%t^bcqqcn$WpdsZ#<4CYoJ4yr4MN)KVY*)Yz zgVa!x1N3ZBxop;#95f^{*x9r*)cc$tiWh4e`OrpyKgMrW+6`oKaVCHbXiPO>u`k<` zxT0i?hK1|1^_jA!J!a)=ylX(d{_oVoff)tj>J8=VVLkPg;RnxdRZ2SyjRQt1^zR1G z+S%g-QT~<1j(O4b{I9}$j_vmn`GpVZYP&SC6MNTWb$h(IMvK1>Rtf{-h+_TvyfR4C zM!c+KyTXe>qU>EVoKJJFHBm{Q!M<{LEjaJs|1%6LNifhM4iY-gnGZMIj7w~pTd@Uk z@VOV|XEr`RV9Yf4cf&`B+0Th-sp<>^IUWhr+$JgBFv_K zzb8g(eD+}ct#yxRa~<|~w%6G_H~Mu7P`0<%YACwu115L7=F8KdH+Gtj9%oi>q=2*X z_NMgW^9N{*esedy4Jc#21Tn%Gc+|>007y~XvzjaYi;#$a9ANw`Yh3biUAnTr+C(kH zN=#>CB`4gXVR<;U)P86)V7KahQ2%JDA~8meLzXh z(0rm^LI&lq^oA=u}w#UO-$vud<6CRHuS_zT08K{FtiU|(I?9fS~_mJGDDY2ED1Tyrf;=| zjgh7mz8+d%ko76JKUUGbiv{5vZjBZ$>zzzfT($pCknVJXT$xmPxdjBJ^k0taRqk9# z%T*iM1?VZPUC_^#am%y`zT&a56~MsA-&^G6<8^xVcvDgm{*S|aV{5t3QCj*Q90=>4Y{NebAgS2(#pS0P9i60o@seFV@IS< zH!@oep{NxJSV_suF{KlV94YmA>!baB6~JglWA5t;7bFo2QdJ9tIZlWHO9|f{m=t0X zytJhTRFK0|W(^SaBL^6h`8e%Wkyg~V;XWeooqN4%Sm@MhrbH{Spo^^0tzqO1NNb{O ziV2OL`jeJ8S2QjO8f-Im;;&bjy>=$*Jgj8Ki*u14(ua?L3iFjA1`?g9`;&w3>o5BI z0U~Rlb*Ka3o?3^IM}+T=7@GWx^EE(`E({zWGXM7l*ltOj$ymNL^W{b2hI(1tOYm5g z#cdE#+>5IUZ{VgwIeqQ~@(cOwVpHu$i0LNjR?bvr7r^E&ChAGWbmf$My&W_lYILo@ znb6!>2ozsUO1BfV?ENx$(io)P*jh@5@%s}4Dr|_jRE1v{F3Yg$gU|f}H!Zjd}_Z2J)}awfM+whmkm0FkI%9C#h-;GL~fCuo(zix^*s;Q<{m0=-VNXJw_cU@ zt%=D882?I1ZXQeJk^nDw+;<{M63nqeA*H9YpUHtx`D<`q-7LgqT*;RF zSwE&Jr8W?zV{9e9EO~mlaX#QZWmzsi)2I(5OB#7Qn=RbH(b7#1F5ISPy?gL87Ms`Z z6ybGe^u_LtY#~H{{-c4;JwRirZsCD6e%fH5yVD?gK168Jem|gwN6$G+)Tx`xk^J%( z5avwF*N>bsEfqu-Coq3&l4S{A6h%%otoQxd(^LiGM(H9VH#stw#UB0%{F*O9OX&L! zof@mCkRoO!P5)4Mm%E9w1U@P3eu8I{4bysa$l5D|*FR=3u~-4KY4n7Uq;Y7;l`eXt zwZlsG1;Aft|5`DkHkZIWx77>nnYuZ-k%k8|^H>sas2B+2ropp~bcSsuk6WFLN!%ix zfci6=z7c>5cgpdV7>N+(+Jyd>49b3JKk&Pa^3XX3cQn*n`o~Hs3M=s`aMRV=Cg_8R zf$JT9^jDsO4p{UE5MAEp^{2)g|UXWirR36sUH3%ZF~2+;;wm+v1=vkng<4(MP8Ie(>2yex5{%h zWHo`)wRN`B6T~U9)Oj_ZZ5mN(DAYo_BbRW{L7LtxIhxhfGGG(Msk)N-3PEfYpGmho ze`X0BL-P38mWAwQ;*Up;&38I=apex^{T5+V>}6G9RKf*?y0 z6-b0j;D2wl%gp@Ks-2!Lr*=8y=6>J1Je$;@9mtVK;vmMlio_nW=s4`~Lb$4VYM*}w zWr2ka+$&+u(>mDc_6&taiD^14w+9T`&1-ZD5{HRiKZ=o%Px30{P!aun*7vaAmCt() zTmzu5CU4+&hM)x*A*nHzDjK}B)Kh#?Y7W&j+UpQ`(ecFOfjicQ0;$_0BE5+R#Xv*8 zD^+#2h#^+$H+F;RIHV`T&AQH>bb_HG|5Gmxx$A@MpA3NfCToGG*s`L>5UGRooxd@` zc5ZPXm#y%aB}>t67I5x%x^{_g1YLC+8TXyY@pg9Ri=zie-;pdFk-(x*;N+a^=s=S6 zB@c%dsenIsq1UQ`$A|RqEZI5{t-;^tf4}~!3YDq2AK)MkLX)m_WzmSX63WF>wIu~z!Ah$R11nM5(l+Yu1rj5+ zA?Gl-!mi=Zv+1~Xo?Yrvm;vB=tY$ASw zcE+!=k~UQapT4KTR(zprx_Dh*Nqz5H)_*L8q4WJ8Ero&erKpyap9fp&pDK@oUX*;> z)VkOuNtRv>46qcc^L5N6hR1L){pMTO&+20lU;MFtf|q<*$Et!-CaA#$CL{0*eL#PR#w*2=%3-UEpDEg z*twZOd)2DGgm7#cmjmLt*r>hx27Bb--$YGc&Z$F|!u@gRuzr!D+6oReMJ9?iR! z84;T-6$m;Z2QIUUs?ZBACMaKjK7C)HT^jeDmJ}utWyzSJG4OfSUT5dT^|1l`%H%Ot zf*-0dQo>ZhrmH|Ey}(}OY`ZM`Jf;AWv8nKjiJ+k z{x?u3#ccK#*cKnz381rR+wzy_@-9vE*W!07WhY9vH|fa&U9-2TLbQ);ETZdQsob=F zXY4PqQDRoR%O4E1n|i@fk$+qvv?V%?n9tFj6&4y=UB6=9^nkcmQu09x&TV_LC zPl^(ZBf5gQG^xutPccly)1-*8Tvr0A*Co8SE67FuqhQd~?2RBZlH4#s4T(aBGEw@T z${SYLu{@i1;B+|AmFGw7CdrGNCkX*{^dFi%#fwI)ZVQ})Q7a*KPU+!rjoueO5_OXM z;RL(LgSj=4=q<27?-V^+%c$p|OkqcceZ*J~P-Ii}NC9F8fCspWLuq1VVzTtQPL1rt zN4tuwlh@P1lwA9Df3jOhS7dMM79t%URMSTFs3!>r0WkF3N4`hVI(*(eefb?zJtGNT6KzUPg=2D;1v*si zp<@@sg$Gq$3O;Rfu@fWe!mHjb*Jpf{EjrhCc#iI5XlQ6toi%GxY)mI^8#xo^8jU=$ z{M5Dp1^q9m*%e5qBIs8%L|{NvRC#jR;JwPPT!iQe2KR zMBW?jq}bXO(K2 z%<4<3dXjr8tw?eO*6mKL{@&izBU53nlb_Cyg%B$VfPu$zDeF;iY$TFw>OLS<+oi*7NglgYbe3-v*>qS6U?=CC%n#r-F-Y1+bNX zfid=x4@ANMkV>kkV#8(%_F{SlZD8-)q{fQ!An{f&0sYBe9r{w(F$SK7KU~wdy1`zk zKTz|sO#E?>MvCm?FeFA)bHPH0W2t=O>_%;wx1Q+($_$bzp*0qZT`dG0;Tih_4>enU_(Xh zl@@$O$oFr6+3JfM`2qhJD0m#4BqeIK-plPJ$`yj!)X-OSCPY^T^{YXw46VH5Sfnyj_gu(zU^*K1`C%qP|+MGbmZ6H;V{cLI6q zeZldgTPx^4?4R1cebtPSl!xci*4<|7cPtdhoDuG}7wPxlHtHP?oiMs8b<^#z{>LBo z!~gUbdX7pS+`{PiztxsFQE%O^W!d%&%z%5`bY(HGDl-=2#<;J(kO5ezJ^S!oZ34m@%QeOO@$a(3E8;_?dGoYeUA0LcouY$pZ4zn>O_4z zutWM`e^>i*8SHHcp<^-RwyrQ@+gWQotWyL6XCe0q5o_6@Q>FYkGB4%H?DNJVAUtx6 zK(;`G!$x`rh(1Pd~I7&dQD=|3{<+{Tz&rAM9F#y?t=erA&xue!xqtR3<&uC$M^~>ja$r>KLJ& z1WJ;R1XFSw>6i#yD!z>@;gIhEo8u*?f=7Dd6YoP=$%ho3@FH$RSv)}5jqZnoZJ&KO z_*8rY9|4QRe&8wf(qO8v5CIndh-hN%Lx}>wD;HR35GyrNuRl;*FAbAiF!86r!S`M!DZ&gwlaP4&yNzUe8`U6iUW4!CM zGk@%f6cuX)ZX4;GnMk&@v>dq~KW|AR)mdR_B`m2S!=j3`;BgE2g=IvQFUK))1dNvk zfM8@uK=uvUoHbdG50$aP$o438K^b$@2glx?O5M_(EZx~eb#4R!DmN6vv*9pQvXE?$ zs7bia*E3Z!W3?^eW&g=LDx82D*0wJLSYJ&L7Qpip<{60Iezvt&fa_d0X&uZY9i?#B z-jB>BQ)1bOH)-m{c0gYnr_74H1S;KVt4BIKxTth}I`aHa6J4so^q|7LOHZhariyFw zA|?t_q*KwLaCptp)}`-2KXB7le6Fcf&9^oJd%SQUt!O66XWa2fKuJ$por0;)oSDiw zSkph?#@{u8 zle%TRA>;8LK+ImwvnN%3Ic_W7Pj?bBFUP7%#1_kP{H%0azP_t(O^Lu zQUOMff#?X61 z7&XIVDX#IelwpSyS)N8dJuoM2=&NF+;Y(>Y?2~vpZb^Am&>Nt%-=dbE3IZsNv5RMN zylp#`J--OUaLNP8t~(DpC9SB*OY9|+*$$ch}p%qn(Q6FvkCny1b&7$={|YN zmN}#{^0H9o+@z;zR>Dt_)Otapr3mg+5;KQdUfH}9mASqZZu%J7WH4(ne8{#fcoZ=D zL>dKoNmUAVp%ZdAC8?h7C;QA-fmiV9TF1lV@ln07jP^zZC4M#;=mn~4h*?vOFG`Yu zIB3KMO_tkSGz8e&@q&ILw}ylp2*h>*Uo;+=|9;3qn$!@F?0dm^Pri16-qPkH6#F7! z>0N=%#Wd@7foA75L*$G704q}gT51qDhm--iux*K8M=;ZNw&LO*ln6|EineZ529$WB z2_+6^5y}l_azkPEcuN2^AypPkhV}rz)ro*Cpm-fpp7F!Lfk=RCF1VH zEH@VYr2JtsMuAQvwOHYKc-{VG4n6L+Dc3R9wgyt^yMZY6A}~P0VgN-cR*vbmM!ojV zF{rgmntLonDC>~NvHjsNtarp4D-J8aik6?aZU5_$ls@2T@)SEEsfql=Cut~Hi_AQn zGd|nl;ji;2c^l*gbb~M;`9K~{m^;7g;uG z)sQyYmYdc~41>FBc{~R!eZWHWuB9=F>GC8Ttj;gwBBNjdtqK&*Mnl@)a0fiUX#Ki8 zIMmQuq*;n)8B&kssP;()VAnsaC3AhGE|`|^XCK_KBS=sFWhac3@kt9a-WpGJ1W;$w z0$!u@pyoiJ=l2PP-;VF}ud5vjaUgB=l&IV%Ys(T5=ndjV_NP}-!Pf1!0rMelQWtmU ze=%TQo)y8MZ$gpOS=>ZdWC_hOufP6*)K-iJ- z`J^>q7+2fKUoM#o%9?Nd)<9DW#$-D~Y3$mmExZVsjP$YJD$w=-hyLnW;iIo6#Bh9 z%8bq%^-ED7?qv5oxmB<-sb?hYHRLmMxS^-eeJ~Wwwg{#Wh)Y&Nqg={;pvQFcYaTBZ z#9Zf-u3P%BYQWd`?FP(mbFIGtsjCO@h$Vob=A>xV$L@DR=)wUW$<5O}v#)1-?zccs zw3L!F&RYnv9h;!ek&g$<&X%>70BC{7y|rTIx7}}^%a_1RnhzQwU{cEUx?O&(g2{4> zr+D5-&<-hk6HbzP=L?LT!5<{#Tl2HTCwimoZHr9ntqm|G9M2JZGThG{L!E)K$(3KP z!}fpIJaxS>jOo&DoC>3*izK><%?$kh^{7Tw*)_ibsDW$jl^>!YzSppu-o-ix-69q6 zf|=D>(%IeM5~XyPLR4r&H$Rv;B9b-x^jtRcB&x1Z}%HDjjXV%@@T7(8z&EO#aoYrmOW!IW;E4*2i|Uo48H_uFGaizUl& zDowzF6HywzF6X4#nQ%EFfw;9W#X9fzRZeqoQL}xdEzeora@a~#*v=y{8MFsHxUiM9 z_3Zfp}&|;u`p*@q#YnJIv)kTL6oQps+S;N`nC%(X0NLM82mwL$aZ_NYiw3eW2 zP9yhH*s@sfQ{_d~JW>jSTE9%Ff%HM+!#{C8D=X)|N#-+})IGElh^aSO_9QA4;>Ix$ zI02U->MdBoNqxa^=IolNAZ+~y&qjlQqXkzEFBL+{geH#^=|f1CejX3n2q+)4NR*C` zej*$h)l!J1%bNZHbx3w8SuLjFz53|)(O>IJ9_;jZX12AW3jNsnD@T#5myxi$ z(fX+poWTFLgkV_VYT!qXhebux>wc}BO8B|iIS4O1*mfU*@+pWqu)+r9%BOT<`siB~ zP*ToJgfj;p9D)a@or&WmelorB2V)nj&zUQ^vJ+d1R>5jfJU}4ZVq)oNyJY8r9Nuzd zJ&J`z#pBMLsuYf~!c#qVX!Kw~g%X*~QazwajYCzDS<+;mcn>%70w{eqs9iovwgFVa zS%5KhZ-oV379>FP!5zIXSSNXOX`7p;|v3Q#=r)j2rgH~TOQ6=)LPKbE&2yj_6Xt93UWF}xj zMJ?}d3%wf8*-wPN*Fep*re2|kyK;buK6aNuS0xb;E>2fD&pb<#fHyxE0fa>w! z&>Rl81@Gvd=4qI#dwNG}Q@JEG9cELLHH>VI19}VdK&@06#Q3mHd%fLO4RjBpeD zI&re@d{rALP4I>SOXN(6-_(j#zM-L-rqb4rvZUGpKZ6K{waJ2<53(!ic*y^xWHxWz zD*$F+;ihn=0eJZ!hp{u_QA%tpj|9#Gjp@+HzfIZPQlT+__yTP-3)c2FHKew!E$SBbq@IJ*>d=J)-bHL?2}{%`ppi9 zo9qTB8Q`wodfYivTXv!1TnkOg)QkX8vdr#}P$?w?WHr0`AaFGDBRFkuO43zNmujSx zb(AIE%&BBs88qOnW7rJ~NAk8UtTzr}?m!yr1@xX?{2iFVN{W+$w1H(zleM3{_(^zx z@Z^+m$x{zXRfB=<&>KiiJ6(#JDTynrz92ERt#%VAPi&sygnNzm!xGjf9rhorh2pnm z=l(inLb*ZiJrkDRFxGonCH2eGC&f0`Kb?L@ad?p~kJ`&hWzd?;A6^>Yw5twQI8HL* z<9jch6-)kOwv;e2wHK;rq3h|@0#vp3`V3tJgn1#rQHaNZxbCYWFzBOgD#P3aL`nLz zrof(gat`^FPXk}!y#6({rN7D6A{QHpyU`{*=_55u+2jU!LqXCo5i9L)yEOiw2H)ob zoT^KkKw>1dh-Fm@<-YfvocXtVN1seZriX*#6BIKCok<)9tuMUr3)XVkb|~9f_!wQ- zJDP7{R+0UYPTD-$@C(ZHYY`{Xcll z19;}8a`QvpD8<2<(|S&^?!EKbWq&A+fNSR+KHlT=S|BFJ;^->kx4{Q~iAE#>;Y z%3`y6e9^w;*#14CTUparP3srmP>WAdhQ03K1#oFtOwpkK{cUXjho^|8>x2Rs#nu6~ zD~snohmK+HY~>6xlR}fNCs5vHX6HaG?_2S7UoMTd79ga1!moh)ibX|Z!>+KD9WE=T zAPGlfKfs&}kM$48FiCKl2Ke%BJ%v1;R9)=SvOP;SFOq8(?~?@T=TI7F=oU3bqzJe_ z-+DeCImw#bt88mgUGw8~W=xE*rrH!lI(t6oC%{(mzspi-!JmV66Ex*MiHc&>j}lHc zC}_}dHLQ>lhuj9dK|hUXYsoO~03N#=d zx4W~MXvPCPUfKqAddI{#U?}T<{^qfbcU?}VpFL@- zEtBVowzv)4@0(-7ltZ0`{>|Afmkx$~52lgzSh4>Q$vnZQO}3gq2`e`ptBg}kS5G{P zQv3{0=tuB(?+NbMLxvu>s|0QZIQ01N??*Qog?F_R)YM==q^iEC z6XrKoeqEvpq$-mNAAw4AeV>FmyciS*>nVWpCa#RFtW77!N~R-~{@s_q?6sulfI?r< z!PHTee$|D1=l1No%FT*@dUa;cAFS8dANvJuyR5)gv-~xkA6}MY=#Td9$Qot<>sh8< z4t7~(m@60}~r*yPPger-mCn~nS#numC&OlrrCi69gt}xQN)B@_NHHQq#ufsmJ zkcZ)1hJiALR%@FD0vq6K{XL)*T_^p53VneT{BF68HvzZ8q+r`fW5|F^aXX;D9RN*Q zFYb|#(n>TZ7a3?&#kMwMUJ_HVb>pT}J6%R{`b6_%w{q$FkLi+(zU8t%V5r%tM7+mv z3x*)j@j)_KF{HLU?ik&i;6;j3R311s+ICN|`-u;}W^7h)QRQ5-w+B_z&w6}s4vOZ+ z=tp0J!~JtA9WKO|Mg1la{%g=nfSq+8Nc;Yb)gPulHYZZVB7rEv+=&tv?ntNxCy>L{Z+-+2PYr7M#1Q8@=rN>FM(J^RVWka zbFbku@fS7UB@1hIY5dkP?up7Z)$8ZYiO@nrTk#Ys*)}yv2IJ!Vkxq}!AbyM<(Wasn z>^COE{0B`WOP|ETE=(uka;#ToUt>p$D~Y-_z)Pa)2={KwTdT^{yQA{haNRq%d=yAd z2J*a&^odc-#+$)W>m^cuA!GX9EyaZ}EB4fFS${W8&L9HxM1p76dEJT3o$cdGdEGQe#l$Lil7lcuQeJX##NYVgDsQ&4uKNwQRA%}oZ z<4lI-SxA}JhqBV+KDhXBFVvWXO>qz|0LCP6h)z91BXSr##2(!(&$I-f=p0{4<@#*$Ul_t$#q!BSUV2G~o*nV#m&(a^d+ynmREvVC7gn}|?UTs3iJA~(Ur||PRv&-Kb{Ob6y}h|<6LX~x z8UtacM$Tivo({-DOJ2+I;u}0Gn_+z|SXX*|t`Df(;U1`Q?iBEk-TS?T*p6q30YB|` z0=3l}Qm6j2k7XerIhFT!jMupQdR9H+t zV_-4-j5oHVLxnepy)cM(^L7RXe^s@;(j!~w6x+)~e>-o6G519lNl;@B!`BzfW_ud~ zx|N=9eGnbMkIRYjzC);lazmChohtu^fPAZNa3n?|(;^`69quUwiht(DJKz-)?Ha7J z7v<{)u6yNr14N{z@|q+{?q1sn@F`J3=>-if2*LCRQs98I z5ri3?GLVxQhJSi2K0)D@U|KkT_UL!>5|vUd{FH_k++>!Pyxgg9e`b&_ESN}jwvg@2 zYve5C6yCxmY{J)sck8DPE53k5)Gl1)2Zi7tNb=ioNf})1hn6%6j%qY@Vr*yuNqhJ+NQ+JK(L!7p&qy`w9SX z?}Fqe0Eq8k7X<-q=mJd6!wCzY@)U_x)&T^HC473b!C-Qlw5;kaRI$Bil}<<OpKBs^%QY1Y&JSet=Hu*FS{cX)RorF4tR>X5S zT|_ut|HXUaq<0xGX_x&AUQ2h+v+OWY9671CwDAH%kJ=_x!?j2Y>YmM#2%N)8F!3m1 z!`8MU57Yt>yZ2_YR}`kbduM5TNz{e{?(mHJ^lI0-tjF0NoR)Kn+t*ABl}X**U~Hs! za4Aa!luIxp86&tc*z+I#z;yuPuU_i#^*84Ih8;WU-p@2)gsSTstYhM-1ADTho_VYm zL867o8syDSVwCOtrQ)|G`~s`isEx{cB>l_>s5hd8mmxW+s#CkaiCq-buXFk*Rmc5e zub@lTCs5l37k}@9t1yrx$`%jtk~XLh-24%J??Jk`Z&JP8^}$7iML7sfX@DquROF-#0m$_V6hdvB z;QeYsQRlh86Ah(Hn%F>|0K&hw4`uc!vI8a-iQO1MX#X+Vtb)s2X&cTRE7^ zeeoP6q?G!))?}A~vqZ6Jlj_kg^Gbaw_Rq^BKIF;#d+jl|1v1Idn$jpFNV{3~u*bna zqYzvq1P{+~Ne7Q_xFf7lh${6F+cm{%>v&{|?cn zmRS2(g){M_65)j63%z&*)aGt^pw3s=HJnp4O&ljI2B%9fkRcL~)m6aFxy}CWoZlSM zih%-wqt9XW9vOME0;bzpMMqNLdt9D2BsvYF@B+c_0=cDbj8#5Z{W-VwJ3a^R!J` z8>s28DRi~w-USIWBQnoHDA2EPxkP5lk+oX3-WiVh*z9YB0b=Da1rjR@Ph?36$PLYI zj(c3%@G2QN-o1q&=l4PPC+*T>K3ua&T_#L2-n|tyz~URN0o!))U1;A~q$k6v6dlEq z`oS~mQV=(?)O*l&ohP1hKNsGiH=JAP=NWnm0cEa@t)#TGZ@vuJ!f1l`^wX;*Dm zFMxc+c)a3MwN=xsZqChFi9MH5_eMmmDSsQKO^Tuhc2slFN!GQ?qii?2n)?KlaI&;9 zO9z{=?M7%zg(c9FK4qvp0+{kW&ZIbZuXnJl27xS6D~uWRsZSJa&p_>BAW-51o^qHR zH+%9^n`3eh(}lkt!6H2?!BRo?35IwKTp&X9WEc0RKb!~rv$b@Kodi}wG?=4S-5g z_7gVc&SAw~!*g|T8-KQgY0}2Ca%5L#F>1b*H%yFIc{MPH9Eb7>c7XvzeQS&^pJXiH zxG*9$KJ2-iEN%Z&r{86|&D)<-dtVxw7*gF41?H~;bku1g_bbuAlQ0nj&SoY-7JoI zUcT=W@TzV00LMRF*&)7y(J6gQ6N{p-S#L>9QX{OLyOs*6i(_m;ymQerNQuoo8`zez zz6JaTH&k9XtM4!JU9NsrLpcvKCO)<0p~4g$Ud-ows8p1swWSt99>s=FS~ZY;tXVID zsh#*3ba&v}S=VS2Mqotx*a);(6iT+ngkTASIT;UfRwjPxQ-^B zaYyw~sPZ2FTeS~3xS&MUrJan#esY;X3%gng_a^>%w|aiTo66T*nhNx0nv~BT%V6rf z{X~Y2hy^#Nw&e5>@ucT`lCS;-vn@=rrmWQXTH*R>KBxpDia^bY*OP{1No!BW$WDb9 zN}?QZcXNv63$1aezgYU8y7j_@a~CzP06B;bKA>zJ<;d`P(#vv3uVB!cPnM`Po9sEd zeo(qYL;Er-%`Z*u_htrlZ9?Jd|Mca3B{aQ`4J`r=@>1&x@Ok*4iR}}hbzT!z;uRfx z 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 literal 0 HcmV?d00001 diff --git a/pkg/usr/share/icons/hicolor/scalable/apps/spark-store.svg b/pkg/usr/share/icons/hicolor/scalable/apps/spark-store.svg deleted file mode 100644 index a1f93964..00000000 --- a/pkg/usr/share/icons/hicolor/scalable/apps/spark-store.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/pkg/usr/share/icons/hicolor/scalable/apps/spark-store_128px.svg b/pkg/usr/share/icons/hicolor/scalable/apps/spark-store_128px.svg deleted file mode 100644 index 2607b311..00000000 --- a/pkg/usr/share/icons/hicolor/scalable/apps/spark-store_128px.svg +++ /dev/null @@ -1,312 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/pkg/usr/share/icons/hicolor/scalable/apps/spark-store_16px.svg b/pkg/usr/share/icons/hicolor/scalable/apps/spark-store_16px.svg deleted file mode 100644 index 3cc08a08..00000000 --- a/pkg/usr/share/icons/hicolor/scalable/apps/spark-store_16px.svg +++ /dev/null @@ -1,312 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/pkg/usr/share/icons/hicolor/scalable/apps/spark-store_256px.svg b/pkg/usr/share/icons/hicolor/scalable/apps/spark-store_256px.svg deleted file mode 100644 index 2b5178bb..00000000 --- a/pkg/usr/share/icons/hicolor/scalable/apps/spark-store_256px.svg +++ /dev/null @@ -1,312 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/pkg/usr/share/icons/hicolor/scalable/apps/spark-store_32px.svg b/pkg/usr/share/icons/hicolor/scalable/apps/spark-store_32px.svg deleted file mode 100644 index 87bfa668..00000000 --- a/pkg/usr/share/icons/hicolor/scalable/apps/spark-store_32px.svg +++ /dev/null @@ -1,312 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/pkg/usr/share/icons/hicolor/scalable/apps/spark-store_512px.svg b/pkg/usr/share/icons/hicolor/scalable/apps/spark-store_512px.svg deleted file mode 100644 index 35f5e2ab..00000000 --- a/pkg/usr/share/icons/hicolor/scalable/apps/spark-store_512px.svg +++ /dev/null @@ -1,312 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/pkg/usr/share/icons/hicolor/scalable/apps/spark-store_64px.svg b/pkg/usr/share/icons/hicolor/scalable/apps/spark-store_64px.svg deleted file mode 100644 index d064c5bb..00000000 --- a/pkg/usr/share/icons/hicolor/scalable/apps/spark-store_64px.svg +++ /dev/null @@ -1,312 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -- Gitee From 33efff03470f2569a40e3522dacd90e05edc3d93 Mon Sep 17 00:00:00 2001 From: shenmo Date: Fri, 26 Sep 2025 10:00:54 +0000 Subject: [PATCH 096/105] fix: Can't do app upgrade in mint --- spark-update-tool/src/aptssupdater.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spark-update-tool/src/aptssupdater.cpp b/spark-update-tool/src/aptssupdater.cpp index c4bd9060..c5044b0a 100644 --- a/spark-update-tool/src/aptssupdater.cpp +++ b/spark-update-tool/src/aptssupdater.cpp @@ -78,7 +78,7 @@ QStringList aptssUpdater::getPackageSizes() foreach (const QString &packageName, updateablePackages) { // 构建新命令(包含包名参数) - QString command = QString("apt download %1 --print-uris -c /opt/durapps/spark-store/bin/apt-fast-conf/aptss-apt.conf " + QString command = QString("/usr/bin/apt download %1 --print-uris -c /opt/durapps/spark-store/bin/apt-fast-conf/aptss-apt.conf " "-o Dir::Etc::sourcelist=\"/opt/durapps/spark-store/bin/apt-fast-conf/sources.list.d/sparkstore.list\" " "-o Dir::Etc::sourceparts=\"/dev/null\"").arg(packageName); -- Gitee From 04db540f2ccdedd5b7c133f72b9bf35a1f55e2b8 Mon Sep 17 00:00:00 2001 From: shenmo Date: Sun, 28 Sep 2025 13:00:35 +0000 Subject: [PATCH 097/105] 4.8.2 --- debian/changelog | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/debian/changelog b/debian/changelog index 5df6527a..4b0b3e4d 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,9 +1,13 @@ -spark-store (4.8.2~test1) UNRELEASED; urgency=medium +spark-store (4.8.2) UNRELEASED; urgency=medium + + * 更新软件主图标 + * 软件更新器更新成功后删除软件包 + * 修复:首次安装ACE环境情况下无法正确配置ACE中aptss的问题 + * 修复:使用aptss后在/tmp下留下垃圾的问题 + + -- momen Tue, 28 Aug 2025 01:03:08 +0800 - * 添加WebEngine沙箱禁用选项,在设置页面新增复选框以允许用户在需要时关闭沙箱功能 - * 实现设置持久化,将沙箱禁用状态保存到配置文件并在应用启动时读取 - -- momen spark-store (4.8.1-1) UNRELEASED; urgency=medium -- Gitee From 5338e1409ab6d561d52a1aad675d1631d08737fc Mon Sep 17 00:00:00 2001 From: shenmo Date: Fri, 10 Oct 2025 14:06:50 +0800 Subject: [PATCH 098/105] =?UTF-8?q?=E4=BF=AE=E6=94=B9=20pass-auth.sh=20?= =?UTF-8?q?=EF=BC=8C=E5=8F=AF=E7=9B=B4=E6=8E=A5=E6=9B=BF=E6=8D=A2pkexec?= =?UTF-8?q?=E4=BD=BF=E7=94=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- tool/store-helper/pass-auth.sh | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/tool/store-helper/pass-auth.sh b/tool/store-helper/pass-auth.sh index dd668b15..cc11a537 100755 --- a/tool/store-helper/pass-auth.sh +++ b/tool/store-helper/pass-auth.sh @@ -1,6 +1,3 @@ -#!/bin/bash -# We use sudo twice to avoid ACE bug here -# https://gitee.com/amber-ce/amber-ce-bookworm/commit/43e1a1599ede474b37e41aa10c53fd8afc4d35a1 #!/bin/bash # We use sudo twice to avoid ACE bug here @@ -14,6 +11,12 @@ function zenity_prompt() { fi } +if [ "${IS_ACE_ENV}" = "" ]; then +echo "检测为非ACE环境,直接提权" +pkexec "$@" +exit $? +fi + # 检查sudo是否需要密码 if sudo -n true 2>/dev/null; then echo "sudo 无需密码,继续执行" -- Gitee From 08f593ce745812d7bae374de15486cf350b022b3 Mon Sep 17 00:00:00 2001 From: MeowVing Date: Mon, 13 Oct 2025 13:38:50 +0000 Subject: [PATCH 099/105] =?UTF-8?q?!370=20=E6=9B=B4=E6=96=B0=E8=A7=84?= =?UTF-8?q?=E8=8C=83=E5=8C=96=20Transhell=20=E6=96=87=E6=9C=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../aptss/transhell/aptss_en_US.transhell | 8 ++--- .../aptss/transhell/aptss_zh_CN.transhell | 8 ++--- .../transhell/ssinstall-local_en_US.transhell | 10 +++--- .../transhell/ssinstall-local_zh_CN.transhell | 10 +++--- .../transhell/ssinstall_en_US.transhell | 10 +++--- .../transhell/ssinstall_zh_CN.transhell | 10 +++--- .../ss-do-upgrade.sh_en_US.transhell | 32 +++++++++---------- .../ss-do-upgrade.sh_zh_CN.transhell | 28 ++++++++-------- .../ss-do-upgrade.sh_zh_TW.transhell | 32 +++++++++---------- .../ss-update-controler.sh_en_US.transhell | 14 ++++---- .../ss-update-controler.sh_zh_CN.transhell | 8 ++--- .../ss-update-controler.sh_zh_TW.transhell | 24 +++++++------- .../ss-update-notifier.sh_en_US.transhell | 8 ++--- .../ss-update-notifier.sh_zh_CN.transhell | 8 ++--- .../ss-update-notifier.sh_zh_TW.transhell | 8 ++--- 15 files changed, 109 insertions(+), 109 deletions(-) diff --git a/pkg/usr/share/aptss/transhell/aptss_en_US.transhell b/pkg/usr/share/aptss/transhell/aptss_en_US.transhell index b74b3885..7d3cb08c 100644 --- a/pkg/usr/share/aptss/transhell/aptss_en_US.transhell +++ b/pkg/usr/share/aptss/transhell/aptss_en_US.transhell @@ -1,5 +1,5 @@ #!/bin/bash -TRANSHELL_CONTENT_RUNNING_IN_NOT_ROOT_USER="INFO:Running in non-root mode! If error occurs, please try to excute me as root." -TRANSHELL_CONTENT_INFO_SOURCES_LIST_D_IS_EMPTY="INFO:sources.list.d directory is empty,will not try to sync" -TRANSHELL_CONTENT_GETTING_SERVER_CONFIG_AND_MIRROR_LIST="Getting server and mirror lists..." -TRANSHELL_CONTENT_PLEASE_USE_APTSS_INSTEAD_OF_APT="Please note: Although the error message suggests using \"apt\" (such as \"apt install --fix-broken\"), please use \"aptss\" instead of \"apt\" when troubleshooting errors (for example, change to \"aptss install --fix-broken\")." +TRANSHELL_CONTENT_RUNNING_IN_NOT_ROOT_USER="INFO: Running in non-Root mode! If error occurs, please try running the command with Root privileges." +TRANSHELL_CONTENT_INFO_SOURCES_LIST_D_IS_EMPTY="INFO: The sources.list.d directory is empty. Synchronization will not be attempted." +TRANSHELL_CONTENT_GETTING_SERVER_CONFIG_AND_MIRROR_LIST="Fetching configuration and mirror list from the server..." +TRANSHELL_CONTENT_PLEASE_USE_APTSS_INSTEAD_OF_APT="NOTE: Although the error message may suggest using apt (e.g. apt install --fix-broken) to fix the issue, please use aptss instead when troubleshooting (for example, use: aptss install --fix-broken)." \ No newline at end of file diff --git a/pkg/usr/share/aptss/transhell/aptss_zh_CN.transhell b/pkg/usr/share/aptss/transhell/aptss_zh_CN.transhell index 97d8e948..51ec95fb 100644 --- a/pkg/usr/share/aptss/transhell/aptss_zh_CN.transhell +++ b/pkg/usr/share/aptss/transhell/aptss_zh_CN.transhell @@ -1,5 +1,5 @@ #!/bin/bash -TRANSHELL_CONTENT_RUNNING_IN_NOT_ROOT_USER="信息:正在使用非root权限模式启动!若出现问题,请尝试使用root权限执行指令" -TRANSHELL_CONTENT_INFO_SOURCES_LIST_D_IS_EMPTY="信息:sources.list.d文件夹是空的,将不会尝试同步" -TRANSHELL_CONTENT_GETTING_SERVER_CONFIG_AND_MIRROR_LIST="从服务器获取配置和镜像列表..." -TRANSHELL_CONTENT_PLEASE_USE_APTSS_INSTEAD_OF_APT="注意:尽管报错信息中提示使用apt(如apt install --fix-broken),请在排查错误的时候使用aptss而不是apt(对于例子,改为使用 aptss install --fix-broken)." +TRANSHELL_CONTENT_RUNNING_IN_NOT_ROOT_USER="信息:正在使用非 Root 权限模式启动!若出现问题,请尝试使用 Root 权限执行命令。" +TRANSHELL_CONTENT_INFO_SOURCES_LIST_D_IS_EMPTY="信息:sources.list.d 文件夹是空的,将不会尝试同步。" +TRANSHELL_CONTENT_GETTING_SERVER_CONFIG_AND_MIRROR_LIST="正在从服务器获取配置和镜像列表……" +TRANSHELL_CONTENT_PLEASE_USE_APTSS_INSTEAD_OF_APT="注意:尽管报错信息提示使用 apt(如 apt install --fix-broken)修复问题,但请在排查错误时使用 aptss 进行替代(对于例子,请改为使用 aptss install --fix-broken)。" \ No newline at end of file diff --git a/pkg/usr/share/ssinstall-local/transhell/ssinstall-local_en_US.transhell b/pkg/usr/share/ssinstall-local/transhell/ssinstall-local_en_US.transhell index 7d3fbf1d..76f6cccf 100644 --- a/pkg/usr/share/ssinstall-local/transhell/ssinstall-local_en_US.transhell +++ b/pkg/usr/share/ssinstall-local/transhell/ssinstall-local_en_US.transhell @@ -1,6 +1,6 @@ #!/bin/bash -TRANSHELL_CONTENT_HASH_CHECK_FAILED="Failed in checking package hash! \nPossibly reason can be the package is broken, laggy in sync of Spark Store repository, or, there is a malware attempt to attack. \nIf you don't know what happend, please try install again after execute the command below\n sudo aptss update\n\nIf the problem still happen, please click APP Feedback button in the APP information page to feedback to us.\n\n If you are in the Audition Group,Please use ssaudit instead of ssinstall to audit APPs,for ssinstall is used for password-free install now.\nIf you want to install an app that is removed from Spark Store repository,you can also use ssaudit." -TRANSHELL_CONTENT_PLEASE_RUN_AS_ROOT="Please run ssinstall as root" -TRANSHELL_CONTENT_FILE_NOT_EXIST="File not exist" -TRANSHELL_CONTENT_WILL_NOT_DELETE_DEB="No delete after install option given, will not delete the deb" -TRANSHELL_CONTENT_DEB_IS_DELETED="--delete-after-install option is given and the installation is succeeded, delete the deb file." +TRANSHELL_CONTENT_HASH_CHECK_FAILED="An unexpected error caused the package verification to fail, and the installation process has been terminated.\n\nPossible causes include:\nNetwork or storage issues resulting in a corrupted package; The Spark Store repository has not yet completed synchronization; In extreme cases, malware may be attempting to tamper with the installation package to compromise the system.\n\nFor normal users: please run the following command in the terminal and then try installing again:\nsudo aptss update\n\nIf the problem persists, click 'App Feedback' button in the application information page to submit the issue.\n\nFor auditors: please use ssaudit instead of ssinstall for auditing, as ssinstall is now reserved for password-free installation.\nThe ssaudit command can also be used to attempt installation of applications that have been removed from the Spark Store." +TRANSHELL_CONTENT_PLEASE_RUN_AS_ROOT="Please run the ssinstall command with Root privileges." +TRANSHELL_CONTENT_FILE_NOT_EXIST="The specified file does not exist." +TRANSHELL_CONTENT_WILL_NOT_DELETE_DEB="No --delete-after-install option specified or installation failed. The Deb package will not be deleted." +TRANSHELL_CONTENT_DEB_IS_DELETED="The --delete-after-install option was used and the installation succeeded. The Deb package has been deleted." \ No newline at end of file diff --git a/pkg/usr/share/ssinstall-local/transhell/ssinstall-local_zh_CN.transhell b/pkg/usr/share/ssinstall-local/transhell/ssinstall-local_zh_CN.transhell index 680af76c..940396ea 100644 --- a/pkg/usr/share/ssinstall-local/transhell/ssinstall-local_zh_CN.transhell +++ b/pkg/usr/share/ssinstall-local/transhell/ssinstall-local_zh_CN.transhell @@ -1,6 +1,6 @@ #!/bin/bash -TRANSHELL_CONTENT_HASH_CHECK_FAILED="软件包校验失败!这不应该发生!\n可能是因为软件包已损坏,星火仓库未同步,或者最坏的情况:恶意软件尝试利用自动安装来入侵系统!\n如果你不清楚发生了什么,请执行 sudo aptss update 后再尝试安装。\n如果问题仍然存在,请在应用信息界面点击 应用反馈 来提交反馈给我们!\n\n 如果你是审核人员,请使用 ssaudit来替代ssinstall进行审核工作,因为现在ssinstall已经被用于免密安装。\n如果你正在尝试安装已经下架的星火应用,也可用ssaudit来替代ssinstall" -TRANSHELL_CONTENT_PLEASE_RUN_AS_ROOT="请使用root启动ssinstall" -TRANSHELL_CONTENT_FILE_NOT_EXIST="文件不存在" -TRANSHELL_CONTENT_WILL_NOT_DELETE_DEB="未指定安装后删除或安装出错,不删除deb包" -TRANSHELL_CONTENT_DEB_IS_DELETED="使用了--delete-after-install选项且安装未出错,删除deb包" +TRANSHELL_CONTENT_HASH_CHECK_FAILED="意外错误导致软件包校验失败,安装进程已终止。\n\n可能导致此错误的原因:\n网络或存储问题导致软件包损坏;星火应用商店软件仓库未完成同步;极端情况下,恶意软件尝试篡改安装包进行入侵。\n\n对于普通用户,请在终端执行 sudo aptss update 后再次尝试安装;如仍然遇到此错误,请在应用信息界面点击“应用反馈”提交问题。\n对于审核人员,请使用 ssaudit 替代 ssinstall 执行,现在 ssinstall 已被用于免密安装;此替代命令也可用于尝试安装已于星火应用商店下架的应用。" +TRANSHELL_CONTENT_PLEASE_RUN_AS_ROOT="请使用 Root 权限运行 ssinstall 命令。" +TRANSHELL_CONTENT_FILE_NOT_EXIST="指定的文件不存在。" +TRANSHELL_CONTENT_WILL_NOT_DELETE_DEB="未指定安装后删除软件包或安装出错,不删除 Deb 包。" +TRANSHELL_CONTENT_DEB_IS_DELETED="使用了 --delete-after-install 选项且安装未出错,删除 Deb 包。" \ No newline at end of file diff --git a/pkg/usr/share/ssinstall/transhell/ssinstall_en_US.transhell b/pkg/usr/share/ssinstall/transhell/ssinstall_en_US.transhell index 7d3fbf1d..76f6cccf 100644 --- a/pkg/usr/share/ssinstall/transhell/ssinstall_en_US.transhell +++ b/pkg/usr/share/ssinstall/transhell/ssinstall_en_US.transhell @@ -1,6 +1,6 @@ #!/bin/bash -TRANSHELL_CONTENT_HASH_CHECK_FAILED="Failed in checking package hash! \nPossibly reason can be the package is broken, laggy in sync of Spark Store repository, or, there is a malware attempt to attack. \nIf you don't know what happend, please try install again after execute the command below\n sudo aptss update\n\nIf the problem still happen, please click APP Feedback button in the APP information page to feedback to us.\n\n If you are in the Audition Group,Please use ssaudit instead of ssinstall to audit APPs,for ssinstall is used for password-free install now.\nIf you want to install an app that is removed from Spark Store repository,you can also use ssaudit." -TRANSHELL_CONTENT_PLEASE_RUN_AS_ROOT="Please run ssinstall as root" -TRANSHELL_CONTENT_FILE_NOT_EXIST="File not exist" -TRANSHELL_CONTENT_WILL_NOT_DELETE_DEB="No delete after install option given, will not delete the deb" -TRANSHELL_CONTENT_DEB_IS_DELETED="--delete-after-install option is given and the installation is succeeded, delete the deb file." +TRANSHELL_CONTENT_HASH_CHECK_FAILED="An unexpected error caused the package verification to fail, and the installation process has been terminated.\n\nPossible causes include:\nNetwork or storage issues resulting in a corrupted package; The Spark Store repository has not yet completed synchronization; In extreme cases, malware may be attempting to tamper with the installation package to compromise the system.\n\nFor normal users: please run the following command in the terminal and then try installing again:\nsudo aptss update\n\nIf the problem persists, click 'App Feedback' button in the application information page to submit the issue.\n\nFor auditors: please use ssaudit instead of ssinstall for auditing, as ssinstall is now reserved for password-free installation.\nThe ssaudit command can also be used to attempt installation of applications that have been removed from the Spark Store." +TRANSHELL_CONTENT_PLEASE_RUN_AS_ROOT="Please run the ssinstall command with Root privileges." +TRANSHELL_CONTENT_FILE_NOT_EXIST="The specified file does not exist." +TRANSHELL_CONTENT_WILL_NOT_DELETE_DEB="No --delete-after-install option specified or installation failed. The Deb package will not be deleted." +TRANSHELL_CONTENT_DEB_IS_DELETED="The --delete-after-install option was used and the installation succeeded. The Deb package has been deleted." \ No newline at end of file diff --git a/pkg/usr/share/ssinstall/transhell/ssinstall_zh_CN.transhell b/pkg/usr/share/ssinstall/transhell/ssinstall_zh_CN.transhell index 680af76c..940396ea 100644 --- a/pkg/usr/share/ssinstall/transhell/ssinstall_zh_CN.transhell +++ b/pkg/usr/share/ssinstall/transhell/ssinstall_zh_CN.transhell @@ -1,6 +1,6 @@ #!/bin/bash -TRANSHELL_CONTENT_HASH_CHECK_FAILED="软件包校验失败!这不应该发生!\n可能是因为软件包已损坏,星火仓库未同步,或者最坏的情况:恶意软件尝试利用自动安装来入侵系统!\n如果你不清楚发生了什么,请执行 sudo aptss update 后再尝试安装。\n如果问题仍然存在,请在应用信息界面点击 应用反馈 来提交反馈给我们!\n\n 如果你是审核人员,请使用 ssaudit来替代ssinstall进行审核工作,因为现在ssinstall已经被用于免密安装。\n如果你正在尝试安装已经下架的星火应用,也可用ssaudit来替代ssinstall" -TRANSHELL_CONTENT_PLEASE_RUN_AS_ROOT="请使用root启动ssinstall" -TRANSHELL_CONTENT_FILE_NOT_EXIST="文件不存在" -TRANSHELL_CONTENT_WILL_NOT_DELETE_DEB="未指定安装后删除或安装出错,不删除deb包" -TRANSHELL_CONTENT_DEB_IS_DELETED="使用了--delete-after-install选项且安装未出错,删除deb包" +TRANSHELL_CONTENT_HASH_CHECK_FAILED="意外错误导致软件包校验失败,安装进程已终止。\n\n可能导致此错误的原因:\n网络或存储问题导致软件包损坏;星火应用商店软件仓库未完成同步;极端情况下,恶意软件尝试篡改安装包进行入侵。\n\n对于普通用户,请在终端执行 sudo aptss update 后再次尝试安装;如仍然遇到此错误,请在应用信息界面点击“应用反馈”提交问题。\n对于审核人员,请使用 ssaudit 替代 ssinstall 执行,现在 ssinstall 已被用于免密安装;此替代命令也可用于尝试安装已于星火应用商店下架的应用。" +TRANSHELL_CONTENT_PLEASE_RUN_AS_ROOT="请使用 Root 权限运行 ssinstall 命令。" +TRANSHELL_CONTENT_FILE_NOT_EXIST="指定的文件不存在。" +TRANSHELL_CONTENT_WILL_NOT_DELETE_DEB="未指定安装后删除软件包或安装出错,不删除 Deb 包。" +TRANSHELL_CONTENT_DEB_IS_DELETED="使用了 --delete-after-install 选项且安装未出错,删除 Deb 包。" \ No newline at end of file diff --git a/tool/update-upgrade/transhell/ss-do-upgrade.sh_en_US.transhell b/tool/update-upgrade/transhell/ss-do-upgrade.sh_en_US.transhell index ae708e7d..b74f5449 100644 --- a/tool/update-upgrade/transhell/ss-do-upgrade.sh_en_US.transhell +++ b/tool/update-upgrade/transhell/ss-do-upgrade.sh_en_US.transhell @@ -1,18 +1,18 @@ #!/bin/bash -TRANSHELL_CONTENT_UPDATE_CHEKING_PLEASE_WAIT="Checking for update, please wait..." -TRANSHELL_CONTENT_SPARK_STORE_UPGRADE_MODEL="Spark Store APP Upgrade module" -TRANSHELL_CONTENT_CHECK_UPDATE_PROCESS_ERROR_PRESS_CONFIRM_TO_CHECK="Error occured in checking for update! Press Confirm to get the error log (Can be useful when feedback)" -TRANSHELL_CONTENT_I_ALREDY_COPIED_THE_LOG_HERE_AND_WILL_USE_IT_TO_FEEDBACK="I already copied the log in the text box and I will attach it when feeding back. You can find feedback entry in the settings which is located in the top right of the store." -TRANSHELL_CONTENT_FEEDBACK_CAN_BE_FOUND_IN_THE_SETTINGS="Feedback entry in the settings which is located in the top right of the store" -TRANSHELL_CONTENT_NO_NEED_TO_UPGRADE="All APPs are up to date." -TRANSHELL_CONTENT_CAN_NOT_UPGRADE_FOR_BEING_HOLD="(Unable to upgrade: Being marked as hold)" -TRANSHELL_CONTENT_CHOOSE_APP_TO_UPGRADE="Choose the app you want to upgrade" -TRANSHELL_CONTENT_CHOOSE="Choose" -TRANSHELL_CONTENT_APP_NAME="APP name" +TRANSHELL_CONTENT_UPDATE_CHEKING_PLEASE_WAIT="Checking for updates, please wait..." +TRANSHELL_CONTENT_SPARK_STORE_UPGRADE_MODEL="Spark Store Update Module" +TRANSHELL_CONTENT_CHECK_UPDATE_PROCESS_ERROR_PRESS_CONFIRM_TO_CHECK="An error occurred during the update check process. Click Confirm to view the error log, which can be used for issue reporting." +TRANSHELL_CONTENT_I_ALREDY_COPIED_THE_LOG_HERE_AND_WILL_USE_IT_TO_FEEDBACK="I have copied the log in this text box and will attach it when submitting feedback. The feedback option can be found in the Settings menu at the top-right corner of the main interface." +TRANSHELL_CONTENT_FEEDBACK_CAN_BE_FOUND_IN_THE_SETTINGS="The feedback option can be found in the Settings menu at the top-right corner of the main interface." +TRANSHELL_CONTENT_NO_NEED_TO_UPGRADE="All packages are already up to date." +TRANSHELL_CONTENT_CAN_NOT_UPGRADE_FOR_BEING_HOLD="Unable to update: the current package status is marked as Hold." +TRANSHELL_CONTENT_CHOOSE_APP_TO_UPGRADE="Please select the application you want to update." +TRANSHELL_CONTENT_CHOOSE="Select" +TRANSHELL_CONTENT_APP_NAME="Application Name" TRANSHELL_CONTENT_PKG_NAME="Package Name" -TRANSHELL_CONTENT_NEW_VERSION="New version" -TRANSHELL_CONTENT_UPGRADE_FROM="Upgrade from" -TRANSHELL_CONTENT_NO_APP_IS_CHOSEN="No app is chosen" -TRANSHELL_CONTENT_UPGRADING_PLEASE_WAIT="Upgrading $APP_UPGRADE , please wait..." -TRANSHELL_CONTENT_CHOSEN_APP_UPGRADE_FINISHED="The chosen app is upgraded" -TRANSHELL_CONTENT_APP_UGRADE_PROCESS_ERROR_PRESS_CONFIRM_TO_CHECK="Error occured when upgrading! Press Confirm to get the error log (Can be useful when feedback)" +TRANSHELL_CONTENT_NEW_VERSION="New Version" +TRANSHELL_CONTENT_UPGRADE_FROM="Updating from this version" +TRANSHELL_CONTENT_NO_APP_IS_CHOSEN="You have not selected any application." +TRANSHELL_CONTENT_UPGRADING_PLEASE_WAIT="Updating $APP_UPGRADE, please wait..." +TRANSHELL_CONTENT_CHOSEN_APP_UPGRADE_FINISHED="The selected application has been successfully updated." +TRANSHELL_CONTENT_APP_UGRADE_PROCESS_ERROR_PRESS_CONFIRM_TO_CHECK="An error occurred during the update process. Click Confirm to view the error log, which can be used for issue reporting." \ No newline at end of file diff --git a/tool/update-upgrade/transhell/ss-do-upgrade.sh_zh_CN.transhell b/tool/update-upgrade/transhell/ss-do-upgrade.sh_zh_CN.transhell index 58311a64..2a182374 100644 --- a/tool/update-upgrade/transhell/ss-do-upgrade.sh_zh_CN.transhell +++ b/tool/update-upgrade/transhell/ss-do-upgrade.sh_zh_CN.transhell @@ -1,18 +1,18 @@ #!/bin/bash -TRANSHELL_CONTENT_UPDATE_CHEKING_PLEASE_WAIT="正在检查更新,请稍候..." -TRANSHELL_CONTENT_SPARK_STORE_UPGRADE_MODEL="星火商店更新模块" -TRANSHELL_CONTENT_CHECK_UPDATE_PROCESS_ERROR_PRESS_CONFIRM_TO_CHECK="检查更新进程出现错误!按确定查看报错,可用于反馈" -TRANSHELL_CONTENT_I_ALREDY_COPIED_THE_LOG_HERE_AND_WILL_USE_IT_TO_FEEDBACK="我已复制了此文本框中的日志,且将会在反馈时附上。反馈渠道可以在右上角菜单的设置中找到" -TRANSHELL_CONTENT_FEEDBACK_CAN_BE_FOUND_IN_THE_SETTINGS="反馈渠道在商店右上角的设置里" -TRANSHELL_CONTENT_NO_NEED_TO_UPGRADE="没有软件需要更新" -TRANSHELL_CONTENT_CAN_NOT_UPGRADE_FOR_BEING_HOLD="(无法更新:已被标记为保留)" -TRANSHELL_CONTENT_CHOOSE_APP_TO_UPGRADE="选择你想更新的应用" +TRANSHELL_CONTENT_UPDATE_CHEKING_PLEASE_WAIT="正在检查更新,请稍候……" +TRANSHELL_CONTENT_SPARK_STORE_UPGRADE_MODEL="星火应用商店更新模块" +TRANSHELL_CONTENT_CHECK_UPDATE_PROCESS_ERROR_PRESS_CONFIRM_TO_CHECK="检查更新进程出现错误。单击“确定”查看错误日志,可用于问题反馈。" +TRANSHELL_CONTENT_I_ALREDY_COPIED_THE_LOG_HERE_AND_WILL_USE_IT_TO_FEEDBACK="我已复制且将会在反馈时附上此文本框中的日志,反馈渠道位于软件主界面右上角菜单的设置中。" +TRANSHELL_CONTENT_FEEDBACK_CAN_BE_FOUND_IN_THE_SETTINGS="反馈渠道位于软件主界面右上角菜单的设置中。" +TRANSHELL_CONTENT_NO_NEED_TO_UPGRADE="所有软件包版本已是最新。" +TRANSHELL_CONTENT_CAN_NOT_UPGRADE_FOR_BEING_HOLD="无法更新:当前软件包状态已被标记为“保留”。" +TRANSHELL_CONTENT_CHOOSE_APP_TO_UPGRADE="请选择您需要更新的软件。" TRANSHELL_CONTENT_CHOOSE="选择" TRANSHELL_CONTENT_APP_NAME="应用名" -TRANSHELL_CONTENT_PKG_NAME="包名" +TRANSHELL_CONTENT_PKG_NAME="软件包名" TRANSHELL_CONTENT_NEW_VERSION="新版本" -TRANSHELL_CONTENT_UPGRADE_FROM="从该版本更新" -TRANSHELL_CONTENT_NO_APP_IS_CHOSEN="没有选中任何软件" -TRANSHELL_CONTENT_UPGRADING_PLEASE_WAIT="正在更新 $APP_UPGRADE ,请稍候..." -TRANSHELL_CONTENT_CHOSEN_APP_UPGRADE_FINISHED="选中的软件已经更新完毕" -TRANSHELL_CONTENT_APP_UGRADE_PROCESS_ERROR_PRESS_CONFIRM_TO_CHECK="更新出现错误!按确定查看报错,可用于反馈" +TRANSHELL_CONTENT_UPGRADE_FROM="将从该版本更新" +TRANSHELL_CONTENT_NO_APP_IS_CHOSEN="您没有选中任何软件。" +TRANSHELL_CONTENT_UPGRADING_PLEASE_WAIT="正在更新 $APP_UPGRADE,请稍候……" +TRANSHELL_CONTENT_CHOSEN_APP_UPGRADE_FINISHED="选中的软件已更新完毕。" +TRANSHELL_CONTENT_APP_UGRADE_PROCESS_ERROR_PRESS_CONFIRM_TO_CHECK="更新进程出现错误。单击“确定”查看错误日志,可用于问题反馈。" \ No newline at end of file diff --git a/tool/update-upgrade/transhell/ss-do-upgrade.sh_zh_TW.transhell b/tool/update-upgrade/transhell/ss-do-upgrade.sh_zh_TW.transhell index c7f4b55e..cd110a40 100644 --- a/tool/update-upgrade/transhell/ss-do-upgrade.sh_zh_TW.transhell +++ b/tool/update-upgrade/transhell/ss-do-upgrade.sh_zh_TW.transhell @@ -1,18 +1,18 @@ #!/bin/bash -TRANSHELL_CONTENT_UPDATE_CHEKING_PLEASE_WAIT="正在檢查更新,請稍候…" -TRANSHELL_CONTENT_SPARK_STORE_UPGRADE_MODEL="星火商店更新模塊" -TRANSHELL_CONTENT_CHECK_UPDATE_PROCESS_ERROR_PRESS_CONFIRM_TO_CHECK="檢查更新行程出現錯誤! 按確定查看報錯,可用於回報" -TRANSHELL_CONTENT_I_ALREDY_COPIED_THE_LOG_HERE_AND_WILL_USE_IT_TO_FEEDBACK="我已複製了此文字方塊中的日誌,且將會在回報時附上。 迴響通路可以在右上角選單的設定中找到 " -TRANSHELL_CONTENT_FEEDBACK_CAN_BE_FOUND_IN_THE_SETTINGS="回報入口在商店右上角的設定裏" -TRANSHELL_CONTENT_NO_NEED_TO_UPGRADE="沒有軟體需要更新" -TRANSHELL_CONTENT_CAN_NOT_UPGRADE_FOR_BEING_HOLD="(无法更新:已被标记为保留)" -TRANSHELL_CONTENT_CHOOSE_APP_TO_UPGRADE="选择你想更新的应用" -TRANSHELL_CONTENT_CHOOSE="选择" -TRANSHELL_CONTENT_APP_NAME="应用名" -TRANSHELL_CONTENT_PKG_NAME="包名" +TRANSHELL_CONTENT_UPDATE_CHEKING_PLEASE_WAIT="正在檢查更新,請稍候……" +TRANSHELL_CONTENT_SPARK_STORE_UPGRADE_MODEL="星火應用商店更新模組" +TRANSHELL_CONTENT_CHECK_UPDATE_PROCESS_ERROR_PRESS_CONFIRM_TO_CHECK="檢查更新行程出現錯誤。點擊「確定」查看錯誤日誌,可用於問題回饋。" +TRANSHELL_CONTENT_I_ALREDY_COPIED_THE_LOG_HERE_AND_WILL_USE_IT_TO_FEEDBACK="我已複製且將會在回饋時附上此文字框中的日誌,回饋渠道位於軟體主介面右上角選單的設定中。" +TRANSHELL_CONTENT_FEEDBACK_CAN_BE_FOUND_IN_THE_SETTINGS="回饋渠道位於軟體主介面右上角選單的設定中。" +TRANSHELL_CONTENT_NO_NEED_TO_UPGRADE="所有軟體包版本已是最新。" +TRANSHELL_CONTENT_CAN_NOT_UPGRADE_FOR_BEING_HOLD="無法更新:當前軟體包狀態已被標記為「保留」。" +TRANSHELL_CONTENT_CHOOSE_APP_TO_UPGRADE="請選擇您需要更新的軟體。" +TRANSHELL_CONTENT_CHOOSE="選擇" +TRANSHELL_CONTENT_APP_NAME="應用名稱" +TRANSHELL_CONTENT_PKG_NAME="軟體包名稱" TRANSHELL_CONTENT_NEW_VERSION="新版本" -TRANSHELL_CONTENT_UPGRADE_FROM="从该版本更新" -TRANSHELL_CONTENT_NO_APP_IS_CHOSEN="没有选中任何軟體" -TRANSHELL_CONTENT_UPGRADING_PLEASE_WAIT="正在更新 $APP_UPGRADE ,请稍候..." -TRANSHELL_CONTENT_CHOSEN_APP_UPGRADE_FINISHED="选中的軟體已经更新完毕" -TRANSHELL_CONTENT_APP_UGRADE_PROCESS_ERROR_PRESS_CONFIRM_TO_CHECK="更新出现错误!按确定查看报错,可用于反馈" +TRANSHELL_CONTENT_UPGRADE_FROM="將從該版本更新" +TRANSHELL_CONTENT_NO_APP_IS_CHOSEN="您沒有選中任何軟體。" +TRANSHELL_CONTENT_UPGRADING_PLEASE_WAIT="正在更新 $APP_UPGRADE,請稍候……" +TRANSHELL_CONTENT_CHOSEN_APP_UPGRADE_FINISHED="選中的軟體已更新完畢。" +TRANSHELL_CONTENT_APP_UGRADE_PROCESS_ERROR_PRESS_CONFIRM_TO_CHECK="更新行程出現錯誤。點擊「確定」查看錯誤日誌,可用於問題回饋。" \ No newline at end of file diff --git a/tool/update-upgrade/transhell/ss-update-controler.sh_en_US.transhell b/tool/update-upgrade/transhell/ss-update-controler.sh_en_US.transhell index 8b16f7d8..80c8cc43 100644 --- a/tool/update-upgrade/transhell/ss-update-controler.sh_en_US.transhell +++ b/tool/update-upgrade/transhell/ss-update-controler.sh_en_US.transhell @@ -1,14 +1,14 @@ #!/bin/bash TRANSHELL_CONTENT_CLOSE="Disable" TRANSHELL_CONTENT_OPEN="Enable" -TRANSHELL_CONTENT_WELCOME_AND_CHOOSE_ONE_TO_RUN="Welcome to Spark Store APP Upgrade Settings\nPlease choose one option to run" +TRANSHELL_CONTENT_WELCOME_AND_CHOOSE_ONE_TO_RUN="Welcome to the Spark App Store update and installation settings tool. Please choose one of the following options to continue." TRANSHELL_CONTENT_OPTIONS="Options" -TRANSHELL_CONTENT_OPEN_OR_CLOSE_UPGRADE_CHECK="$text_update_open Spark Store APP upgrade check. (Will notify APP upgrade at start up if opened.)" -TRANSHELL_CONTENT_CHECK_FOR_UPDATE="Check Upgradable app list." +TRANSHELL_CONTENT_OPEN_OR_CLOSE_UPGRADE_CHECK="$text_update_open Spark Store Update Check Tool (When enabled, this tool will automatically check for updates after system startup and display a notification if updates are available)" +TRANSHELL_CONTENT_CHECK_FOR_UPDATE="View the list of upgradable packages" TRANSHELL_CONTENT_EXIT="Exit" -TRANSHELL_CONTENT_CLOSING_UPGRADE_CHECK="Please authorize to close APP upgrade check" +TRANSHELL_CONTENT_CLOSING_UPGRADE_CHECK="Please authorize to disable automatic update check." TRANSHELL_CONTENT_CLOSED="Disabled" -TRANSHELL_CONTENT_OPENING_UPGRADE_CHECK="Please authorize to open APP upgrade check" +TRANSHELL_CONTENT_OPENING_UPGRADE_CHECK="Please authorize to enable automatic update check." TRANSHELL_CONTENT_OPENED="Enabled" -TRANSHELL_CONTENT_CLOSE_CREATE_DESKTOP="Disable auto create desktop shortcut" -TRANSHELL_CONTENT_OPEN_CREATE_DESKTOP="Enable auto create desktop shortcut" +TRANSHELL_CONTENT_CLOSE_CREATE_DESKTOP="Disable automatic creation of desktop launcher" +TRANSHELL_CONTENT_OPEN_CREATE_DESKTOP="Enable automatic creation of desktop launcher" \ No newline at end of file diff --git a/tool/update-upgrade/transhell/ss-update-controler.sh_zh_CN.transhell b/tool/update-upgrade/transhell/ss-update-controler.sh_zh_CN.transhell index 50151d0c..901027be 100644 --- a/tool/update-upgrade/transhell/ss-update-controler.sh_zh_CN.transhell +++ b/tool/update-upgrade/transhell/ss-update-controler.sh_zh_CN.transhell @@ -1,14 +1,14 @@ #!/bin/bash TRANSHELL_CONTENT_CLOSE="关闭" TRANSHELL_CONTENT_OPEN="开启" -TRANSHELL_CONTENT_WELCOME_AND_CHOOSE_ONE_TO_RUN="欢迎使用星火更新和安装设置工具\n请在以下操作中选择一个进行~" +TRANSHELL_CONTENT_WELCOME_AND_CHOOSE_ONE_TO_RUN="欢迎使用星火应用商店更新与安装设置工具,请在以下选项中选择一个以继续。" TRANSHELL_CONTENT_OPTIONS="操作选项" -TRANSHELL_CONTENT_OPEN_OR_CLOSE_UPGRADE_CHECK="$text_update_open星火更新检测工具(如果开启则会在系统启动后自动检测更新。如有更新则会弹出通知)" +TRANSHELL_CONTENT_OPEN_OR_CLOSE_UPGRADE_CHECK="$text_update_open星火更新检测工具(此工具于开启状态下将在系统启动后自动检测更新,如有更新则会弹出通知)" TRANSHELL_CONTENT_CHECK_FOR_UPDATE="查看可更新软件包列表" TRANSHELL_CONTENT_EXIT="退出" -TRANSHELL_CONTENT_CLOSING_UPGRADE_CHECK="执行关闭自动更新检测,请授权" +TRANSHELL_CONTENT_CLOSING_UPGRADE_CHECK="执行“关闭自动更新检测”,请授权。" TRANSHELL_CONTENT_CLOSED="已关闭" -TRANSHELL_CONTENT_OPENING_UPGRADE_CHECK="执行启动自动更新检测,请授权" +TRANSHELL_CONTENT_OPENING_UPGRADE_CHECK="执行“开启自动更新检测”,请授权。" TRANSHELL_CONTENT_OPENED="已开启" TRANSHELL_CONTENT_CLOSE_CREATE_DESKTOP="关闭自动创建桌面启动器" TRANSHELL_CONTENT_OPEN_CREATE_DESKTOP="开启自动创建桌面启动器" diff --git a/tool/update-upgrade/transhell/ss-update-controler.sh_zh_TW.transhell b/tool/update-upgrade/transhell/ss-update-controler.sh_zh_TW.transhell index 50151d0c..c60a4d2a 100644 --- a/tool/update-upgrade/transhell/ss-update-controler.sh_zh_TW.transhell +++ b/tool/update-upgrade/transhell/ss-update-controler.sh_zh_TW.transhell @@ -1,14 +1,14 @@ #!/bin/bash -TRANSHELL_CONTENT_CLOSE="关闭" -TRANSHELL_CONTENT_OPEN="开启" -TRANSHELL_CONTENT_WELCOME_AND_CHOOSE_ONE_TO_RUN="欢迎使用星火更新和安装设置工具\n请在以下操作中选择一个进行~" -TRANSHELL_CONTENT_OPTIONS="操作选项" -TRANSHELL_CONTENT_OPEN_OR_CLOSE_UPGRADE_CHECK="$text_update_open星火更新检测工具(如果开启则会在系统启动后自动检测更新。如有更新则会弹出通知)" -TRANSHELL_CONTENT_CHECK_FOR_UPDATE="查看可更新软件包列表" +TRANSHELL_CONTENT_CLOSE="關閉" +TRANSHELL_CONTENT_OPEN="開啟" +TRANSHELL_CONTENT_WELCOME_AND_CHOOSE_ONE_TO_RUN="歡迎使用星火應用商店更新與安裝設定工具,請在以下選項中選擇一個以繼續。" +TRANSHELL_CONTENT_OPTIONS="操作選項" +TRANSHELL_CONTENT_OPEN_OR_CLOSE_UPGRADE_CHECK="$text_update_open星火更新檢測工具(此工具於開啟狀態下將在系統啟動後自動檢測更新,如有更新則會彈出通知)" +TRANSHELL_CONTENT_CHECK_FOR_UPDATE="查看可更新軟體包清單" TRANSHELL_CONTENT_EXIT="退出" -TRANSHELL_CONTENT_CLOSING_UPGRADE_CHECK="执行关闭自动更新检测,请授权" -TRANSHELL_CONTENT_CLOSED="已关闭" -TRANSHELL_CONTENT_OPENING_UPGRADE_CHECK="执行启动自动更新检测,请授权" -TRANSHELL_CONTENT_OPENED="已开启" -TRANSHELL_CONTENT_CLOSE_CREATE_DESKTOP="关闭自动创建桌面启动器" -TRANSHELL_CONTENT_OPEN_CREATE_DESKTOP="开启自动创建桌面启动器" +TRANSHELL_CONTENT_CLOSING_UPGRADE_CHECK="執行「關閉自動更新檢測」,請授權。" +TRANSHELL_CONTENT_CLOSED="已關閉" +TRANSHELL_CONTENT_OPENING_UPGRADE_CHECK="執行「開啟自動更新檢測」,請授權。" +TRANSHELL_CONTENT_OPENED="已開啟" +TRANSHELL_CONTENT_CLOSE_CREATE_DESKTOP="關閉自動建立桌面啟動器" +TRANSHELL_CONTENT_OPEN_CREATE_DESKTOP="開啟自動建立桌面啟動器" \ No newline at end of file diff --git a/tool/update-upgrade/transhell/ss-update-notifier.sh_en_US.transhell b/tool/update-upgrade/transhell/ss-update-notifier.sh_en_US.transhell index fa28962a..70a88ba5 100644 --- a/tool/update-upgrade/transhell/ss-update-notifier.sh_en_US.transhell +++ b/tool/update-upgrade/transhell/ss-update-notifier.sh_en_US.transhell @@ -1,5 +1,5 @@ #!/bin/bash -TRANSHELL_CONTENT_NETWORK_FAIL="Network fail. Stop to avoid bother dpkg" -TRANSHELL_CONTENT_UPDATE_ERROR_AND_WAIT_15_SEC="Update error! Wait for 15 seconds..." -TRANSHELL_CONTENT_SPARK_STORE_UPGRADE_NOTIFY="Spark Store Upgrade Notifier" -TRANSHELL_CONTENT_THERE_ARE_APPS_TO_UPGRADE="There are ${update_app_number} APPs available to upgrade! Please go to Spark Store to upgrade." +TRANSHELL_CONTENT_NETWORK_FAIL="The current network is abnormal. To prevent blocking the dpkg process, the update has been paused." +TRANSHELL_CONTENT_UPDATE_ERROR_AND_WAIT_15_SEC="An error occurred during the update process. It will automatically retry in 15 seconds." +TRANSHELL_CONTENT_SPARK_STORE_UPGRADE_NOTIFY="Spark Store Update Notifier" +TRANSHELL_CONTENT_THERE_ARE_APPS_TO_UPGRADE="There are ${update_app_number} packages available for update in the repository. Click to open the Spark Store menu for details." \ No newline at end of file diff --git a/tool/update-upgrade/transhell/ss-update-notifier.sh_zh_CN.transhell b/tool/update-upgrade/transhell/ss-update-notifier.sh_zh_CN.transhell index 668fa144..35c68f4d 100644 --- a/tool/update-upgrade/transhell/ss-update-notifier.sh_zh_CN.transhell +++ b/tool/update-upgrade/transhell/ss-update-notifier.sh_zh_CN.transhell @@ -1,5 +1,5 @@ #!/bin/bash -TRANSHELL_CONTENT_NETWORK_FAIL="网络错误!为防止阻塞dpkg,停止" -TRANSHELL_CONTENT_UPDATE_ERROR_AND_WAIT_15_SEC="更新出现异常状况,等待十五秒" -TRANSHELL_CONTENT_SPARK_STORE_UPGRADE_NOTIFY="星火更新提醒" -TRANSHELL_CONTENT_THERE_ARE_APPS_TO_UPGRADE="星火商店仓库中有$update_app_number个软件包可以更新啦!请到星火商店的菜单处理" +TRANSHELL_CONTENT_NETWORK_FAIL="当前网络异常,为防止阻塞 dpkg 进程,已暂停更新。" +TRANSHELL_CONTENT_UPDATE_ERROR_AND_WAIT_15_SEC="更新进程发生异常,将在 15 秒后自动重试。" +TRANSHELL_CONTENT_SPARK_STORE_UPGRADE_NOTIFY="星火应用商店更新提醒" +TRANSHELL_CONTENT_THERE_ARE_APPS_TO_UPGRADE="软件仓库中有 $update_app_number 个软件包可供更新,点击前往星火应用商店菜单查看详情。" \ No newline at end of file diff --git a/tool/update-upgrade/transhell/ss-update-notifier.sh_zh_TW.transhell b/tool/update-upgrade/transhell/ss-update-notifier.sh_zh_TW.transhell index 668fa144..071f71f9 100644 --- a/tool/update-upgrade/transhell/ss-update-notifier.sh_zh_TW.transhell +++ b/tool/update-upgrade/transhell/ss-update-notifier.sh_zh_TW.transhell @@ -1,5 +1,5 @@ #!/bin/bash -TRANSHELL_CONTENT_NETWORK_FAIL="网络错误!为防止阻塞dpkg,停止" -TRANSHELL_CONTENT_UPDATE_ERROR_AND_WAIT_15_SEC="更新出现异常状况,等待十五秒" -TRANSHELL_CONTENT_SPARK_STORE_UPGRADE_NOTIFY="星火更新提醒" -TRANSHELL_CONTENT_THERE_ARE_APPS_TO_UPGRADE="星火商店仓库中有$update_app_number个软件包可以更新啦!请到星火商店的菜单处理" +TRANSHELL_CONTENT_NETWORK_FAIL="當前網路異常,為防止阻塞 dpkg 行程,已暫停更新。" +TRANSHELL_CONTENT_UPDATE_ERROR_AND_WAIT_15_SEC="更新行程發生異常,將在 15 秒後自動重試。" +TRANSHELL_CONTENT_SPARK_STORE_UPGRADE_NOTIFY="星火應用商店更新提醒" +TRANSHELL_CONTENT_THERE_ARE_APPS_TO_UPGRADE="軟體倉庫中有 $update_app_number 個軟體包可供更新,點擊前往星火應用商店選單查看詳情。" \ No newline at end of file -- Gitee From 74a8e5c66946475e80dbd8fa34833d4e5119fb3a Mon Sep 17 00:00:00 2001 From: shenmo Date: Mon, 20 Oct 2025 20:25:11 +0800 Subject: [PATCH 100/105] =?UTF-8?q?=E5=90=8C=E6=AD=A5=20aptss=204.8.3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- debian/changelog | 3 ++- tool/aptss | 37 +++++++++++++++++++++++++++++++++---- tool/ssaudit | 42 ++++++++++++++++++++++++++++++++++++++---- tool/ssinstall | 40 +++++++++++++++++++++++++++++++++++++--- 4 files changed, 110 insertions(+), 12 deletions(-) diff --git a/debian/changelog b/debian/changelog index 4b0b3e4d..2a799e27 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,9 +1,10 @@ -spark-store (4.8.2) UNRELEASED; urgency=medium +spark-store (4.8.3) UNRELEASED; urgency=medium * 更新软件主图标 * 软件更新器更新成功后删除软件包 * 修复:首次安装ACE环境情况下无法正确配置ACE中aptss的问题 * 修复:使用aptss后在/tmp下留下垃圾的问题 + * aptss 更新,支持在APM下使用 -- momen Tue, 28 Aug 2025 01:03:08 +0800 diff --git a/tool/aptss b/tool/aptss index acee277e..2bfa0caf 100755 --- a/tool/aptss +++ b/tool/aptss @@ -2,11 +2,19 @@ SPARK_DOWNLOAD_SERVER_URL="https://d.spark-app.store/" SPARK_DOWNLOAD_SERVER_URL_NO_PROTOCOL="d.spark-app.store" + +if [[ "$IS_APM_ENV" = "" ]] ;then +UPSTREAM_CATOGARY="sparkstore" +else +UPSTREAM_CATOGARY="apm" +fi + source /opt/durapps/spark-store/bin/bashimport/transhell.amber source /opt/durapps/spark-store/bin/bashimport/log.amber load_transhell -case `arch` in +if [[ "$IS_APM_ENV" = "" ]] ;then +case $(arch) in x86_64 | i686 | i386) STORE_URL="store" STORE_LIST_URL="" @@ -24,6 +32,27 @@ case `arch` in STORE_LIST_URL="-riscv64" ;; esac +else +case $(arch) in + x86_64 | i686 | i386) + STORE_URL="amd64-apm" + STORE_LIST_URL="" + ;; + aarch64) + STORE_URL="aarch64-apm" + STORE_LIST_URL="-aarch64" + ;; + loongarch64) + STORE_URL="loong64-apm" + STORE_LIST_URL="-loong64" + ;; + riscv64) + STORE_URL="riscv64-apm" + STORE_LIST_URL="-riscv64" + ;; +esac +fi + SS_APT_FAST="/opt/durapps/spark-store/bin/apt-fast/ss-apt-fast" @@ -32,8 +61,8 @@ is_empty_dir(){ } function update_list(){ -curl --progress-bar -o /opt/durapps/spark-store/bin/apt-fast-conf/sources.list.d/sparkstore.list "${SPARK_DOWNLOAD_SERVER_URL}/sparkstore${STORE_LIST_URL}.list" -log.info "sparkstore${STORE_LIST_URL}.list update done" +curl --progress-bar -o /opt/durapps/spark-store/bin/apt-fast-conf/sources.list.d/aptss.list "${SPARK_DOWNLOAD_SERVER_URL}/${UPSTREAM_CATOGARY}${STORE_LIST_URL}.list" +log.info "${UPSTREAM_CATOGARY}${STORE_LIST_URL}.list update done" } function update_conf(){ @@ -110,7 +139,7 @@ echo update_list update_conf -/usr/bin/apt update -c /opt/durapps/spark-store/bin/apt-fast-conf/aptss-apt.conf -o Dir::Etc::sourceparts="-" -o APT::Get::List-Cleanup="0" -o Dir::Etc::sourcelist="/opt/durapps/spark-store/bin/apt-fast-conf/sources.list.d/sparkstore.list" +/usr/bin/apt update -c /opt/durapps/spark-store/bin/apt-fast-conf/aptss-apt.conf -o Dir::Etc::sourceparts="-" -o APT::Get::List-Cleanup="0" -o Dir::Etc::sourcelist="/opt/durapps/spark-store/bin/apt-fast-conf/sources.list.d/aptss.list" #只更新星火源 diff --git a/tool/ssaudit b/tool/ssaudit index ad5610ee..9654f8dd 100755 --- a/tool/ssaudit +++ b/tool/ssaudit @@ -59,14 +59,48 @@ FORCE_CREATE_DESKTOP="0" load_transhell_debug export DEBIAN_FRONTEND=noninteractive # 根据架构设置仓库URL +if [[ "$IS_APM_ENV" = "" ]] ;then case $(arch) in - x86_64) STORE_URL="store" ;; - aarch64) STORE_URL="aarch64-store" ;; - loongarch64) STORE_URL="loong64-store" ;; + x86_64 | i686 | i386) + STORE_URL="store" + STORE_LIST_URL="" + ;; + aarch64) + STORE_URL="aarch64-store" + STORE_LIST_URL="-aarch64" + ;; + loongarch64) + STORE_URL="loong64-store" + STORE_LIST_URL="-loong64" + ;; + riscv64) + STORE_URL="riscv64-store" + STORE_LIST_URL="-riscv64" + ;; esac +else +case $(arch) in + x86_64 | i686 | i386) + STORE_URL="amd64-apm" + STORE_LIST_URL="" + ;; + aarch64) + STORE_URL="aarch64-apm" + STORE_LIST_URL="-aarch64" + ;; + loongarch64) + STORE_URL="loong64-apm" + STORE_LIST_URL="-loong64" + ;; + riscv64) + STORE_URL="riscv64-apm" + STORE_LIST_URL="-riscv64" + ;; +esac +fi # 帮助函数 function show_help() { - echo "Spark Store Anstall script. 星火商店审核脚本" + echo "Spark Store Audit script. 星火商店审核脚本" echo "用法: $0 [选项] " echo "选项:" echo " -h, --help 显示帮助信息" diff --git a/tool/ssinstall b/tool/ssinstall index a1e44b6b..365902fd 100755 --- a/tool/ssinstall +++ b/tool/ssinstall @@ -59,11 +59,45 @@ FORCE_CREATE_DESKTOP="0" load_transhell_debug export DEBIAN_FRONTEND=noninteractive # 根据架构设置仓库URL +if [[ "$IS_APM_ENV" = "" ]] ;then case $(arch) in - x86_64) STORE_URL="store" ;; - aarch64) STORE_URL="aarch64-store" ;; - loongarch64) STORE_URL="loong64-store" ;; + x86_64 | i686 | i386) + STORE_URL="store" + STORE_LIST_URL="" + ;; + aarch64) + STORE_URL="aarch64-store" + STORE_LIST_URL="-aarch64" + ;; + loongarch64) + STORE_URL="loong64-store" + STORE_LIST_URL="-loong64" + ;; + riscv64) + STORE_URL="riscv64-store" + STORE_LIST_URL="-riscv64" + ;; esac +else +case $(arch) in + x86_64 | i686 | i386) + STORE_URL="amd64-apm" + STORE_LIST_URL="" + ;; + aarch64) + STORE_URL="aarch64-apm" + STORE_LIST_URL="-aarch64" + ;; + loongarch64) + STORE_URL="loong64-apm" + STORE_LIST_URL="-loong64" + ;; + riscv64) + STORE_URL="riscv64-apm" + STORE_LIST_URL="-riscv64" + ;; +esac +fi # 帮助函数 function show_help() { echo "Spark Store Install script. 星火商店安装脚本" -- Gitee From 796bc1d1c7a0fe651953d91da71c2a5c24aba87f Mon Sep 17 00:00:00 2001 From: shenmo Date: Tue, 21 Oct 2025 01:57:03 +0000 Subject: [PATCH 101/105] =?UTF-8?q?aptss=20=E6=94=AF=E6=8C=81reinstall=20?= =?UTF-8?q?=E6=8C=87=E4=BB=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: shenmo --- tool/aptss | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/tool/aptss b/tool/aptss index 2bfa0caf..77166a6f 100755 --- a/tool/aptss +++ b/tool/aptss @@ -53,6 +53,7 @@ case $(arch) in esac fi + SS_APT_FAST="/opt/durapps/spark-store/bin/apt-fast/ss-apt-fast" @@ -62,7 +63,7 @@ is_empty_dir(){ function update_list(){ curl --progress-bar -o /opt/durapps/spark-store/bin/apt-fast-conf/sources.list.d/aptss.list "${SPARK_DOWNLOAD_SERVER_URL}/${UPSTREAM_CATOGARY}${STORE_LIST_URL}.list" -log.info "${UPSTREAM_CATOGARY}${STORE_LIST_URL}.list update done" +log.info "${UPSTREAM_CATOGARY}${STORE_LIST_URL}.list update done" } function update_conf(){ @@ -113,7 +114,7 @@ fi -if [ "$1" = "install" ] || [ "$1" = "upgrade" ] || [ "$1" = "full-upgrade" ] || [ "$1" = "dist-upgrade" ]; then +if [ "$1" = "install" ] || [ "$1" = "upgrade" ] || [ "$1" = "full-upgrade" ] || [ "$1" = "reinstall" ] || [ "$1" = "dist-upgrade" ]; then -- Gitee From e49f4baa87eb8f3adba1616ce018765faeb90d9d Mon Sep 17 00:00:00 2001 From: shenmo Date: Wed, 22 Oct 2025 10:53:14 +0000 Subject: [PATCH 102/105] 4.8.3-1 --- debian/changelog | 2 +- tool/aptss | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/debian/changelog b/debian/changelog index 2a799e27..12bb1672 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,4 +1,4 @@ -spark-store (4.8.3) UNRELEASED; urgency=medium +spark-store (4.8.3-1) UNRELEASED; urgency=medium * 更新软件主图标 * 软件更新器更新成功后删除软件包 diff --git a/tool/aptss b/tool/aptss index 77166a6f..69d78c9c 100755 --- a/tool/aptss +++ b/tool/aptss @@ -36,11 +36,11 @@ else case $(arch) in x86_64 | i686 | i386) STORE_URL="amd64-apm" - STORE_LIST_URL="" + STORE_LIST_URL="-amd64" ;; aarch64) - STORE_URL="aarch64-apm" - STORE_LIST_URL="-aarch64" + STORE_URL="arm64-apm" + STORE_LIST_URL="-arm64" ;; loongarch64) STORE_URL="loong64-apm" -- Gitee From 98ce717d53ea17c86b75b5e72553f6cd0020a63e Mon Sep 17 00:00:00 2001 From: momen Date: Mon, 10 Nov 2025 15:40:46 +0800 Subject: [PATCH 103/105] =?UTF-8?q?update:=E6=9B=B4=E6=96=B0=E7=89=88?= =?UTF-8?q?=E6=9C=AC=E6=97=A5=E5=BF=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- debian/changelog | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/debian/changelog b/debian/changelog index 12bb1672..0db1daf0 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,11 @@ +spark-store (4.8.4) UNRELEASED; urgency=medium + + * 更新器添加忽略功能 + * 修复:更新器在更新完成后删除软件包时,未删除软件包的问题 + * 修复:更新器初始化窗口过大的问题 + + -- momen Tue, 28 Aug 2025 01:03:08 +0800 + spark-store (4.8.3-1) UNRELEASED; urgency=medium * 更新软件主图标 -- Gitee From 43d4fe451dd36ee88eecc71077bb2dd9baadeaae Mon Sep 17 00:00:00 2001 From: momen Date: Mon, 10 Nov 2025 15:41:10 +0800 Subject: [PATCH 104/105] =?UTF-8?q?chore:=E6=9B=B4=E6=96=B0=E7=BF=BB?= =?UTF-8?q?=E8=AF=91=E6=96=87=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- translations/spark-store_en.ts | 21 ++++++++++++++++++--- translations/spark-store_es.ts | 21 ++++++++++++++++++--- translations/spark-store_fr.ts | 21 ++++++++++++++++++--- translations/spark-store_zh_CN.ts | 21 ++++++++++++++++++--- translations/spark-store_zh_TW.ts | 21 ++++++++++++++++++--- 5 files changed, 90 insertions(+), 15 deletions(-) diff --git a/translations/spark-store_en.ts b/translations/spark-store_en.ts index f628dee1..c2c8a2c4 100644 --- a/translations/spark-store_en.ts +++ b/translations/spark-store_en.ts @@ -679,20 +679,35 @@ - + Updating, please wait... - + Spark Store - + Temporary cache was cleaned + + + Logs exported successfully to: %1 + + + + + Failed to export logs + + + + + Export Logs + + TitleBarMenu diff --git a/translations/spark-store_es.ts b/translations/spark-store_es.ts index a1c15fb1..4729e107 100644 --- a/translations/spark-store_es.ts +++ b/translations/spark-store_es.ts @@ -679,20 +679,35 @@ - + Updating, please wait... Se está actualizando, por favor Espere... - + Spark Store SPARK Store - + Temporary cache was cleaned Se ha limpiado la caché temporal + + + Logs exported successfully to: %1 + + + + + Failed to export logs + + + + + Export Logs + + TitleBarMenu diff --git a/translations/spark-store_fr.ts b/translations/spark-store_fr.ts index 31a3a963..3582692d 100644 --- a/translations/spark-store_fr.ts +++ b/translations/spark-store_fr.ts @@ -679,20 +679,35 @@ - + Updating, please wait... Mise à jour en cours, veuillez patienter... - + Spark Store Le Spark store - + Temporary cache was cleaned Cache temporaire nettoyé + + + Logs exported successfully to: %1 + + + + + Failed to export logs + + + + + Export Logs + + TitleBarMenu diff --git a/translations/spark-store_zh_CN.ts b/translations/spark-store_zh_CN.ts index dc194579..d481f772 100644 --- a/translations/spark-store_zh_CN.ts +++ b/translations/spark-store_zh_CN.ts @@ -681,20 +681,35 @@ <html><head/><body><p>我们的服务和软件免费供个人和非营利组织使用、交流和学习,但您在使用过程中必须遵守当地的法律法规,否则出现的任何问题与我们无关。</p><p>我们不从社区版本商店中获利,我们的大部分运营费用依靠社区的捐赠,我们很感激这让我们可以花更少的精力担心钱。但是,为了更好地提供持续的服务,Spark只对个人用户免费开放服务仓库,如果您或您的组织需要提供商业服务或者您的组织是营利性组织,请联系我们获取商业授权。</p><p>严禁用户或组织在使用本软件时从事任何形式的恶意行为,包括但不限于恶意攻击、滥用、破坏、批量抓取软件仓库等。恶意行为的定义由Spark社区判断,违规者将承担法律责任。Spark Community保留发布其生成的软件包的权利。</p><p>未经Spark Community明确授权,禁止任何个人或组织将Spark Community软件包用于商业目的或重新分发。该条款旨在确保开源精神,同时保护Spark社区的知识产权。除此之外,如果您使用Spark Store主程序或其部分代码,则必须遵守GPL v3的所有其他条款和要求。<span style=" font - family:宋体;" <span style=" font - family:宋体;color:#0082fa;">jifengshenmo@outlook.com</span></a>我们会尽快删除侵权内容。</p><p>如果你也想加入我们,无论你是参与开发、设计、推销还是提交作品,我们都欢迎你加入我们。<br/></span>我们的联系方法可以在<a href="https://blog.shenmo.tech/post/%E6%95%85%E9%9A%9C%E5%85%AC%E5%91%8A/"><span style=" text-decoration: underline; color:#0082fa;">找到</span></a></p></body></html> - + Updating, please wait... 正在更新,请稍候…… - + Spark Store 星火应用商店 - + Temporary cache was cleaned 缓存目录已清空 + + + Logs exported successfully to: %1 + + + + + Failed to export logs + + + + + Export Logs + + TitleBarMenu diff --git a/translations/spark-store_zh_TW.ts b/translations/spark-store_zh_TW.ts index 4fcf0717..d718c376 100644 --- a/translations/spark-store_zh_TW.ts +++ b/translations/spark-store_zh_TW.ts @@ -679,20 +679,35 @@ <html><head/><body><p>我们的服务和软件免费供个人和非营利组织使用、交流和学习,但您在使用过程中必须遵守当地的法律法规,否则出现的任何问题与我们无关。</p><p>我们不从社区版本商店中获利,我们的大部分运营费用依靠社区的捐赠,我们很感激这让我们可以花更少的精力担心钱。但是,为了更好地提供持续的服务,Spark只对个人用户免费开放服务仓库,如果您或您的组织需要提供商业服务或者您的组织是营利性组织,请联系我们获取商业授权。</p><p>严禁用户或组织在使用本软件时从事任何形式的恶意行为,包括但不限于恶意攻击、滥用、破坏、批量抓取软件仓库等。恶意行为的定义由Spark社区判断,违规者将承担法律责任。Spark Community保留发布其生成的软件包的权利。</p><p>未经Spark Community明确授权,禁止任何个人或组织将Spark Community软件包用于商业目的或重新分发。该条款旨在确保开源精神,同时保护Spark社区的知识产权。除此之外,如果您使用Spark Store主程序或其部分代码,则必须遵守GPL v3的所有其他条款和要求。<span style=" font - family:宋体;" <span style=" font - family:宋体;color:#0082fa;">jifengshenmo@outlook.com</span></a>我们会尽快删除侵权内容。</p><p>如果你也想加入我们,无论你是参与开发、设计、推销还是提交作品,我们都欢迎你加入我们。<br/></span>我们的联系方法可以在<a href="https://blog.shenmo.tech/post/%E6%95%85%E9%9A%9C%E5%85%AC%E5%91%8A/"><span style=" text-decoration: underline; color:#0082fa;">找到</span></a></p></body></html> - + Updating, please wait... 正在更新,请稍候…… - + Spark Store 星火应用商店 - + Temporary cache was cleaned 缓存目录已清空 + + + Logs exported successfully to: %1 + + + + + Failed to export logs + + + + + Export Logs + + TitleBarMenu -- Gitee From e6246b45295b17201a1d84f4b10b1a8cce6fd40a Mon Sep 17 00:00:00 2001 From: momen Date: Mon, 10 Nov 2025 15:46:13 +0800 Subject: [PATCH 105/105] =?UTF-8?q?chore:=E7=89=88=E6=9C=AC=E6=9B=B4?= =?UTF-8?q?=E6=94=B9=E4=B8=BA4.8.3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- debian/changelog | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/debian/changelog b/debian/changelog index 0db1daf0..98b87756 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,5 +1,10 @@ -spark-store (4.8.4) UNRELEASED; urgency=medium +spark-store (4.8.3) UNRELEASED; urgency=medium + * 更新软件主图标 + * 软件更新器更新成功后删除软件包 + * 修复:首次安装ACE环境情况下无法正确配置ACE中aptss的问题 + * 修复:使用aptss后在/tmp下留下垃圾的问题 + * aptss 更新,支持在APM下使用 * 更新器添加忽略功能 * 修复:更新器在更新完成后删除软件包时,未删除软件包的问题 * 修复:更新器初始化窗口过大的问题 -- Gitee