mirror of
https://gitee.com/spark-store-project/spark-store
synced 2025-12-15 13:22:04 +08:00
Compare commits
16 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 8f6e5408ae | |||
| d5783458fc | |||
| 6e05066dd9 | |||
| 58aa5a3787 | |||
| 6087c8a5c8 | |||
| ff758946be | |||
| d1cbf95447 | |||
|
|
187ce7e277 | ||
| d3e4f75254 | |||
|
|
949eb33511 | ||
|
|
3f65002dc9 | ||
|
|
cfd4c7689a | ||
|
|
367c8d857c | ||
| b41f846ea4 | |||
| 1dcd7d1c5c | |||
| 01ac388f50 |
323
README.md
323
README.md
@@ -1,9 +1,21 @@
|
||||
# 星火商店
|
||||
# 星火应用商店
|
||||
|
||||
|
||||
众所周知,国内的Linux应用比较少,wine应用难以获取,优质工具分散在民间各大论坛,无法形成合力,难以改善生态
|
||||
|
||||
生态构建需要的不是某一方的单打独斗,而是人人行动起来,汇聚星火,产生燎原之势
|
||||
|
||||
我们创建了这个应用商店,广泛收录大家需要的软件包,搜集优质小工具,主动适配wine应用,存放到储存库供大家获取
|
||||
|
||||
我们支持:deepin 20 ; ubuntu 20.04LTS ;UOS Home 20
|
||||
|
||||
希望看到这里的人也可以加入我们的队伍,开发或者投递应用都很欢迎,共同构建Linux应用生态
|
||||
|
||||
### [在这里投稿](http://upload.spark-app.store)
|
||||
|
||||
#### 介绍
|
||||
星火商店商店,由深度社区爱好者维护
|
||||
web页面部分正在开发当中,详情请见[web仓库](https://gitee.com/deepin-community-store/DCSAPP_WEB)
|
||||
|
||||
|
||||
#### 说明
|
||||
|
||||
当前服务器线路列表(项目中包含):
|
||||
@@ -14,15 +26,14 @@ http://store.jerrywang.top/
|
||||
http://dcstore.spark-app.store/
|
||||
```
|
||||
|
||||
#### 参数
|
||||
#### 调用参数(spk规则)
|
||||
|
||||
参数只有一个Url,该url应当遵循这种格式:`spk://<任意合法字符>/web分类/包名`
|
||||
|
||||
例如:
|
||||
|
||||
[spk://abcdefg/network/firefox-zh](spk://abcdefg/network/firefox-zh)
|
||||
[spk://abcdefg/games/store.spark-app.hmcl](spk://abcdefg/games/store.spark-app.hmcl)
|
||||
|
||||
[spk://higklmn/network/firefox-zh](spk://higklmn/network/firefox-zh)
|
||||
|
||||
可选的web分类:
|
||||
|
||||
@@ -41,20 +52,14 @@ http://dcstore.spark-app.store/
|
||||
| 主题美化 | themes |
|
||||
| 其他应用 | others |
|
||||
|
||||
#### 目录结构
|
||||
|
||||
安装软件过程中产生的包,图标,截图等被储存到`/tmp/deepin-community-store/`中。
|
||||
|
||||
配置文件被储存到`~/.config/deepin-community-store/`中。
|
||||
|
||||
线路文件:新版的线路文件被放置于源服务器中,可随时刷新更新源列表
|
||||
|
||||
#### 如何编译
|
||||
|
||||
Deepin V20/UOS 系统下, 安装依赖
|
||||
|
||||
```shell
|
||||
sudo apt install qt5-default libdtkcore-dev libdtkwidget-dev qtwebengine5-dev
|
||||
sudo apt install qt5-default libdtkcore-dev libdtkwidget-dev qtwebengine5-dev libnotify-dev
|
||||
```
|
||||
|
||||
```shell
|
||||
@@ -68,6 +73,294 @@ make -j
|
||||
|
||||
./build文件下的spark-store即为可执行文件
|
||||
|
||||
#### 参与贡献
|
||||
# 星火应用商店文档
|
||||
|
||||
# 目录结构
|
||||
几个目录结构
|
||||
```
|
||||
/
|
||||
/icons 图标文件夹
|
||||
/tags 首页图标
|
||||
/tras 多语言翻译
|
||||
```
|
||||
|
||||
主要的文件分析
|
||||
```js
|
||||
spark-store.pro Qt工程配置文件
|
||||
ssinstall 调用包安装器的脚本
|
||||
icons.qrc 图标资源文件
|
||||
main.cpp 入口文件
|
||||
widget.h widget.cpp widget.ui 主要窗口控件
|
||||
downloadlist.h downloadlist.cpp downloadlist.ui 单个软件的下载安装展示控件
|
||||
progressload.h progressload.cpp 网页加载显示? 得在deepin上编译运行才能搞清楚
|
||||
workerthreads.h workerthreads.cpp 应用信息加载线程
|
||||
image_show.h image_show.cpp 应用页面截图预览控件
|
||||
big_image.h big_image.cpp 大图查看控件
|
||||
```
|
||||
|
||||
# 使用的开源库及第三方工具
|
||||
* GDebi 一个 Ubuntu 软件中心的轻量级替代品 https://linux.cn/article-4982-1.html
|
||||
* libnotify 系统通知 https://developer.gnome.org/libnotify/unstable/
|
||||
|
||||
|
||||
# 源码分析
|
||||
## 应用的组成部分
|
||||
左侧应用分类菜单
|
||||
主窗口的下拉菜单
|
||||
应用列表页面
|
||||
应用详情页面
|
||||
应用首页,有几个链接跳转
|
||||
商店设置页面
|
||||
下载列表页面
|
||||
|
||||
## 应用初始化,及主控件加载
|
||||
初始化 `DApplication` 进入事件循环。
|
||||
设置关于我们弹窗 `DAboutDialog`。
|
||||
主控件 Widget 根据不同屏幕大小自适应。
|
||||
首页打开webview页面,如果传入了`spk://`参数,会打开应用详情页。
|
||||
```cpp
|
||||
// main.cpp
|
||||
QString arg1=argv[1];
|
||||
if(arg1.left(6)=="spk://"){
|
||||
w.openUrl(QUrl(argv[1]));
|
||||
}
|
||||
|
||||
// widget.cpp
|
||||
void Widget::openUrl(QUrl u)
|
||||
{
|
||||
QString app=serverUrl + "store"+u.path()+"/app.json";
|
||||
ui->webEngineView->setUrl(app); // 会触发 webEngineView 的
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
**Widget 初始化**
|
||||
```cpp
|
||||
void Widget::initConfig()
|
||||
{
|
||||
...
|
||||
// 读取服务器URL并初始化菜单项的链接
|
||||
QSettings readConfig(QDir::homePath()+"/.config/spark-store/config.ini",QSettings::IniFormat);
|
||||
if(readConfig.value("server/choose").toString()!=""){
|
||||
ui->comboBox_server->setCurrentText(readConfig.value("server/choose").toString());
|
||||
appinfoLoadThread.setServer(serverUrl=readConfig.value("server/choose").toString());
|
||||
}else {
|
||||
appinfoLoadThread.setServer(serverUrl="http://sucdn.jerrywang.top/"); // 默认URL
|
||||
}
|
||||
configCanSave=true; // 防止触发保存配置信号
|
||||
menuUrl[0]=serverUrl + "store/#/"; // 首页
|
||||
// 下面是各个应用分类页面,直接加载的webview的
|
||||
// 每个连接对应一个左侧的菜单项,在构造函数用连接到 chooseLeftMenu 槽函数
|
||||
menuUrl[1]=serverUrl + "store/#/network";
|
||||
...
|
||||
menuUrl[12]=serverUrl + "store/#/others";
|
||||
...
|
||||
ui->webfoot->hide();
|
||||
|
||||
//初始化首页
|
||||
ui->webEngineView->setUrl(menuUrl[0]);
|
||||
}
|
||||
/**
|
||||
* 菜单切换逻辑
|
||||
*
|
||||
*/
|
||||
void Widget::chooseLeftMenu(int index)
|
||||
{
|
||||
nowMenu=index;
|
||||
updateUI();
|
||||
left_list[index]->setStyleSheet("color:#FFFFFF;background-color:"+main_color.name()+";border-radius:8;border:0px");
|
||||
// index <=12 加载某个分类的应用列表的webviejw
|
||||
// index == 13 加载下载列表页面
|
||||
if(index<=12){
|
||||
if(themeIsDark){
|
||||
darkurl = 夜间模式的URL
|
||||
ui->webEngineView->setUrl(darkurl);
|
||||
}else {
|
||||
ui->webEngineView->setUrl(menuUrl[index]);
|
||||
}
|
||||
ui->stackedWidget->setCurrentIndex(0);
|
||||
}else if (index==13) {
|
||||
ui->stackedWidget->setCurrentIndex(1);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 应用下载安装卸载分析
|
||||
**应用详情页面加载**
|
||||
```cpp
|
||||
/**
|
||||
* 加载单个应用的信息
|
||||
*/
|
||||
void Widget::on_webEngineView_urlChanged(const QUrl &arg1)
|
||||
{
|
||||
//分析出服务器中的分类名称
|
||||
...
|
||||
//如果是app.json就打开详情页
|
||||
if(arg1.path().right(8)=="app.json"){
|
||||
...
|
||||
// 读取相应的应用信息
|
||||
appinfoLoadThread.requestInterruption();
|
||||
appinfoLoadThread.wait(100);
|
||||
appinfoLoadThread.setUrl(arg1);
|
||||
appinfoLoadThread.start();
|
||||
}
|
||||
}
|
||||
// 设置详情页的APP信息
|
||||
SpkAppInfoLoaderThread::requestSetAppInformation() -> Widget::sltAppinfoDetails()
|
||||
// 设置详情页的APP图标
|
||||
SpkAppInfoLoaderThread::finishedIconLoad() -> Widget::sltAppinfoIcon()
|
||||
// 设置详情页的APP截图
|
||||
SpkAppInfoLoaderThread::finishedScreenshotLoad() -> Widget::sltAppinfoScreenshot()
|
||||
|
||||
// 下载APP详情信息线程
|
||||
void SpkAppInfoLoaderThread::run()
|
||||
{
|
||||
QProcess get_json;
|
||||
get_json.start("curl -o app.json " + targetUrl.toString());
|
||||
QFile app_json("app.json");
|
||||
读取 app.json 里的信息,提取应用名、描述、图标、截图
|
||||
处理完毕后发射相应的信号
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
**应用下载**
|
||||
Widget::on_pushButton_download_clicked() 是点击下载的安装方法。
|
||||
最终使用的是 `QNetwrokAccessManager` 进行GET请求获取数据写入文件。
|
||||
```cpp
|
||||
void Widget::on_pushButton_download_clicked()
|
||||
{
|
||||
if(!isBusy){
|
||||
file = new QFile(fileName);
|
||||
...
|
||||
nowDownload+=1;
|
||||
startRequest(urList.at(nowDownload-1)); // 进行链接请求
|
||||
}
|
||||
}
|
||||
void Widget::startRequest(QUrl url)
|
||||
{
|
||||
reply = manager->get(QNetworkRequest(url));
|
||||
// 请求响应完成,关闭文件,清理下载队列
|
||||
connect(reply,SIGNAL(finished()),this,SLOT(httpFinished()));
|
||||
// 接收应用下载数据
|
||||
connect(reply,SIGNAL(readyRead()),this,SLOT(httpReadyRead()));
|
||||
// 更新应用下载进度
|
||||
connect(reply,SIGNAL(downloadProgress(qint64,qint64)),this,SLOT(updateDataReadProgress(qint64,qint64)));
|
||||
}
|
||||
```
|
||||
|
||||
使用 QSettings 来读取配置,更换服务源
|
||||
```cpp
|
||||
void Widget::on_comboBox_server_currentIndexChanged(const QString &arg1)
|
||||
{
|
||||
appinfoLoadThread.setServer(arg1); // 服务器信息更新
|
||||
if(configCanSave){
|
||||
ui->label_setting1->show();
|
||||
QSettings *setConfig=new QSettings(QDir::homePath()+"/.config/spark-store/config.ini",QSettings::IniFormat);
|
||||
setConfig->setValue("server/choose",arg1);
|
||||
}
|
||||
}
|
||||
```
|
||||
使用 `QProcess` 来调用各种小文件下载、包安装卸载的命令。
|
||||
|
||||
**应用安装**
|
||||
```cpp
|
||||
void Widget::httpFinished() // 完成下载
|
||||
{
|
||||
...清理资源
|
||||
download_list[nowDownload-1].readyInstall();
|
||||
download_list[nowDownload-1].free=true;
|
||||
if(nowDownload<allDownload){ // 如果有排队则下载下一个
|
||||
...队列的下一个下载请求
|
||||
}
|
||||
}
|
||||
void downloadlist::readyInstall()
|
||||
{
|
||||
...将安装按钮设置为允许点击
|
||||
ui->pushButton_install->setEnabled(true);
|
||||
ui->pushButton_install->show();
|
||||
ui->pushButton_2->hide();
|
||||
Widget::sendNotification(tr("Finished downloading %1, awaiting to install").arg(ui->label->text()), 5000,
|
||||
"/tmp/spark-store/icon_"+QString::number(num).toUtf8()+".png");
|
||||
}
|
||||
void downloadlist::on_pushButton_install_clicked()
|
||||
{
|
||||
//弹出菜单
|
||||
menu_install->exec(cursor().pos());
|
||||
}
|
||||
在 downloadlist 构造函数里将三种安装方式的按钮按条件放入了 menu_install 菜单里
|
||||
用户点击时,downloadlist::install() 方法
|
||||
三种安装方式为: gdebi, dpkg, deepin-deb-installer
|
||||
void downloadlist::install(int t)
|
||||
{
|
||||
QtConcurrent::run([=](){
|
||||
QProcess installer;
|
||||
installer.start("pkexec gdebi -n /tmp/spark-store/"+ui->label_filename->text().toUtf8());
|
||||
installer.start("pkexec ssinstall /tmp/spark-store/"+ui->label_filename->text().toUtf8());
|
||||
installer.start("deepin-deb-installer /tmp/spark-store/"+ui->label_filename->text().toUtf8());
|
||||
});
|
||||
}
|
||||
```
|
||||
|
||||
**应用卸载**
|
||||
```cpp
|
||||
void Widget::on_pushButton_uninstall_clicked()
|
||||
{
|
||||
QtConcurrent::run([=](){
|
||||
uninstall.start("pkexec apt purge -y "+pkgName);
|
||||
});
|
||||
}
|
||||
```
|
||||
|
||||
**仓库源更新**
|
||||
```cpp
|
||||
// 更新源列表
|
||||
void Widget::on_pushButton_updateServer_clicked()
|
||||
{
|
||||
QtConcurrent::run([=](){
|
||||
...
|
||||
QFile::remove(QDir::homePath().toUtf8()+"/.config/spark-store/server.list");
|
||||
system("curl -o "+QDir::homePath().toUtf8()+"/.config/spark-store/server.list http://dcstore.shenmo.tech/store/server.list");
|
||||
server.open(QDir::homePath().toUtf8()+"/.config/spark-store/server.list",std::ios::in);
|
||||
...
|
||||
while (getline(server,lineTmp)) {
|
||||
ui->comboBox_server->addItem(QString::fromStdString(lineTmp));
|
||||
}
|
||||
});
|
||||
}
|
||||
// 更新星火商店apt源
|
||||
void Widget::on_pushButton_updateApt_clicked()
|
||||
{
|
||||
QtConcurrent::run([=](){
|
||||
读取 comboBox_server 的内容,写入 /tmp/spark-store/sparkstore.list 文件
|
||||
创建bash脚本,内容为将 sparkstore.list 移动到 /etc/apt/sources.list.d/ 目录下
|
||||
使用QProcess 执行命令 pkexec update.sh
|
||||
}):
|
||||
}
|
||||
```
|
||||
|
||||
## 发送系统通知
|
||||
```cpp
|
||||
#include <libnotify/notify.h>
|
||||
|
||||
static NotifyNotification *_notify = nullptr; // 初始化
|
||||
notify_init(tr("Spark\\ Store").toLocal8Bit()); // 构造函数初始化
|
||||
notify_uninit(); // 析构函数调用
|
||||
|
||||
void Widget::sendNotification(const QString &message, const int msTimeout, const QString &icon)
|
||||
{
|
||||
if(_notify == nullptr)
|
||||
{
|
||||
_notify = notify_notification_new(tr("Spark\\ Store").toLocal8Bit(), message.toLocal8Bit(), icon.toLocal8Bit());
|
||||
notify_notification_set_timeout(_notify, msTimeout);
|
||||
}
|
||||
else
|
||||
notify_notification_update(_notify, tr("Spark\\ Store").toLocal8Bit(), message.toLocal8Bit(), icon.toLocal8Bit());
|
||||
|
||||
notify_notification_show(_notify, nullptr);
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
1. Fork 本仓库
|
||||
|
||||
@@ -18,7 +18,6 @@ image_show::image_show(QWidget *parent) : QWidget(parent)
|
||||
|
||||
void image_show::setImage(QPixmap image)
|
||||
{
|
||||
|
||||
QImage screen0;
|
||||
screen0=image.toImage();
|
||||
// QPainter painter(&screen0);
|
||||
|
||||
24
main.cpp
24
main.cpp
@@ -3,21 +3,32 @@
|
||||
#include <QDesktopWidget>
|
||||
#include <widget.h>
|
||||
#include <QTranslator>
|
||||
#include <DAboutDialog>
|
||||
DWIDGET_USE_NAMESPACE
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
DApplication::loadDXcbPlugin(); //让bar处在标题栏中
|
||||
DApplication a(argc, argv);
|
||||
DAboutDialog dialog;
|
||||
//DAboutDialog dialog;
|
||||
a.setAttribute(Qt::AA_UseHighDpiPixmaps);
|
||||
a.loadTranslator();//载入翻译
|
||||
a.setAboutDialog(&dialog);
|
||||
|
||||
a.setOrganizationName("spark-union");
|
||||
a.setApplicationVersion(DApplication::buildVersion("2.0.2.4"));
|
||||
a.setApplicationAcknowledgementPage("https://gitee.com/deepin-community-store/spark-store");
|
||||
a.setProductIcon(QIcon::fromTheme("spark-store")); //设置Logo
|
||||
|
||||
a.setProductName(QLabel::tr("Spark Store"));
|
||||
a.setApplicationDescription(QObject::tr("<span style=' font-size:10pt;font-weight:60;'>An appstore powered by deepin community</span><br/>""<a href='https://www.spark-app.store/'>https://www.spark-app.store</a><br/>""<span style=' font-size:12pt;'>Spark developers</span><br/>We publish this program under GPL V3"));
|
||||
a.setApplicationName("Spark应用商店"); //只有在这儿修改窗口标题才有效
|
||||
Widget w;
|
||||
QDesktopWidget *s=DApplication::desktop();
|
||||
/*
|
||||
a.setAboutDialog(&dialog);
|
||||
dialog.setLicense(QObject::tr("We publish this program under GPL V3"));
|
||||
dialog.setVersion(DApplication::buildVersion("Version 2.0+2"));
|
||||
dialog.setVersion(DApplication::buildVersion("Version 2.0.2.3"));
|
||||
dialog.setAcknowledgementVisible(true);
|
||||
dialog.setAcknowledgementLink(QObject::tr("https://gitee.com/deepin-community-store/spark-store"));
|
||||
a.setApplicationAcknowledgementPage(QObject::tr("https://gitee.com/deepin-community-store/spark-store"));
|
||||
//a.setApplicationAcknowledgementPage(QObject::tr("https://gitee.com/deepin-community-store/spark-store"));
|
||||
dialog.setProductIcon(QIcon::fromTheme("spark-store")); //设置Logo
|
||||
dialog.setProductName(QLabel::tr("Spark Store"));
|
||||
//dialog.setDescription(QLabel::tr("An appstore powered by deepin community\n We born for change"));
|
||||
@@ -34,7 +45,8 @@ int main(int argc, char *argv[])
|
||||
|
||||
Widget w;
|
||||
QDesktopWidget *s=DApplication::desktop();
|
||||
int d_w=s->width();
|
||||
*/
|
||||
int d_w=s->width();
|
||||
int d_h=s->height();
|
||||
if(d_w<=1366){
|
||||
w.setMinimumWidth(925);
|
||||
|
||||
@@ -9,9 +9,10 @@ QT += core gui network concurrent webenginewidgets
|
||||
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
|
||||
TRANSLATIONS = ./trans/spark-store_en.ts \
|
||||
./trans/spark-store_zh_CN.ts
|
||||
./trans/spark-store_fr.ts\
|
||||
|
||||
CONFIG += link_pkgconfig
|
||||
PKGCONFIG += dtkwidget
|
||||
PKGCONFIG += dtkwidget glib-2.0 gdk-pixbuf-2.0 libnotify
|
||||
|
||||
TARGET = spark-store
|
||||
TEMPLATE = app
|
||||
@@ -33,14 +34,16 @@ SOURCES += main.cpp\
|
||||
downloadlist.cpp \
|
||||
image_show.cpp \
|
||||
big_image.cpp \
|
||||
progressload.cpp
|
||||
progressload.cpp \
|
||||
workerthreads.cpp
|
||||
|
||||
HEADERS += \
|
||||
widget.h \
|
||||
downloadlist.h \
|
||||
image_show.h \
|
||||
big_image.h \
|
||||
progressload.h
|
||||
progressload.h \
|
||||
workerthreads.h
|
||||
|
||||
|
||||
|
||||
|
||||
BIN
trans/spark-store_fr.qm
Normal file
BIN
trans/spark-store_fr.qm
Normal file
Binary file not shown.
304
widget.cpp
304
widget.cpp
@@ -1,3 +1,4 @@
|
||||
#include <libnotify/notify.h>
|
||||
#include "widget.h"
|
||||
#include "ui_widget.h"
|
||||
#include <QDebug>
|
||||
@@ -57,6 +58,13 @@ Widget::Widget(DBlurEffectWidget *parent) :
|
||||
connect(ui->menu_download,&DPushButton::clicked,[=](){Widget::chooseLeftMenu(13);});
|
||||
// connect((ui->titlebar))
|
||||
|
||||
connect(&appinfoLoadThread, SIGNAL(requestResetUi()), this, SLOT(sltAppinfoResetUi()), Qt::ConnectionType::BlockingQueuedConnection);
|
||||
connect(&appinfoLoadThread, &SpkAppInfoLoaderThread::requestSetTags, this, &Widget::sltAppinfoTags, Qt::ConnectionType::BlockingQueuedConnection);
|
||||
connect(&appinfoLoadThread, &SpkAppInfoLoaderThread::requestSetAppInformation, this, &Widget::sltAppinfoDetails, Qt::ConnectionType::BlockingQueuedConnection);
|
||||
connect(&appinfoLoadThread, &SpkAppInfoLoaderThread::finishedIconLoad, this, &Widget::sltAppinfoIcon, Qt::ConnectionType::BlockingQueuedConnection);
|
||||
connect(&appinfoLoadThread, &SpkAppInfoLoaderThread::finishedScreenshotLoad, this, &Widget::sltAppinfoScreenshot, Qt::ConnectionType::BlockingQueuedConnection);
|
||||
connect(&appinfoLoadThread, &SpkAppInfoLoaderThread::finishAllLoading, this, &Widget::sltAppinfoFinish, Qt::ConnectionType::BlockingQueuedConnection);
|
||||
|
||||
// 搜索事件
|
||||
connect(searchEdit,&DSearchEdit::editingFinished,this,[=](){
|
||||
QString searchtext=searchEdit->text();
|
||||
@@ -103,11 +111,13 @@ Widget::Widget(DBlurEffectWidget *parent) :
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
notify_init(tr("Spark\\ Store").toLocal8Bit());
|
||||
}
|
||||
|
||||
Widget::~Widget()
|
||||
{
|
||||
notify_uninit();
|
||||
|
||||
delete ui;
|
||||
qDebug()<<"exit";
|
||||
DApplication::quit();
|
||||
@@ -126,6 +136,9 @@ void Widget::initUI()
|
||||
ui->icon->setPixmap(QIcon::fromTheme("spark-store").pixmap(36,36));
|
||||
ui->titlebar->setFixedHeight(50);
|
||||
|
||||
label_screen << ui->screen_0 << ui->screen_1 << ui->screen_2 << ui->screen_3 << ui->screen_4;
|
||||
|
||||
|
||||
// 初始化分界线
|
||||
QGraphicsOpacityEffect *opacityEffect_1=new QGraphicsOpacityEffect;
|
||||
opacityEffect_1->setOpacity(0.1);
|
||||
@@ -201,9 +214,9 @@ void Widget::initConfig()
|
||||
QSettings readConfig(QDir::homePath()+"/.config/spark-store/config.ini",QSettings::IniFormat);
|
||||
if(readConfig.value("server/choose").toString()!=""){
|
||||
ui->comboBox_server->setCurrentText(readConfig.value("server/choose").toString());
|
||||
serverUrl=readConfig.value("server/choose").toString();
|
||||
appinfoLoadThread.setServer(serverUrl=readConfig.value("server/choose").toString());
|
||||
}else {
|
||||
serverUrl="http://sucdn.jerrywang.top/"; // 默认URL
|
||||
appinfoLoadThread.setServer(serverUrl="http://sucdn.jerrywang.top/"); // 默认URL
|
||||
}
|
||||
configCanSave=true; // 防止触发保存配置信号
|
||||
menuUrl[0]=serverUrl + "store/#/";
|
||||
@@ -223,13 +236,13 @@ void Widget::initConfig()
|
||||
|
||||
|
||||
//web控件初始化
|
||||
// ui->webView->page()->setLinkDelegationPolicy(QWebPage::DelegateAllLinks); //用来激活接受linkClicked信号
|
||||
// ui->webView->page()->settings()->setAttribute(QWebSettings::JavascriptEnabled,true);
|
||||
// ui->webView->page()->setLinkDelegationPolicy(QWebPage::DelegateAllLinks); //用来激活接受linkClicked信号
|
||||
// ui->webView->page()->settings()->setAttribute(QWebSettings::JavascriptEnabled,true);
|
||||
ui->webfoot->hide();
|
||||
|
||||
//初始化首页
|
||||
ui->webEngineView->setUrl(menuUrl[0]);
|
||||
// ui->webEngineView->setUrl(menuUrl[1]);
|
||||
// ui->webEngineView->setUrl(menuUrl[1]);
|
||||
|
||||
//给下载列表赋值到数组,方便调用
|
||||
for (int i =0; i<LIST_MAX;i++){
|
||||
@@ -261,7 +274,7 @@ void Widget::setTheme(bool isDark,QColor color)
|
||||
ui->btn_openDir->setStyleSheet("color:#8B91A1;background-color:#2E2F30;border:0px");
|
||||
ui->webfoot->setStyleSheet("background-color:#252525");
|
||||
ui->label->setStyleSheet("background-color:#252525");
|
||||
// ui->scrollArea->setStyleSheet("background-color:#252525");
|
||||
// ui->scrollArea->setStyleSheet("background-color:#252525");
|
||||
ui->label_show->setStyleSheet("background-color:#252525");
|
||||
ui->pushButton_return->setIcon(QIcon(":/icons/icons/category_active_dark.svg"));
|
||||
ui->pushButton_refresh->setIcon(QIcon(":/icons/icons/refresh-page-dark.svg"));
|
||||
@@ -272,7 +285,7 @@ void Widget::setTheme(bool isDark,QColor color)
|
||||
ui->webfoot->setStyleSheet("background-color:#FFFFFF");
|
||||
ui->btn_openDir->setStyleSheet("color:#505050;background-color:#FBFBFB;border:0px");
|
||||
ui->label->setStyleSheet("background-color:#FFFFFF");
|
||||
// ui->scrollArea->setStyleSheet("background-color:#F8F8F8");
|
||||
// ui->scrollArea->setStyleSheet("background-color:#F8F8F8");
|
||||
ui->label_show->setStyleSheet("background-color:#F8F8F8");
|
||||
ui->pushButton_return->setIcon(QIcon(":/icons/icons/category_active.svg"));
|
||||
ui->pushButton_refresh->setIcon(QIcon(":/icons/icons/refresh-page.svg"));
|
||||
@@ -288,23 +301,35 @@ void Widget::setTheme(bool isDark,QColor color)
|
||||
|
||||
DTitlebar* Widget::getTitlebar()
|
||||
{
|
||||
return ui->titlebar;
|
||||
return ui->titlebar;
|
||||
}
|
||||
|
||||
static NotifyNotification *_notify = nullptr;
|
||||
|
||||
void Widget::sendNotification(const QString &message, const int msTimeout, const QString &icon)
|
||||
{
|
||||
system((QString("notify-send --icon=%1 --expire-time=%2 --app-name=").arg(icon).arg(msTimeout) +
|
||||
tr("Spark\\ Store") +
|
||||
" '" + message + "'"
|
||||
).toUtf8());
|
||||
if(_notify == nullptr)
|
||||
{
|
||||
_notify = notify_notification_new(tr("Spark\\ Store").toLocal8Bit(), message.toLocal8Bit(), icon.toLocal8Bit());
|
||||
notify_notification_set_timeout(_notify, msTimeout);
|
||||
}
|
||||
else
|
||||
notify_notification_update(_notify, tr("Spark\\ Store").toLocal8Bit(), message.toLocal8Bit(), icon.toLocal8Bit());
|
||||
|
||||
notify_notification_show(_notify, nullptr);
|
||||
}
|
||||
|
||||
void Widget::sendNotification(const char *message, const int msTimeout, const QString &icon)
|
||||
{
|
||||
system((QString("notify-send --icon=%1 --expire-time=%2 --app-name=").arg(icon).arg(msTimeout) +
|
||||
tr("Spark\\ Store") +
|
||||
" '" + message + "'"
|
||||
).toUtf8());
|
||||
if(_notify == nullptr)
|
||||
{
|
||||
_notify = notify_notification_new(tr("Spark\\ Store").toLocal8Bit(), message, icon.toLocal8Bit());
|
||||
notify_notification_set_timeout(_notify, msTimeout);
|
||||
}
|
||||
else
|
||||
notify_notification_update(_notify, tr("Spark\\ Store").toLocal8Bit(), message, icon.toLocal8Bit());
|
||||
|
||||
notify_notification_show(_notify, nullptr);
|
||||
}
|
||||
|
||||
void Widget::updateUI()
|
||||
@@ -477,7 +502,7 @@ int Widget::loadappinfo(QUrl arg1)
|
||||
get_json.waitForFinished();
|
||||
if(get_json.exitCode())
|
||||
{
|
||||
sendNotification(tr("Failed to download app info. Please check internet connection."));
|
||||
sendNotification(tr("Failed to download app info. Please check internet connection."));
|
||||
}
|
||||
|
||||
QFile app_json("app.json");
|
||||
@@ -560,25 +585,21 @@ int Widget::loadappinfo(QUrl arg1)
|
||||
get_json.start("curl -o icon.png "+urladdress+"icon.png");
|
||||
get_json.waitForFinished();
|
||||
if(!get_json.exitCode()) {
|
||||
QPixmap appicon(QString::fromUtf8(TMP_PATH)+"/icon.png");
|
||||
ui->label_appicon->setPixmap(appicon);
|
||||
ui->pushButton_download->setEnabled(true);
|
||||
ui->pushButton->setEnabled(true);
|
||||
ui->pushButton_translate->setEnabled(true);
|
||||
ui->pushButton_website->setEnabled(true);
|
||||
QPixmap appicon(QString::fromUtf8(TMP_PATH)+"/icon.png");
|
||||
ui->label_appicon->setPixmap(appicon);
|
||||
ui->pushButton_download->setEnabled(true);
|
||||
ui->pushButton->setEnabled(true);
|
||||
ui->pushButton_translate->setEnabled(true);
|
||||
ui->pushButton_website->setEnabled(true);
|
||||
}
|
||||
else
|
||||
sendNotification(tr("Failed to load application icon."));
|
||||
sendNotification(tr("Failed to load application icon."));
|
||||
|
||||
|
||||
// 截图展示加载
|
||||
image_show *label_screen[5];
|
||||
label_screen[0]=ui->screen_0;
|
||||
label_screen[1]=ui->screen_1;
|
||||
label_screen[2]=ui->screen_2;
|
||||
label_screen[3]=ui->screen_3;
|
||||
label_screen[4]=ui->screen_4;
|
||||
for (int i=0;i<5;i++) {
|
||||
QList<image_show*> label_screen;
|
||||
label_screen << ui->screen_0 << ui->screen_1 << ui->screen_2 << ui->screen_3 << ui->screen_4;
|
||||
for (int i = 0; i < 5; i++) {
|
||||
QString cmd = "curl -o screen_"+QString::number(i+1)+".png "+urladdress+"screen_"+QString::number(i+1)+".png";
|
||||
get_json.terminate();
|
||||
get_json.start(cmd);
|
||||
@@ -587,6 +608,7 @@ int Widget::loadappinfo(QUrl arg1)
|
||||
if(s){
|
||||
label_screen[i]->setImage(screen[i]);
|
||||
label_screen[i]->show();
|
||||
/*
|
||||
switch(i){ // 故意为之,为了清除多余截图
|
||||
case 0:
|
||||
label_screen[1]->hide();
|
||||
@@ -596,7 +618,8 @@ int Widget::loadappinfo(QUrl arg1)
|
||||
label_screen[3]->hide();
|
||||
case 3:
|
||||
label_screen[4]->hide();
|
||||
}
|
||||
|
||||
}*/
|
||||
}else{
|
||||
QFile::remove("screen_"+QString::number(i+1)+".png");
|
||||
break;
|
||||
@@ -691,6 +714,111 @@ void Widget::updateDataReadProgress(qint64 bytesRead, qint64 totalBytes)
|
||||
}
|
||||
}
|
||||
|
||||
void Widget::sltAppinfoResetUi()
|
||||
{
|
||||
// 先隐藏详情页负责显示截图的label
|
||||
ui->screen_0->hide();
|
||||
ui->screen_1->hide();
|
||||
ui->screen_2->hide();
|
||||
ui->screen_3->hide();
|
||||
ui->screen_4->hide();
|
||||
ui->label_appicon->clear();
|
||||
ui->tag_community->hide();
|
||||
ui->tag_ubuntu->hide();
|
||||
ui->tag_deepin->hide();
|
||||
ui->tag_uos->hide();
|
||||
ui->tag_dtk5->hide();
|
||||
ui->tag_dwine2->hide();
|
||||
ui->tag_dwine5->hide();
|
||||
ui->tag_a2d->hide();
|
||||
|
||||
// 重置UI状态
|
||||
ui->pushButton_uninstall->hide();
|
||||
ui->pushButton_website->setEnabled(false);
|
||||
ui->pushButton->setEnabled(false);
|
||||
ui->pushButton_translate->setEnabled(false);
|
||||
ui->label_show->setText("Loading...");
|
||||
ui->label_show->show();
|
||||
}
|
||||
|
||||
void Widget::sltAppinfoTags(QStringList *tagList)
|
||||
{
|
||||
foreach (const QString &tag, *tagList) {
|
||||
if(tag=="community")
|
||||
ui->tag_community->show();
|
||||
else if(tag=="ubuntu")
|
||||
ui->tag_ubuntu->show();
|
||||
else if(tag=="deepin")
|
||||
ui->tag_deepin->show();
|
||||
else if(tag=="uos")
|
||||
ui->tag_uos->show();
|
||||
else if(tag=="dtk5")
|
||||
ui->tag_dtk5->show();
|
||||
else if(tag=="dwine2")
|
||||
ui->tag_dwine2->show();
|
||||
else if(tag=="dwine5")
|
||||
ui->tag_dwine5->show();
|
||||
else if(tag=="a2d")
|
||||
ui->tag_a2d->show();
|
||||
}
|
||||
}
|
||||
|
||||
void Widget::sltAppinfoDetails(QString *name, QString *details, QString *info,
|
||||
QString *website, QString *packageName, QUrl *fileUrl,
|
||||
bool isInstalled)
|
||||
{
|
||||
ui->label_appname->setText(appName = *name);
|
||||
ui->label_appname->show();
|
||||
ui->label_info->setText(*details);
|
||||
ui->label_info->show();
|
||||
ui->label_more->setText(*info);
|
||||
ui->label_more->show();
|
||||
pkgName = *packageName;
|
||||
url = *fileUrl;
|
||||
appweb = *website;
|
||||
if(isInstalled){
|
||||
ui->pushButton_download->setText(tr("Reinstall"));
|
||||
ui->pushButton_uninstall->show();
|
||||
}else {
|
||||
ui->pushButton_download->setText(tr("Install"));
|
||||
}
|
||||
}
|
||||
|
||||
void Widget::sltAppinfoIcon(QPixmap *icon)
|
||||
{
|
||||
ui->label_appicon->setPixmap(*icon);
|
||||
ui->label_appicon->show();
|
||||
ui->pushButton_download->setEnabled(true);
|
||||
ui->pushButton->setEnabled(true);
|
||||
ui->pushButton_translate->setEnabled(true);
|
||||
ui->pushButton_website->setEnabled(true);
|
||||
}
|
||||
|
||||
void Widget::sltAppinfoScreenshot(QPixmap *picture, int index)
|
||||
{
|
||||
if(picture != nullptr) {
|
||||
screen[index] = *picture;
|
||||
label_screen[index]->setImage(*picture);
|
||||
label_screen[index]->show();
|
||||
switch(index) { // 故意为之,为了清除多余截图
|
||||
case 0:
|
||||
label_screen[1]->hide();
|
||||
case 1:
|
||||
label_screen[2]->hide();
|
||||
case 2:
|
||||
label_screen[3]->hide();
|
||||
case 3:
|
||||
label_screen[4]->hide();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Widget::sltAppinfoFinish()
|
||||
{
|
||||
ui->label_show->setText("");
|
||||
ui->label_show->hide();
|
||||
}
|
||||
|
||||
void Widget::httpFinished() // 完成下载
|
||||
{
|
||||
file->flush();
|
||||
@@ -727,6 +855,7 @@ void Widget::on_pushButton_return_clicked()
|
||||
// chooseLeftMenu(13);
|
||||
// return;
|
||||
// }
|
||||
appinfoLoadThread.requestInterruption();
|
||||
chooseLeftMenu(nowMenu);
|
||||
// if(themeIsDark){
|
||||
// QString darkurl=menuUrl[nowMenu].toString();
|
||||
@@ -746,13 +875,14 @@ void Widget::on_pushButton_return_clicked()
|
||||
void Widget::on_pushButton_refresh_clicked()
|
||||
{
|
||||
if(ui->stackedWidget->currentIndex() == 2) //如果在详情页面要重新触发UrlChanged
|
||||
emit ui->webEngineView->urlChanged(ui->webEngineView->url());
|
||||
emit ui->webEngineView->urlChanged(ui->webEngineView->url());
|
||||
else
|
||||
ui->webEngineView->reload();
|
||||
ui->webEngineView->reload();
|
||||
}
|
||||
|
||||
void Widget::on_comboBox_server_currentIndexChanged(const QString &arg1)
|
||||
{
|
||||
appinfoLoadThread.setServer(arg1); // 服务器信息更新
|
||||
if(configCanSave){
|
||||
ui->label_setting1->show();
|
||||
QSettings *setConfig=new QSettings(QDir::homePath()+"/.config/spark-store/config.ini",QSettings::IniFormat);
|
||||
@@ -785,70 +915,70 @@ void Widget::on_pushButton_updateServer_clicked()
|
||||
void Widget::on_pushButton_updateApt_clicked()
|
||||
{
|
||||
QtConcurrent::run([=](){
|
||||
ui->pushButton_updateApt->setEnabled(false);
|
||||
ui->label_aptserver->setText(tr("Updating, please wait..."));
|
||||
ui->pushButton_updateApt->setEnabled(false);
|
||||
ui->label_aptserver->setText(tr("Updating, please wait..."));
|
||||
|
||||
std::fstream sourcesList, policy, update;
|
||||
QDir tmpdir("/tmp");
|
||||
auto tmpPath = QString::fromUtf8(TMP_PATH).toStdString();
|
||||
bool unknownError = true;
|
||||
std::fstream sourcesList, policy, update;
|
||||
QDir tmpdir("/tmp");
|
||||
auto tmpPath = QString::fromUtf8(TMP_PATH).toStdString();
|
||||
bool unknownError = true;
|
||||
|
||||
tmpdir.mkpath("spark-store");
|
||||
sourcesList.open(tmpPath + "/sparkstore.list", std::ios::out);
|
||||
//policy.open(tmpPath + "/sparkstore", std::ios::out);
|
||||
// 商店已经下架会替换系统库的包,优先级policy弃用
|
||||
tmpdir.mkpath("spark-store");
|
||||
sourcesList.open(tmpPath + "/sparkstore.list", std::ios::out);
|
||||
//policy.open(tmpPath + "/sparkstore", std::ios::out);
|
||||
// 商店已经下架会替换系统库的包,优先级policy弃用
|
||||
|
||||
if(sourcesList /*&& policy*/) {
|
||||
auto serverAddr = ui->comboBox_server->currentText();
|
||||
if(sourcesList /*&& policy*/) {
|
||||
auto serverAddr = ui->comboBox_server->currentText();
|
||||
|
||||
sourcesList << "deb [by-hash=force] ";
|
||||
sourcesList << serverAddr.toUtf8().toStdString();
|
||||
sourcesList << " /";
|
||||
sourcesList.close();
|
||||
sourcesList << "deb [by-hash=force] ";
|
||||
sourcesList << serverAddr.toUtf8().toStdString();
|
||||
sourcesList << " /";
|
||||
sourcesList.close();
|
||||
|
||||
/*
|
||||
/*
|
||||
policy << "Package: *\n"
|
||||
"Pin: origin *" << serverAddr.mid(serverAddr.indexOf('.')).toUtf8().toStdString() << "\n"
|
||||
"Pin-Priority: 90"; // 降低星火源的优先级,防止从星火安装已存在的系统包,破坏依赖
|
||||
policy.close();
|
||||
*/
|
||||
|
||||
update.open(tmpPath + "/update.sh",std::ios::out);
|
||||
if(update) {
|
||||
unknownError = false;
|
||||
update << "#!/bin/sh\n"
|
||||
"mv " + tmpPath + "/sparkstore.list /etc/apt/sources.list.d/sparkstore.list && "
|
||||
// "mv " + tmpPath + "/sparkstore /etc/apt/preferences.d/sparkstore && "
|
||||
"apt update";
|
||||
update.close();
|
||||
update.open(tmpPath + "/update.sh",std::ios::out);
|
||||
if(update) {
|
||||
unknownError = false;
|
||||
update << "#!/bin/sh\n"
|
||||
"mv " + tmpPath + "/sparkstore.list /etc/apt/sources.list.d/sparkstore.list && "
|
||||
// "mv " + tmpPath + "/sparkstore /etc/apt/preferences.d/sparkstore && "
|
||||
"apt update";
|
||||
update.close();
|
||||
|
||||
system(("chmod +x " + tmpPath + "/update.sh").c_str());
|
||||
QProcess runupdate;
|
||||
runupdate.start(QString::fromStdString("pkexec " + tmpPath + "/update.sh"));
|
||||
runupdate.waitForFinished();
|
||||
QString error = runupdate.readAllStandardError();
|
||||
system(("chmod +x " + tmpPath + "/update.sh").c_str());
|
||||
QProcess runupdate;
|
||||
runupdate.start(QString::fromStdString("pkexec " + tmpPath + "/update.sh"));
|
||||
runupdate.waitForFinished();
|
||||
QString error = runupdate.readAllStandardError();
|
||||
|
||||
QStringList everyError = error.split("\n");
|
||||
bool haveError = false;
|
||||
for (int i=0; i < everyError.size(); i++) {
|
||||
if(everyError[i].left(2) == "E:") {
|
||||
haveError = true;
|
||||
}
|
||||
}
|
||||
QStringList everyError = error.split("\n");
|
||||
bool haveError = false;
|
||||
for (int i=0; i < everyError.size(); i++) {
|
||||
if(everyError[i].left(2) == "E:") {
|
||||
haveError = true;
|
||||
}
|
||||
}
|
||||
|
||||
if(!haveError) {
|
||||
ui->label_aptserver->setText("deb [by-hash=force] " + ui->comboBox_server->currentText().toUtf8() + " /");
|
||||
} else {
|
||||
ui->label_aptserver->setText(tr("Apt has reported an error. Please use apt update in terminal to locate the problem."));
|
||||
}
|
||||
}
|
||||
}
|
||||
if(!haveError) {
|
||||
ui->label_aptserver->setText("deb [by-hash=force] " + ui->comboBox_server->currentText().toUtf8() + " /");
|
||||
} else {
|
||||
ui->label_aptserver->setText(tr("Apt has reported an error. Please use apt update in terminal to locate the problem."));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(unknownError) {
|
||||
ui->label_aptserver->setText(tr("Unknown error!"));
|
||||
}
|
||||
if(unknownError) {
|
||||
ui->label_aptserver->setText(tr("Unknown error!"));
|
||||
}
|
||||
|
||||
ui->pushButton_updateApt->setEnabled(true);
|
||||
ui->pushButton_updateApt->setEnabled(true);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -983,10 +1113,16 @@ void Widget::on_webEngineView_urlChanged(const QUrl &arg1)
|
||||
ui->pushButton_download->setEnabled(false);
|
||||
ui->stackedWidget->setCurrentIndex(2);
|
||||
qDebug()<<"https://demo-one-vert.vercel.app/"+type_name+"/"+pname;
|
||||
/*
|
||||
load.cancel();//打开并发加载线程前关闭正在执行的线程
|
||||
load = QtConcurrent::run([=](){
|
||||
int loadresult = loadappinfo(arg1);
|
||||
});
|
||||
*/
|
||||
appinfoLoadThread.requestInterruption();
|
||||
appinfoLoadThread.wait(100);
|
||||
appinfoLoadThread.setUrl(arg1);
|
||||
appinfoLoadThread.start();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1009,7 +1145,7 @@ void Widget::on_webEngineView_loadProgress(int progress)
|
||||
void Widget::on_webEngineView_loadFinished(bool arg1)
|
||||
{
|
||||
if(arg1){
|
||||
m_loadweb->setValue(0);
|
||||
m_loadweb->setValue(0);
|
||||
}else {
|
||||
m_loadweb->setValue(0);
|
||||
m_loaderror->show();
|
||||
|
||||
17
widget.h
17
widget.h
@@ -21,6 +21,9 @@
|
||||
#include <DTitlebar>
|
||||
#include <DSearchEdit>
|
||||
#include <progressload.h>
|
||||
#include "workerthreads.h"
|
||||
#include "image_show.h"
|
||||
|
||||
#define LIST_MAX 99 //一次最多下载数量
|
||||
#define TMP_PATH "/tmp/spark-store"
|
||||
|
||||
@@ -56,6 +59,17 @@ private slots:
|
||||
void httpFinished();
|
||||
void httpReadyRead();
|
||||
void updateDataReadProgress(qint64,qint64);
|
||||
|
||||
// SpkAppInfoLoaderThread的槽函数
|
||||
void sltAppinfoResetUi();
|
||||
void sltAppinfoTags(QStringList *tagList);
|
||||
void sltAppinfoDetails(QString *name, QString *details, QString *info,
|
||||
QString *website, QString *packageName,
|
||||
QUrl *fileUrl, bool isInstalled);
|
||||
void sltAppinfoIcon(QPixmap *icon);
|
||||
void sltAppinfoScreenshot(QPixmap *picture, int index);
|
||||
void sltAppinfoFinish();
|
||||
|
||||
void on_pushButton_download_clicked();
|
||||
void on_pushButton_return_clicked();
|
||||
void on_comboBox_server_currentIndexChanged(const QString &arg1);
|
||||
@@ -125,6 +139,9 @@ private:
|
||||
DSearchEdit *searchEdit=new DSearchEdit;
|
||||
DTitlebar *titlebar;
|
||||
|
||||
QList<image_show*> label_screen;
|
||||
SpkAppInfoLoaderThread appinfoLoadThread;
|
||||
|
||||
};
|
||||
|
||||
#endif // WIDGET_H
|
||||
|
||||
152
workerthreads.cpp
Normal file
152
workerthreads.cpp
Normal file
@@ -0,0 +1,152 @@
|
||||
|
||||
#include <QProcess>
|
||||
#include <QDir>
|
||||
#include <QFile>
|
||||
#include <QJsonDocument>
|
||||
#include "workerthreads.h"
|
||||
#include "widget.h"
|
||||
|
||||
void SpkAppInfoLoaderThread::run()
|
||||
{
|
||||
emit requestResetUi();
|
||||
|
||||
QProcess get_json;
|
||||
QString urladdress, deatils, more, packagename, appweb;
|
||||
QDir dir("/tmp");
|
||||
bool isInstalled;
|
||||
dir.mkdir("spark-store");
|
||||
QDir::setCurrent("/tmp/spark-store");
|
||||
|
||||
get_json.start("curl -o app.json " + targetUrl.toString());
|
||||
if(waitDownload(get_json) == -1)
|
||||
return;
|
||||
if(get_json.exitCode())
|
||||
{
|
||||
Widget::sendNotification(tr("Failed to download app info. Please check internet connection."));
|
||||
}
|
||||
|
||||
QFile app_json("app.json");
|
||||
if(app_json.open(QIODevice::ReadOnly)){
|
||||
// 成功得到json文件
|
||||
QByteArray json_array = app_json.readAll();
|
||||
// 将路径转化为相应源的下载路径
|
||||
urladdress = targetUrl.toString().left(targetUrl.toString().length()-8);
|
||||
QStringList downloadurl=urladdress.split("/");
|
||||
|
||||
QString deburl = serverUrl;
|
||||
deburl = deburl.left(urladdress.length()-1);
|
||||
urladdress = "https://cdn.jsdelivr.net/gh/Jerrywang959/jsonpng@master/"; // 使用图片专用服务器请保留这行,删除后将使用源服务器
|
||||
urladdress = urladdress.left(urladdress.length()-1);
|
||||
|
||||
for (int i=3;i<downloadurl.size();i++) {
|
||||
urladdress+="/"+downloadurl[i];
|
||||
deburl+="/"+downloadurl[i];
|
||||
}
|
||||
|
||||
// 路径转化完成
|
||||
QJsonObject json= QJsonDocument::fromJson(json_array).object();
|
||||
QString appName = json["Name"].toString();
|
||||
QUrl fileUrl = deburl + json["Filename"].toString();
|
||||
|
||||
// 软件信息加载
|
||||
QString details;
|
||||
details = tr("PkgName: ") + json["Pkgname"].toString()+"\n";
|
||||
details += tr("Version: ") + json["Version"].toString()+"\n";
|
||||
if(json["Author"].toString() != "" && json["Author"].toString() != " "){
|
||||
details += tr("Author: ") + json["Author"].toString() + "\n";
|
||||
}
|
||||
|
||||
if(json["Website"].toString() != "" && json["Website"].toString() != " "){
|
||||
details += tr("Official Site: ") + json["Website"].toString() + "\n";
|
||||
//ui->pushButton_website->show(); move to setinfo slot
|
||||
appweb=json["Website"].toString();
|
||||
}
|
||||
details+=tr("Contributor: ")+json["Contributor"].toString()+"\n";
|
||||
details+=tr("Update Time: ")+json["Update"].toString()+"\n";
|
||||
details+=tr("Installed Size: ")+json["Size"].toString()+"\n";
|
||||
more = json["More"].toString();
|
||||
|
||||
QProcess isInstall;
|
||||
packagename = json["Pkgname"].toString();
|
||||
isInstall.start("dpkg -s "+json["Pkgname"].toString());
|
||||
isInstall.waitForFinished();
|
||||
int error=QString::fromStdString(isInstall.readAllStandardError().toStdString()).length();
|
||||
if(error==0)
|
||||
isInstalled = true;
|
||||
else
|
||||
isInstalled = false;
|
||||
|
||||
emit requestSetAppInformation(&appName, &details, &more, &appweb, &packagename, &fileUrl, isInstalled);
|
||||
|
||||
//tag加载
|
||||
QString tags=json["Tags"].toString();
|
||||
QStringList tagList=tags.split(";");
|
||||
emit requestSetTags(&tagList);
|
||||
|
||||
// 图标加载
|
||||
get_json.start("curl -o icon.png "+urladdress+"icon.png");
|
||||
if(waitDownload(get_json) == -1)
|
||||
return;
|
||||
if(!get_json.exitCode()) {
|
||||
QPixmap appicon("icon.png");
|
||||
emit finishedIconLoad(&appicon);
|
||||
}
|
||||
else
|
||||
Widget::sendNotification(tr("Failed to load application icon."));
|
||||
|
||||
|
||||
// 截图展示加载
|
||||
QPixmap screenshotCache[5];
|
||||
for (int i = 0; i < 5; i++) {
|
||||
QString cmd = "curl -o screen_"+QString::number(i+1)+".png "+urladdress+"screen_"+QString::number(i+1)+".png";
|
||||
get_json.start(cmd);
|
||||
if(waitDownload(get_json) == -1)
|
||||
return;
|
||||
bool s = screenshotCache[i].load(QString(TMP_PATH) + "/screen_"+QString::number(i+1)+".png");
|
||||
if(s){
|
||||
emit finishedScreenshotLoad(&screenshotCache[i], i);
|
||||
}else{
|
||||
emit finishedScreenshotLoad(nullptr, i);
|
||||
QFile::remove("screen_"+QString::number(i+1)+".png");
|
||||
break;
|
||||
}
|
||||
}
|
||||
emit finishAllLoading();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void SpkAppInfoLoaderThread::setUrl(const QUrl &url)
|
||||
{
|
||||
targetUrl = url;
|
||||
}
|
||||
|
||||
void SpkAppInfoLoaderThread::setServer(const QString &server)
|
||||
{
|
||||
serverUrl = server;
|
||||
}
|
||||
|
||||
void SpkAppInfoLoaderThread::downloadFinished(int exitcode, QProcess::ExitStatus status)
|
||||
{
|
||||
Q_UNUSED(exitcode);
|
||||
Q_UNUSED(status);
|
||||
qDebug() << "Finish one download";
|
||||
finishedDownload = true;
|
||||
}
|
||||
|
||||
int SpkAppInfoLoaderThread::waitDownload(QProcess& downloader)
|
||||
{
|
||||
while(!downloader.waitForFinished(100))
|
||||
{
|
||||
if(downloader.state() == QProcess::NotRunning)
|
||||
return -1;
|
||||
if(this->isInterruptionRequested())
|
||||
{
|
||||
downloader.terminate();
|
||||
downloader.waitForFinished(-1);
|
||||
qDebug() << "Appinfo loader thread was forcefully terminated";
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
36
workerthreads.h
Normal file
36
workerthreads.h
Normal file
@@ -0,0 +1,36 @@
|
||||
#ifndef WORKERTHREADS_H
|
||||
#define WORKERTHREADS_H
|
||||
|
||||
#include <QThread>
|
||||
#include <QPixmap>
|
||||
#include <QUrl>
|
||||
#include <QProcess>
|
||||
|
||||
class SpkAppInfoLoaderThread Q_DECL_FINAL : public QThread
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
//explicit SpkAppInfoLoaderThread() = default;
|
||||
void run() Q_DECL_OVERRIDE;
|
||||
public slots:
|
||||
void setUrl(const QUrl &url);
|
||||
void setServer(const QString &server);
|
||||
void downloadFinished(int exitcode, QProcess::ExitStatus status);
|
||||
signals:
|
||||
void requestResetUi();
|
||||
void requestSetTags(QStringList *tagList);
|
||||
void requestSetAppInformation(QString *name, QString *details, QString *info,
|
||||
QString *website, QString *packageName,
|
||||
QUrl *fileUrl, bool isInstalled);
|
||||
void finishedIconLoad(QPixmap *icon);
|
||||
void finishedScreenshotLoad(QPixmap *icon, int index); // 该信号必须以BlockingQueued方式连接
|
||||
void finishAllLoading(); // 该信号必须以BlockingQueued方式连接
|
||||
private:
|
||||
int waitDownload(QProcess& downloader);
|
||||
QUrl targetUrl;
|
||||
QString serverUrl;
|
||||
bool finishedDownload = false;
|
||||
int downloaderRetval = 0;
|
||||
};
|
||||
|
||||
#endif // WORKERTHREADS_H
|
||||
Reference in New Issue
Block a user