Compare commits

...

30 Commits

Author SHA1 Message Date
0ab9f4dda6 !22 合并 multiple 分支修复的 BUG
Merge pull request !22 from zty199/multiple
2021-06-13 14:36:48 +08:00
5a97f6caef Merge branch 'master' of gitee.com:deepin-community-store/spark-store into multiple 2021-06-13 14:36:05 +08:00
3da25b0904 Fix bugs about server address in widget.cpp 2021-06-13 14:30:31 +08:00
RigoLigo
116c824365 更正错误的服务URL 2021-06-09 20:40:45 +08:00
zty199
44edb08518 Fix issues about TitleBar
Fix a issue about titlebar display on Ubuntu.
2021-04-24 21:17:51 +08:00
zty199
9a3d32ee11 Improve Features
Support save current theme setting when exit;
Use QScreen::primaryScreen() instead of QDesktopWidget to get desktop size;
Ensure only one instance will be running at the same time.
2021-04-20 18:49:17 +08:00
Jerry
e5fe80cb76 add jenkins from master 2021-04-20 16:04:42 +08:00
Jerry
9314acd7e1 !21 Jenkins自动构建并在commit下评论
* debug
* update
* debug
* debug
* debug
* debug
* debug
* update
* update
* debug
* Merge branch 'jenkins' of gitee.com:deepin-community-store/spark-store…
* up
* Added Jenkinsfile
* debug
* debug
* debug
* up
* up
* debug
* up
* debug
* Merge branch 'jenkins' of gitee.com:deepin-community-store/spark-store…
* debug
* Added Jenkinsfile
* Added Jenkinsfile
* up
* 1
* update
* Added Jenkinsfile
* Merge branch 'jenkins' of gitee.com:deepin-community-store/spark-store…
* update
* Added Jenkinsfile
* Added Jenkinsfile
* Added Jenkinsfile
* Added Jenkinsfile
* 不使用 make -j
* 修改字体
* Added Jenkinsfile
* Added Jenkinsfile
2021-04-20 15:50:44 +08:00
zty199
e64e7fcae2 Reorganize codes
Reorganize all parts of codes;
Fix a bug that index page color is not correct when initialized.
2021-04-17 15:43:11 +08:00
536efeedfa !19 检查 UI 中的 BUG
* 整理部分代码
* 修改下载线程上限 4 线程为 5 线程
2021-04-17 04:37:30 +08:00
zty199
6fd3c40e97 Reorganize part of codes
Reorganize spark-store.pro, widget.h and widget.cpp.
2021-04-17 04:30:28 +08:00
Jerry
90513a8925 !18 4线程到5线程
Merge pull request !18 from Jerry/4to5
2021-04-17 03:23:01 +08:00
Jerry
ed3d869b99 4线程切换到5线程 2021-04-17 03:22:03 +08:00
Jerry
c80737a458 Merge branch 'multiple' of gitee.com:deepin-community-store/spark-store into multiple 2021-04-17 03:19:44 +08:00
Jerry
ebf30e67f9 4线程到5线程 2021-04-17 03:19:38 +08:00
Jerry
90b684af87 Merge branch 'master' of gitee.com:deepin-community-store/spark-store into multiple 2021-04-17 03:18:40 +08:00
Jerry
3ff363d7b1 4线程切到5线程 2021-04-17 03:16:22 +08:00
Jerry
f7ced7739c !17 多线程下载合并
* Update README.md
* Improve Features
* 修改获取线路的域名
* 修改默认源
* 修改多线程下载域名和图片服务器
* 修正取消下载的闪退问题
* 将图片下载由 curl 转为 QtNetworkService
* 切换多域名下载,提高下载速度
* 完成并发请求下载
2021-04-17 01:35:51 +08:00
zty199
e12f617f59 Update README.md 2021-04-17 01:16:01 +08:00
zty199
d164aec86d Improve Features
Fix a bug that annotations in server list can be chosen in combobox;
Fix a bug that index page don't follow system theme;
Disable qDebug/qWarning output in Release version;
Update default server list.
2021-04-17 00:53:26 +08:00
Jerry
96cd1b9918 修改获取线路的域名 2021-04-16 19:05:30 +08:00
Jerry
393c8220f5 修改默认源 2021-04-16 18:48:01 +08:00
Jerry
01d1543cc4 修改多线程下载域名和图片服务器 2021-04-16 12:19:22 +08:00
metanoia1989
4ccc8c0dae 修正取消下载的闪退问题 2021-03-06 17:00:55 +08:00
metanoia1989
815036e28f 将图片下载由 curl 转为 QtNetworkService 2021-03-06 15:18:31 +08:00
metanoia1989
9cc68fac86 切换多域名下载,提高下载速度 2021-02-20 06:47:57 +08:00
metanoia1989
2f8c11a30b 完成并发请求下载 2021-02-16 23:00:27 +08:00
1a4b1176fb !16 Improve Features
* Improce Features
* History Backup for Version 3.0-stable
2021-01-30 21:12:20 +08:00
3101f1fe70 Restore Patches 2020-12-17 00:18:10 +08:00
58f32c119a Bump version to 3.0 2020-12-16 23:49:54 +08:00
32 changed files with 1636 additions and 1074 deletions

2
.gitee/Dockerfile Normal file
View File

@@ -0,0 +1,2 @@
FROM python:3
RUN pip3 install requests

31
.gitee/callback.py Normal file
View File

@@ -0,0 +1,31 @@
import os
import requests
import json
# sha=os.system("git rev-parse HEAD")
sha = os.getenv("GIT_COMMIT")
# sha = '48fed26c51a8c42554e45f72f43e49703e04c97f'
#get sha from environment
url = "https://gitee.com/api/v5/repos/deepin-community-store/spark-store/commits/{}/comments".format(sha)
token = os.getenv("gitee_token")
# process = os.popen("git symbolic-ref --short -q HEAD")
body = "构建详情请见" + os.getenv("JENKINS_URL") + "blue/organizations/jenkins/" + os.getenv("JOB_NAME").replace("/", "/detail/") + "/" + str(os.getenv("BUILD_ID"))
# process.close()
d = {
'access_token': token,
"body": body
}
h = {
"Content-Type": "application/json;charset=UTF-8"
}
res = requests.post(url,headers=h, data=json.dumps(d))
# print(res.status_code)
# print(res.content)

33
Jenkinsfile vendored Normal file
View File

@@ -0,0 +1,33 @@
pipeline {
agent any
stages {
stage('build') {
agent {
docker {
image 'jerry979/dtke:5.11'
}
}
steps {
sh 'mkdir build && cd build && qmake .. && make '
archiveArtifacts(artifacts: 'build/src/spark-store', allowEmptyArchive: true, defaultExcludes: true)
}
}
stage('send') {
agent {
dockerfile {
filename '.gitee/Dockerfile'
}
}
environment {
gitee_token = credentials('1')
}
steps {
sh "python3 .gitee/callback.py"
}
}
}
}

View File

@@ -21,9 +21,8 @@ web页面部分正在开发当中详情请见[web仓库](https://gitee.com/de
当前服务器线路列表(项目中包含):
```
http://sucdn.jerrywang.top/
http://store.jerrywang.top/
http://dcstore.spark-app.store/
https://d.store.deepinos.org.cn/
https://store.deepinos.org.cn/
```
#### 调用参数(spk规则)

View File

@@ -64,6 +64,6 @@
<file>tags/dwine2-small.png</file>
</qresource>
<qresource prefix="/fonts">
<file>fonts/华康少女字体.ttf</file>
<file>fonts/hksnzt.ttf</file>
</qresource>
</RCC>

View File

@@ -1,7 +1,9 @@
TEMPLATE = subdirs
CONFIG += ordered
SUBDIRS = third-party/QtNetworkService \
SUBDIRS += \
third-party/QtNetworkService \
src/spark-store.pro
spark-store.depends = third-party/QtNetworkService
spark-store.depends = third-party/QtNetworkService

View File

@@ -14,12 +14,12 @@ AppItem::AppItem(QWidget *parent) :
{
ui->setupUi(this);
// auto shadow = new QGraphicsDropShadowEffect();
// shadow->setXOffset(0);
// shadow->setYOffset(1);
// shadow->setBlurRadius(2);
// shadow->setColor(QColor::fromRgba(qRgba(0, 0, 0, 180)));
// ui->container->setGraphicsEffect(shadow);
// auto shadow = new QGraphicsDropShadowEffect();
// shadow->setXOffset(0);
// shadow->setYOffset(1);
// shadow->setBlurRadius(2);
// shadow->setColor(QColor::fromRgba(qRgba(0, 0, 0, 180)));
// ui->container->setGraphicsEffect(shadow);
}
AppItem::~AppItem()
@@ -46,7 +46,8 @@ void AppItem::setDescription(QString description)
void AppItem::setIcon(QString icon)
{
m_icon = icon;
if (!icon.isEmpty()) {
if(!icon.isEmpty())
{
downloadIcon(icon);
}
}
@@ -58,7 +59,8 @@ void AppItem::setUrl(QString url)
void AppItem::mousePressEvent(QMouseEvent *event)
{
Q_UNUSED(event);
Q_UNUSED(event)
emit clicked(QUrl(m_url));
}
@@ -68,8 +70,10 @@ void AppItem::mousePressEvent(QMouseEvent *event)
*/
void AppItem::downloadIcon(QString icon)
{
QtConcurrent::run([=](){
QtConcurrent::run([=]()
{
auto reqManager = new QNetworkAccessManager();
QUrl url(icon);
QNetworkReply *reply = reqManager->get(QNetworkRequest(url));
QEventLoop loop;
@@ -77,14 +81,17 @@ void AppItem::downloadIcon(QString icon)
connect(reply, &QNetworkReply::finished, this, [=] () { emit finished(); });
loop.exec();
reqManager->deleteLater();
QPixmap pixmap;
pixmap.loadFromData(reply->readAll());
pixmap = pixmap.scaled(78, 78, Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
if (reply->error() == QNetworkReply::NoError) {
QMetaObject::invokeMethod(this, "loadIcon", Qt::QueuedConnection,
Q_ARG(QPixmap, pixmap));
} else {
qDebug() << reply->errorString();
if (reply->error() == QNetworkReply::NoError)
{
QMetaObject::invokeMethod(this, "loadIcon", Qt::QueuedConnection, Q_ARG(QPixmap, pixmap));
}
else
{
qDebug() << reply->errorString();
}
});
}
@@ -93,5 +100,3 @@ void AppItem::loadIcon(QPixmap pic)
{
ui->lbl_icon->setPixmap(pic);
}

View File

@@ -14,7 +14,7 @@ class AppItem : public QWidget
public:
explicit AppItem(QWidget *parent = nullptr);
~AppItem();
~AppItem() override;
void setTitle(QString title);
void setDescription(QString description);
@@ -24,14 +24,6 @@ public:
protected:
void mousePressEvent(QMouseEvent *event) override;
signals:
void clicked(QUrl url);
void finished();
public slots:
void downloadIcon(QString icon);
void loadIcon(QPixmap pic);
private:
Ui::AppItem *ui;
@@ -39,6 +31,15 @@ private:
QString m_description;
QString m_icon;
QString m_url;
public slots:
void downloadIcon(QString icon);
void loadIcon(QPixmap pic);
signals:
void clicked(QUrl url);
void finished();
};
#endif // APPITEM_H

View File

@@ -1,22 +1,30 @@
#include "big_image.h"
#include <QHBoxLayout>
#include <QtConcurrent>
big_image::big_image(DBlurEffectWidget *parent) : DBlurEffectWidget(parent)
big_image::big_image(DBlurEffectWidget *parent) :
DBlurEffectWidget(parent),
m_image(new QLabel)
{
// m_image->setParent(this);
QHBoxLayout *layout=new QHBoxLayout;
setLayout(layout);
layout->addWidget(m_image);
layout->setMargin(0);
m_image->setAlignment(Qt::AlignCenter);
// m_image->setMaximumSize(1360,768);
setWindowFlags(this->windowFlags() | Qt::WindowStaysOnTopHint);//设置图片对话框总在最前
setWindowFlags(this->windowFlags() | Qt::WindowStaysOnTopHint); // 设置图片对话框总在最前
setRadius(0);
setMaskAlpha(60);
setMaskColor(QColor("#000000"));
QHBoxLayout *layout = new QHBoxLayout;
setLayout(layout);
layout->addWidget(m_image);
layout->setMargin(0);
// m_image->setParent(this);
// m_image->setMaximumSize(1360,768);
m_image->setAlignment(Qt::AlignCenter);
}
void big_image::setimage(QPixmap image)
{
m_image->setPixmap(image);
}
void big_image::mousePressEvent(QMouseEvent *)
@@ -25,11 +33,6 @@ void big_image::mousePressEvent(QMouseEvent *)
m_image->clear();
}
void big_image::setimage(QPixmap image)
{
m_image->setPixmap(image);
}
void big_image::focusOutEvent(QFocusEvent *)
{
hide();

View File

@@ -1,25 +1,27 @@
#ifndef BIG_IMAGE_H
#define BIG_IMAGE_H
#include <QWidget>
#include <DBlurEffectWidget>
#include <QMouseEvent>
#include <QLabel>
#include <DBlurEffectWidget>
DWIDGET_USE_NAMESPACE
class big_image : public DBlurEffectWidget
{
Q_OBJECT
public:
explicit big_image(DBlurEffectWidget *parent = nullptr);
void mousePressEvent(QMouseEvent *event);
QLabel *m_image=new QLabel;
QLabel *m_image;
void setimage(QPixmap);
void focusOutEvent(QFocusEvent *event);
signals:
public slots:
protected:
void mousePressEvent(QMouseEvent *event) override;
void focusOutEvent(QFocusEvent *event) override;
};
#endif // BIG_IMAGE_H

View File

@@ -1,19 +1,27 @@
#include "downloadlist.h"
#include "ui_downloadlist.h"
#include "widget.h"
#include <QDebug>
#include <QIcon>
#include <QPixmap>
#include <QtConcurrent>
#include <QProcess>
#include <QTextBrowser>
bool downloadlist::isInstall=false;
#include "widget.h"
bool downloadlist::isInstall = false;
downloadlist::downloadlist(QWidget *parent) :
QWidget(parent),
ui(new Ui::downloadlist)
reinstall(false),
close(false),
ui(new Ui::downloadlist),
menu_install(new QMenu),
action_dpkg(new QAction),
action_deepin(new QAction),
action_gdebi(new QAction),
output_w(new DDialog),
textbrowser(new QTextBrowser)
{
ui->setupUi(this);
ui->pushButton_install->setEnabled(false);
ui->progressBar->setValue(0);
ui->label_filename->hide();
@@ -22,22 +30,25 @@ downloadlist::downloadlist(QWidget *parent) :
ui->widget_spinner->start();
ui->widget_spinner->hide();
action_dpkg->setText(tr("Spark Store App Installer"));
action_gdebi->setText(tr("gdebi"));
action_deepin->setText(tr("deepin deb installer"));
action_gdebi->setText(tr("gdebi"));
connect(action_dpkg,&QAction::triggered,[=](){downloadlist::install(0);});
connect(action_deepin,&QAction::triggered,[=](){downloadlist::install(1);});
connect(action_gdebi,&QAction::triggered,[=](){downloadlist::install(2);});
//ssinstall命令存在时再加入该选项
QFile ssinstall("/bin/ssinstall");
// ssinstall 命令存在时再加入该选项
QFile ssinstall("/usr/local/bin/ssinstall");
ssinstall.open(QIODevice::ReadOnly);
if(ssinstall.isOpen()){
if(ssinstall.isOpen())
{
menu_install->addAction(action_dpkg);
}
QFile deepin("/bin/deepin-deb-installer");
QFile deepin("/usr/bin/deepin-deb-installer");
deepin.open(QIODevice::ReadOnly);
if(deepin.isOpen()){
if(deepin.isOpen())
{
menu_install->addAction(action_deepin);
}
@@ -49,18 +60,19 @@ downloadlist::~downloadlist()
delete ui;
}
void downloadlist::setValue(long long value)
void downloadlist::setValue(qint64 value)
{
ui->progressBar->setValue(int(value));
ui->label_2->setText(QString::number(double(value)/100)+"% ("+speed+")");
if(ui->label_2->text().left(4)=="100%"){
ui->progressBar->setValue(qint32(value));
ui->label_2->setText(QString::number(double(value) / 100) + "% (" + speed + ")");
if(ui->label_2->text().left(4) == "100%")
{
ui->label_2->setText(tr("Downloaded, waiting to install"));
}
}
void downloadlist::setMax(long long max)
void downloadlist::setMax(qint64 max)
{
ui->progressBar->setMaximum(int(max));
ui->progressBar->setMaximum(qint32(max));
}
void downloadlist::setName(QString name)
@@ -75,26 +87,28 @@ QString downloadlist::getName()
void downloadlist::readyInstall()
{
if(ui->progressBar->value()!= ui->progressBar->maximum() && !close){
if(ui->progressBar->value() != ui->progressBar->maximum() && !close)
{
ui->progressBar->hide();
ui->pushButton_install->show();
ui->pushButton_2->hide();
Widget::sendNotification(tr("Failed to download %1").arg(ui->label->text()), 5000,
"/tmp/spark-store/icon_"+QString::number(num).toUtf8()+".png");
"/tmp/spark-store/icon_" + QString::number(num).toUtf8() + ".png");
ui->label_2->setText(tr("Download FailedCheck Your Connection"));
ui->pushButton_install->setEnabled(false);
return;
return;
}
if(!close){
if(!close)
{
ui->progressBar->hide();
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");
"/tmp/spark-store/icon_" + QString::number(num).toUtf8() + ".png");
}
}
void downloadlist::setFileName(QString fileName)
@@ -114,79 +128,98 @@ void downloadlist::closeDownload()
void downloadlist::setSpeed(QString s)
{
speed=s;
speed = s;
}
void downloadlist::install(int t)
{
if(!isInstall){
isInstall=true;
if(!isInstall)
{
isInstall = true;
ui->pushButton_install->hide();
ui->widget_spinner->show();
qDebug()<<"/tmp/spark-store/"+ui->label_filename->text().toUtf8();
qDebug() << "/tmp/spark-store/" + ui->label_filename->text().toUtf8();
ui->label_2->setText(tr("Installing"));
QtConcurrent::run([=](){
QtConcurrent::run([=]()
{
QProcess installer;
if(!reinstall){
switch (t) {
if(!reinstall)
{
switch(t)
{
case 0:
installer.start("pkexec ssinstall /tmp/spark-store/"+ui->label_filename->text().toUtf8());
installer.start("pkexec ssinstall /tmp/spark-store/" + ui->label_filename->text().toUtf8());
break;
case 1:
installer.start("deepin-deb-installer /tmp/spark-store/"+ui->label_filename->text().toUtf8());
installer.start("deepin-deb-installer /tmp/spark-store/" + ui->label_filename->text().toUtf8());
break;
case 2:
installer.start("pkexec gdebi -n /tmp/spark-store/"+ui->label_filename->text().toUtf8());
break;
}
}else {
switch (t) {
case 0:
installer.start("pkexec ssinstall /tmp/spark-store/"+ui->label_filename->text().toUtf8());
break;
case 1:
installer.start("deepin-deb-installer /tmp/spark-store/"+ui->label_filename->text().toUtf8());
break;
case 2:
installer.start("pkexec gdebi -n /tmp/spark-store/"+ui->label_filename->text().toUtf8());
installer.start("pkexec gdebi -n /tmp/spark-store/" + ui->label_filename->text().toUtf8());
break;
}
}
bool haveError=false;
bool notRoot=false;
else
{
switch(t)
{
case 0:
installer.start("pkexec ssinstall /tmp/spark-store/" + ui->label_filename->text().toUtf8());
break;
case 1:
installer.start("deepin-deb-installer /tmp/spark-store/" + ui->label_filename->text().toUtf8());
break;
case 2:
installer.start("pkexec gdebi -n /tmp/spark-store/" + ui->label_filename->text().toUtf8());
break;
}
}
bool haveError = false;
bool notRoot = false;
installer.waitForFinished();
out=installer.readAllStandardOutput();
QStringList everyOut=out.split("\n");
for (int i=0;i<everyOut.size();i++) {
if(everyOut[i].left(2)=="E:"){
haveError=true;
out = installer.readAllStandardOutput();
QStringList everyOut = out.split("\n");
for(int i=0;i<everyOut.size();i++)
{
if(everyOut[i].left(2) == "E:")
{
haveError = true;
}
if(everyOut[i].right(14)=="Not authorized"){
notRoot=true;
if(everyOut[i].right(14) == "Not authorized")
{
notRoot = true;
}
}
QProcess isInstall;
isInstall.start("dpkg -s "+pkgName);
isInstall.start("dpkg -s " + pkgName);
isInstall.waitForFinished();
int error=QString::fromStdString(isInstall.readAllStandardError().toStdString()).length();
if(error==0){
int error = QString::fromStdString(isInstall.readAllStandardError().toStdString()).length();
if(error == 0)
{
ui->pushButton_install->hide();
ui->label_2->setText(tr("Finish"));
ui->pushButton_3->show();
}else {
}
else
{
ui->pushButton_install->show();
ui->pushButton_install->setText(tr("Retry"));
ui->label_2->setText(tr("Error happened in dpkg progress , you can try it again"));
ui->pushButton_3->show();
}
if(notRoot){
if(notRoot)
{
ui->label_2->setText(tr("dpkg progress had been abortedyou can retry installation"));
ui->pushButton_install->show();
ui->pushButton_3->hide();
}
ui->widget_spinner->hide();
downloadlist::isInstall=false;
ui->widget_spinner->hide();
downloadlist::isInstall = false;
});
qDebug()<<ui->label_filename->text().toUtf8();
@@ -196,7 +229,7 @@ void downloadlist::install(int t)
void downloadlist::on_pushButton_install_clicked()
{
//弹出菜单
// 弹出菜单
menu_install->exec(cursor().pos());
}
@@ -205,17 +238,18 @@ void downloadlist::on_pushButton_2_clicked()
ui->label_2->setText(tr("Download canceled"));
ui->pushButton_2->setEnabled(false);
ui->progressBar->hide();
close=true;
close = true;
}
void downloadlist::on_pushButton_3_clicked()
{
output_w.layout()->addWidget(textbrowser);
textbrowser->setLineWidth(0);
textbrowser->setText(out);
output_w.layout()->setMargin(20);
output_w.setTitle(ui->label->text());
output_w.setMinimumHeight(600);
output_w.setAttribute(Qt::WA_TranslucentBackground);
output_w.show();
output_w->setMinimumHeight(600);
output_w->setAttribute(Qt::WA_TranslucentBackground);
output_w->setTitle(ui->label->text());
output_w->layout()->setMargin(20);
output_w->layout()->addWidget(textbrowser);
output_w->show();
}

View File

@@ -2,11 +2,14 @@
#define DOWNLOADLIST_H
#include <QWidget>
#include <DDialog>
#include <QTextBrowser>
#include <QMenu>
#include <QAction>
#include <DDialog>
DWIDGET_USE_NAMESPACE
namespace Ui {
class downloadlist;
}
@@ -18,40 +21,45 @@ class downloadlist : public QWidget
public:
explicit downloadlist(QWidget *parent = nullptr);
~downloadlist();
void setValue(long long);
void setMax(long long);
int num;
bool free;
static bool isInstall;
bool reinstall;
QString speed;
QString out;
QString pkgName;
bool close;
void setValue(qint64);
void setMax(qint64);
void setName(QString);
QString getName();
void readyInstall();
bool free;
void setFileName(QString);
void seticon(const QPixmap);
void closeDownload();
void setSpeed(QString);
int num;
bool close=false;
QString out;
DDialog output_w;
QTextBrowser *textbrowser=new QTextBrowser;
bool reinstall=false;
QString pkgName;
QMenu *menu_install=new QMenu;
QAction *action_gdebi=new QAction;
QAction *action_dpkg=new QAction;
QAction *action_deepin=new QAction;
void install(int);
private slots:
void on_pushButton_install_clicked();
// void on_pushButton_maninst_clicked();
void on_pushButton_2_clicked();
void on_pushButton_3_clicked();
private:
Ui::downloadlist *ui;
static bool isInstall;
QString speed;
QMenu *menu_install;
QAction *action_dpkg;
QAction *action_deepin;
QAction *action_gdebi;
DDialog *output_w;
QTextBrowser *textbrowser;
private slots:
void on_pushButton_install_clicked();
void on_pushButton_2_clicked();
void on_pushButton_3_clicked();
};
//bool downloadlist::isInstall=false;
#endif // DOWNLOADLIST_H

277
src/downloadworker.cpp Normal file
View File

@@ -0,0 +1,277 @@
#include "downloadworker.h"
#include <QEventLoop>
#include <QNetworkAccessManager>
#include <QNetworkRequest>
#include <QNetworkReply>
#include <QThread>
#include <QRegularExpression>
#include <QFileInfo>
#include <QDir>
DownloadWorker::DownloadWorker(QObject *parent)
{
Q_UNUSED(parent)
}
void DownloadWorker::setIdentifier(int identifier)
{
this->identifier = identifier;
}
void DownloadWorker::setParamter(const QString &url, QPair<qint64, qint64> range, QFile *file)
{
this->url = url;
this->startPos = range.first;
this->endPos = range.second;
this->file = file;
}
qint64 DownloadWorker::getReceivedPos()
{
return receivedPos;
}
void DownloadWorker::doWork()
{
mgr = new QNetworkAccessManager(this);
QNetworkRequest request;
request.setUrl(url);
request.setAttribute(QNetworkRequest::FollowRedirectsAttribute, true);
request.setRawHeader("Range", QString("bytes=%1-%2").arg(startPos).arg(endPos).toLocal8Bit());
reply = mgr->get(request);
qDebug() << "开始下载数据:" << QString(" %1~%2 -> writePos Start %3").arg(startPos).arg(endPos).arg(receivedPos);
connect(reply, static_cast<void(QNetworkReply::*)(QNetworkReply::NetworkError) > (&QNetworkReply::error),
[this](QNetworkReply::NetworkError error)
{
if(error != QNetworkReply::NoError)
{
qDebug() << "出错了:" << reply->errorString();
}
});
connect(reply, &QNetworkReply::finished, mgr, &QNetworkAccessManager::deleteLater);
connect(reply, &QNetworkReply::readyRead, this, &DownloadWorker::dataReady);
connect(reply, &QNetworkReply::finished, this, &DownloadWorker::slotFinish);
connect(reply, &QNetworkReply::downloadProgress, this, &DownloadWorker::handleProcess);
// connect(reply, &QNetworkReply::finished, reply, &QNetworkReply::deleteLater);
connect(reply, &QNetworkReply::finished, this, &DownloadWorker::doStop);
}
void DownloadWorker::doStop()
{
if (reply) {
reply->disconnect();
reply->aboutToClose();
reply->deleteLater();
reply = nullptr;
}
}
void DownloadWorker::dataReady()
{
QByteArray data = reply->readAll();
file->seek(startPos + receivedPos);
file->write(data);
receivedPos += data.size();
}
void DownloadWorker::slotFinish()
{
file->flush();
qDebug() << "数据块下载完毕:" << QString(" %1~%2 -> writePos Start %3").arg(startPos).arg(endPos).arg(receivedPos);
emit workFinished();
}
void DownloadWorker::handleProcess(qint64, qint64)
{
emit this->downloadProcess();
}
DownloadController::DownloadController(QObject *parent)
{
Q_UNUSED(parent)
domains = {
"d1.store.deepinos.org.cn",
"d2.store.deepinos.org.cn",
"d3.store.deepinos.org.cn",
"d4.store.deepinos.org.cn",
"d5.store.deepinos.org.cn"
};
this->threadNum = domains.size() > 5 ? 5 : domains.size();
}
DownloadController::~DownloadController()
{
if(workers.size() > 0)
{
for(int i = 0; i < workers.size(); i++)
{
workers.at(i)->doStop();
workers.at(i)->disconnect();
workers.at(i)->deleteLater();
}
workers.clear();
}
}
void DownloadController::setFilename(QString filename)
{
this->filename = filename;
}
void DownloadController::setThreadNum(int threadNum)
{
this->threadNum = threadNum;
}
/**
* @brief 开始下载
*/
void DownloadController::startDownload(const QString &url)
{
finish = 0;
// 下载任务等分,计算每个线程的下载数据
fileSize = getFileSize(url);
if(fileSize == 0)
{
emit errorOccur("文件大小获取失败");
return;
}
qint64 segmentSize = fileSize / threadNum;
ranges.resize(threadNum);
QVector<qint64> receivedBytes;
receivedBytes.resize(threadNum);
for(int i = 0; i < threadNum; i++)
{
ranges[i].first = i * segmentSize;
ranges[i].second = i * segmentSize + segmentSize - 1;
receivedBytes[i] = 0;
}
ranges[threadNum - 1].second = fileSize; // 余数部分加入最后一个
// 打开文件
QDir tmpdir("/tmp/spark-store");
file = new QFile;
file->setFileName(tmpdir.absoluteFilePath(filename));
if(file->exists())
{
file->remove();
}
if(!file->open(QIODevice::WriteOnly))
{
delete file;
file = nullptr;
emit errorOccur(file->errorString());
return;
}
file->resize(fileSize);
// 创建下载线程
workers.clear();
for(int i = 0; i < ranges.size(); i++)
{
qDebug() << QString("第%1个下载请求%2-%3").arg(i).arg(ranges.at(i).first).arg(ranges.at(i).second);
auto worker = new DownloadWorker(this);
auto range = ranges.at(i);
QString chunkUrl = replaceDomain(url, domains.at(i));
worker->setIdentifier(i);
worker->setParamter(chunkUrl, range, file);
workers.append(worker);
connect(worker, &DownloadWorker::downloadProcess, this, &DownloadController::handleProcess);
connect(worker, &DownloadWorker::workFinished, this, &DownloadController::chunkDownloadFinish);
worker->doWork();
}
}
/**
* @brief 停止下载
*/
void DownloadController::stopDownload()
{
for(int i = 0; i < workers.size(); i++)
{
workers.at(i)->doStop();
workers.at(i)->disconnect();
workers.at(i)->deleteLater();
}
workers.clear();
qDebug() << "文件下载路径:" << QFileInfo(file->fileName()).absoluteFilePath();
file->flush();
file->close();
delete file;
file = nullptr;
}
void DownloadController::handleProcess()
{
qint64 bytesReceived = 0;
for(int i = 0; i < workers.size(); i++)
{
bytesReceived += workers.at(i)->getReceivedPos();
}
qDebug() << QString("下载进度 %1-%2").arg(bytesReceived).arg(fileSize);
emit downloadProcess(bytesReceived, fileSize);
}
void DownloadController::chunkDownloadFinish()
{
finish++;
qDebug() << QString("已下载了%1块共%2块").arg(finish).arg(threadNum);
if(finish == threadNum)
{
stopDownload();
emit downloadFinished();
}
}
qint64 DownloadController::getFileSize(const QString& url)
{
QEventLoop event;
QNetworkAccessManager requestManager;
QNetworkRequest request;
request.setUrl(QUrl(url));
request.setAttribute(QNetworkRequest::FollowRedirectsAttribute, true);
QNetworkReply *reply = requestManager.head(request);
connect(reply, static_cast<void(QNetworkReply::*)(QNetworkReply::NetworkError) > (&QNetworkReply::error),
[this, reply](QNetworkReply::NetworkError error)
{
if(error != QNetworkReply::NoError)
{
emit errorOccur(reply->errorString());
}
});
connect(reply, &QNetworkReply::finished, &event, &QEventLoop::quit);
event.exec();
qint64 fileSize = 0;
if(reply->rawHeader("Accept-Ranges") == QByteArrayLiteral("bytes")
&& reply->hasRawHeader(QString("Content-Length").toLocal8Bit()))
{
fileSize = reply->header(QNetworkRequest::ContentLengthHeader).toUInt();
}
qDebug() << "文件大小为:" << fileSize;
reply->deleteLater();
return fileSize;
}
QString DownloadController::replaceDomain(const QString& url, const QString domain)
{
QRegularExpression regex(R"((?:[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?\.)+[a-z0-9][a-z0-9-]{0,61}[a-z0-9])");
if(regex.match(url).hasMatch())
{
return QString(url).replace(regex.match(url).captured(), domain);
}
return url;
}

81
src/downloadworker.h Normal file
View File

@@ -0,0 +1,81 @@
#ifndef DOWNLOADWORKER_H
#define DOWNLOADWORKER_H
#include <QObject>
#include <QList>
#include <QFile>
#include <QNetworkReply>
class DownloadWorker : public QObject
{
Q_OBJECT
public:
explicit DownloadWorker(QObject *parent = nullptr);
void setIdentifier(int identifier);
void setParamter(const QString &url, QPair<qint64, qint64> range, QFile *flle);
qint64 getReceivedPos();
public slots:
void doWork();
void doStop();
void dataReady();
void slotFinish();
void handleProcess(qint64, qint64);
private:
int identifier;
QString url;
qint64 startPos;
qint64 endPos;
qint64 receivedPos = 0;
QNetworkReply *reply;
QNetworkAccessManager *mgr;
QFile *file;
signals:
void resultReady(int identifier, QByteArray data);
void testSignals();
void workFinished();
void downloadProcess();
};
class DownloadController : public QObject
{
Q_OBJECT
public:
explicit DownloadController(QObject *parent = nullptr);
~DownloadController();
void setFilename(QString filename);
void setThreadNum(int threadNum);
void startDownload(const QString &url);
void stopDownload();
qint64 getFileSize(const QString& url);
QString replaceDomain(const QString& url, const QString domain);
private:
int threadNum;
QString filename;
qint64 fileSize;
QVector<QPair<qint64, qint64>> ranges;
QFile *file;
QList<DownloadWorker*> workers;
int finish = 0;
QVector<QString> domains;
public slots:
void handleProcess();
void chunkDownloadFinish();
signals:
void errorOccur(const QString& msg);
void downloadProcess(qint64, qint64);
void downloadFinished();
};
#endif // FILEDOWNLOADWORKER_H

View File

@@ -117,14 +117,14 @@ QLayoutItem *FlowLayout::takeAt(int index)
if (index >= 0 && index < itemList.size())
return itemList.takeAt(index);
else
return 0;
return nullptr;
}
//! [5]
//! [6]
Qt::Orientations FlowLayout::expandingDirections() const
{
return 0;
return nullptr;
}
//! [6]
@@ -215,7 +215,7 @@ int FlowLayout::smartSpacing(QStyle::PixelMetric pm) const
return -1;
} else if (parent->isWidgetType()) {
QWidget *pw = static_cast<QWidget *>(parent);
return pw->style()->pixelMetric(pm, 0, pw);
return pw->style()->pixelMetric(pm, nullptr, pw);
} else {
return static_cast<QLayout *>(parent)->spacing();
}

View File

@@ -60,7 +60,7 @@ class FlowLayout : public QLayout
public:
explicit FlowLayout(QWidget *parent, int margin = -1, int hSpacing = -1, int vSpacing = -1);
explicit FlowLayout(int margin = -1, int hSpacing = -1, int vSpacing = -1);
~FlowLayout();
~FlowLayout() override;
void addItem(QLayoutItem *item) override;
int horizontalSpacing() const;
@@ -85,4 +85,4 @@ private:
};
//! [0]
#endif // FLOWLAYOUT_H
#endif // FLOWLAYOUT_H

View File

@@ -1,16 +1,15 @@
#include "image_show.h"
#include <QHBoxLayout>
#include <QDebug>
#include <QPainter>
#include <DDialog>
#include <DBlurEffectWidget>
#include <DWidgetUtil>
#include <DApplication>
#include <QDesktopWidget>
DWIDGET_USE_NAMESPACE
image_show::image_show(QWidget *parent) : QWidget(parent)
#include <QScreen> // Qt5 不再建议使用 QDesktopWidget
#include <QGuiApplication>
image_show::image_show(QWidget *parent) :
QWidget(parent),
m_dialog(new big_image),
m_label(new QLabel)
{
QHBoxLayout *layout=new QHBoxLayout;
QHBoxLayout *layout = new QHBoxLayout;
layout->addWidget(m_label);
setLayout(layout);
m_label->setText("layout");
@@ -19,17 +18,22 @@ image_show::image_show(QWidget *parent) : QWidget(parent)
void image_show::setImage(QPixmap image)
{
QImage screen0;
screen0=image.toImage();
// QPainter painter(&screen0);
screen0 = image.toImage();
QImage re_screen1;
QImage re_screen0=screen0.scaled(QSize(400,300),Qt::KeepAspectRatio,Qt::SmoothTransformation);
desktop_w=DApplication::desktop()->width();
desktop_h=DApplication::desktop()->height();
if(screen0.width()>(desktop_w-20) || screen0.height()>(desktop_h-20)){
re_screen1=screen0.scaled(QSize(desktop_w-20,desktop_h-20),Qt::KeepAspectRatio,Qt::SmoothTransformation);
m_image=QPixmap::fromImage(re_screen1);
}else {
m_image=image;
QImage re_screen0 = screen0.scaled(QSize(400, 300), Qt::KeepAspectRatio, Qt::SmoothTransformation);
// 获取主屏幕尺寸
desktop_w = QGuiApplication::primaryScreen()->geometry().width();
desktop_h = QGuiApplication::primaryScreen()->geometry().height();
if(screen0.width() > (desktop_w - 20) || screen0.height() > (desktop_h - 20))
{
re_screen1 = screen0.scaled(QSize(desktop_w - 20, desktop_h - 20), Qt::KeepAspectRatio, Qt::SmoothTransformation);
m_image = QPixmap::fromImage(re_screen1);
}
else
{
m_image = image;
}
m_label->setPixmap(QPixmap::fromImage(re_screen0));
@@ -37,10 +41,11 @@ void image_show::setImage(QPixmap image)
void image_show::mousePressEvent(QMouseEvent *)
{
m_dialog->setimage(m_image);
m_dialog->showFullScreen();
m_dialog->setFixedSize(desktop_w,desktop_h);
m_dialog->move(0,0);/*
moveToCenter(m_dialog);*/
m_dialog->setimage(m_image);
m_dialog->showFullScreen();
// 识别主屏幕尺寸并设置 widget 大小
m_dialog->setFixedSize(desktop_w, desktop_h);
m_dialog->move(0,0);
}

View File

@@ -3,30 +3,30 @@
#include <QWidget>
#include <QMouseEvent>
#include <QLabel>
#include <QPixmap>
#include <DDialog>
#include <DBlurEffectWidget>
#include <big_image.h>
DWIDGET_USE_NAMESPACE
#include "big_image.h"
class image_show : public QWidget
{
Q_OBJECT
public:
explicit image_show(QWidget *parent = nullptr);
void setImage(QPixmap);
int desktop_w;
int desktop_h;
private:
QLabel *m_label=new QLabel;
QPixmap m_image;
QLabel image;
big_image *m_dialog=new big_image;
void mousePressEvent(QMouseEvent *event);
signals:
public slots:
void setImage(QPixmap);
protected:
void mousePressEvent(QMouseEvent *event) override;
private:
big_image *m_dialog;
QLabel *m_label;
QLabel image;
QPixmap m_image;
};
#endif // IMAGE_SHOW_H

View File

@@ -1,19 +1,19 @@
#include <DApplication>
#include <DWidgetUtil> //Dtk::Widget::moveToCenter(&w); 要调用它就得引用DWidgetUtil
#include <QDesktopWidget>
#include <widget.h>
#include <QTranslator>
#include <DAboutDialog>
#include "appitem.h"
#include <DApplicationSettings>
#include <DWidgetUtil> // Dtk::Widget::moveToCenter(&w); 要调用它,就得引用 DWidgetUtil
#include <QScreen>
#include "widget.h"
DWIDGET_USE_NAMESPACE
int main(int argc, char *argv[])
{
DApplication::loadDXcbPlugin(); //bar处在标题栏中
DApplication::loadDXcbPlugin(); //bar 处在标题栏中
DApplication a(argc, argv);
a.setAttribute(Qt::AA_UseHighDpiPixmaps);
a.loadTranslator();//载入翻译
a.loadTranslator(); // 载入翻译
/* Customized DAboutDialog (Can't work on other distro like Ubuntu...)
*
@@ -21,7 +21,7 @@ int main(int argc, char *argv[])
* a.setAboutDialog(&dialog);
* dialog.setLicense(QObject::tr("We publish this program under GPL V3"));
* dialog.setVersion(DApplication::buildVersion("Version 2.0.2.5"));
* dialog.setProductIcon(QIcon::fromTheme("spark-store")); //设置Logo
* dialog.setProductIcon(QIcon::fromTheme("spark-store")); // 设置Logo
* dialog.setProductName(QLabel::tr("Spark Store"));
* dialog.setDescription(
* QObject::tr(
@@ -41,7 +41,7 @@ int main(int argc, char *argv[])
a.setOrganizationName("spark-union");
a.setOrganizationDomain("https://www.deepinos.org/");
a.setApplicationName("Spark Store"); //不需要翻译,否则 ~/.local/share/ 下文件夹名称也被翻译为中文
a.setApplicationVersion(DApplication::buildVersion("3.0~alpha2"));
a.setApplicationVersion(DApplication::buildVersion("3.0"));
a.setApplicationAcknowledgementPage("https://gitee.com/deepin-community-store/spark-store");
a.setApplicationDescription(
QObject::tr(
@@ -52,36 +52,49 @@ int main(int argc, char *argv[])
)
);
// 限制单实例运行
if(!a.setSingleInstance("spark-store"))
{
return -1;
}
// 保存窗口主题设置
DApplicationSettings settings;
Widget w;
QDesktopWidget *s=DApplication::desktop();
int d_w=s->width();
int d_h=s->height();
if(d_w<=1366){
QScreen *s = DApplication::primaryScreen();
int d_w = s->geometry().width();
int d_h = s->geometry().height();
if(d_w <= 1366)
{
w.setMinimumWidth(925);
w.resize(925,650);
}else if(d_w<=1920){
w.setMinimumWidth(1180);
w.resize(1180,760);
}else {
}
else
{
w.setMinimumWidth(1180);
w.resize(1180,760);
}
if(d_h<=768){
if(d_h <= 768)
{
w.setMinimumHeight(650);
w.resize(925,650);
}else if(d_h<=1080){
w.setMinimumHeight(760);
w.resize(1180,760);
}else {
}
else
{
w.setMinimumHeight(760);
w.resize(1180,760);
}
QString arg1=argv[1];
if(arg1.left(6)=="spk://"){
QString arg1 = argv[1];
if(arg1.left(6)=="spk://")
{
w.openUrl(QUrl(argv[1]));
}
//让打开时界面显示在正中
// 让打开时界面显示在正中
Dtk::Widget::moveToCenter(&w);
w.show();

View File

@@ -1,37 +1,44 @@
#include "progressload.h"
ProgressLoad::ProgressLoad(QWidget *parent) : QWidget(parent)
#include <DApplicationHelper>
ProgressLoad::ProgressLoad(QWidget *parent) :
QWidget(parent),
m_progess(new QWidget(this)),
timer(new QTimer),
value(0)
{
m_progess=new QWidget(this);
m_progess->move(0,0);
m_progess->show();
timer=new QTimer;
value=0;
timer->setInterval(10);
timer->start();
connect(timer,&QTimer::timeout,[=](){
m_progess->setFixedWidth(width()/100*value);
connect(timer, &QTimer::timeout, [=]()
{
m_progess->setFixedWidth(width() / 100 * value);
m_progess->setFixedHeight(height());
});
}
void ProgressLoad::setValue(int v)
{
value=v;
m_progess->setFixedWidth(width()/100*value);
value = v;
m_progess->setFixedWidth(width() / 100 * value);
}
void ProgressLoad::setTheme(bool dark, QColor color)
{
if(dark){
plt.setColor(QPalette::Background,QColor(28,28,28));
setAutoFillBackground(true);
setPalette(plt);
}else {
plt.setColor(QPalette::Background,QColor(255,255,255));
if(dark)
{
plt.setColor(QPalette::Background, QColor(40, 40, 40));
setAutoFillBackground(true);
setPalette(plt);
}
m_progess->setStyleSheet("background-color:"+color.name());
else
{
plt.setColor(QPalette::Background, QColor(255, 255, 255));
setAutoFillBackground(true);
setPalette(plt);
}
m_progess->setStyleSheet("background-color: " + color.name() + ";");
}

View File

@@ -4,21 +4,23 @@
#include <QWidget>
#include <QTimer>
#include <QPalette>
class ProgressLoad : public QWidget
{
Q_OBJECT
public:
explicit ProgressLoad(QWidget *parent = nullptr);
void setValue(int v);
void setTheme(bool dark,QColor color);
signals:
public slots:
void setValue(int v);
void setTheme(bool dark, QColor color);
private:
QWidget *m_progess;
int value;
QTimer *timer;
int value;
QPalette plt;
};
#endif // PROGRESSLOAD_H

View File

@@ -8,9 +8,6 @@ QT += core gui network concurrent webenginewidgets
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
CONFIG += c++11 link_pkgconfig
PKGCONFIG += dtkwidget glib-2.0 gdk-pixbuf-2.0 libnotify
TARGET = spark-store
TEMPLATE = app
@@ -25,30 +22,42 @@ DEFINES += QT_DEPRECATED_WARNINGS
# You can also select to disable deprecated APIs only up to a certain version of Qt.
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0
SOURCES += main.cpp\
DEFINES += QT_APP_DEBUG
include(../third-party/QtNetworkService/QtNetworkService.pri)
CONFIG += c++11 link_pkgconfig
PKGCONFIG += dtkwidget glib-2.0 gdk-pixbuf-2.0 libnotify
# 禁止输出 qWarning / qDebug 信息
CONFIG(release, debug|release): DEFINES += QT_NO_WARNING_OUTPUT QT_NO_DEBUG_OUTPUT
SOURCES += \
appitem.cpp \
widget.cpp \
downloadlist.cpp \
image_show.cpp \
big_image.cpp \
progressload.cpp \
downloadlist.cpp \
downloadworker.cpp \
flowlayout.cpp \
image_show.cpp \
main.cpp \
progressload.cpp \
widget.cpp \
workerthreads.cpp
HEADERS += \
HEADERS += \
appitem.h \
widget.h \
downloadlist.h \
image_show.h \
big_image.h \
progressload.h \
downloadlist.h \
downloadworker.h \
flowlayout.h \
image_show.h \
progressload.h \
widget.h \
workerthreads.h
FORMS += \
appitem.ui \
widget.ui \
downloadlist.ui
downloadlist.ui \
widget.ui
RESOURCES += \
../assets/icons.qrc
@@ -68,10 +77,7 @@ DISTFILES += \
../assets/tags/logo_icon.svg \
../assets/tags/uos.svg
TRANSLATIONS = ../translations/spark-store_en.ts \
../translations/spark-store_zh_CN.ts
../translations/spark-store_fr.ts\
DEFINES += QT_APP_DEBUG
include(../third-party/QtNetworkService/QtNetworkService.pri)
TRANSLATIONS += \
../translations/spark-store_en.ts \
../translations/spark-store_fr.ts \
../translations/spark-store_zh_CN.ts

File diff suppressed because it is too large Load Diff

View File

@@ -2,11 +2,10 @@
#define WIDGET_H
#include <QWidget>
#include <QUrl>
#include <QFile>
#include <QNetworkReply>
#include <QNetworkAccessManager>
#include <downloadlist.h>
#include <QJsonObject>
#include <QProcess>
#include <QFuture>
@@ -17,44 +16,47 @@
#include <QFontDatabase>
#include <QMutex>
#include <DSettings>
#include <DBlurEffectWidget>
#include <DSpinner>
#include <DWaterProgress>
#include <QLabel>
#include <DTitlebar>
#include <DSearchEdit>
#include <progressload.h>
#include "workerthreads.h"
#include "image_show.h"
#include <DSettings>
#include <DSpinner>
#include <DWaterProgress>
#define LIST_MAX 99 //一次最多下载数量
#include "image_show.h"
#include "downloadlist.h"
#include "progressload.h"
#include "workerthreads.h"
#define LIST_MAX 99 // 一次最多下载数量
#define TMP_PATH "/tmp/spark-store"
DWIDGET_USE_NAMESPACE
namespace Ui {
class Widget;
}
class FlowLayout;
class DownloadController;
namespace AeaQt {
class HttpClient;
class HttpClient;
}
class Widget : public DBlurEffectWidget
{
Q_OBJECT
public:
explicit Widget(DBlurEffectWidget *parent = nullptr);
~Widget();
void startRequest(QUrl url);
void startRequest(QUrl url, QString fileName);
void searchApp(QString);
int nowDownload=0;
int allDownload=0;
int isdownload=false;
int nowDownload = 0;
int allDownload = 0;
int isdownload = false;
void opensetting(); //打开设置页面
void openUrl(QUrl);
void setTheme(bool,QColor);
@@ -101,7 +103,6 @@ private slots:
void on_pushButton_translate_clicked();
public:
QUrl url;
downloadlist download_list[LIST_MAX];
@@ -121,7 +122,6 @@ public:
private:
void initUI();
void initConfig();
int loadappinfo(QUrl);
void chooseLeftMenu(int index);
void setfoot(int);
void updatefoot();
@@ -133,14 +133,15 @@ private:
QPushButton * left_list[15];
QUrl menuUrl[13];
ProgressLoad *m_loadweb;
QLabel *m_loaderror=new QLabel;
QLabel *m_loaderror = new QLabel;
QString serverUrl;
bool configCanSave=false;
bool isBusy=false;
int nowMenu=0; //定位当前菜单
long download_size=0;
long size1=0;
long size2=0;
bool configCanSave = false;
bool isBusy = false;
int nowMenu = 0; // 定位当前菜单
int prePage = 0; // 定位前一个页面
long download_size = 0;
long size1 = 0;
long size2 = 0;
QPixmap screen[5];
QFuture<void> load;
QFutureWatcher<void> watchScreenshotLoad;
@@ -148,8 +149,9 @@ private:
QString type_name;
QColor main_color;
int foot;
DSearchEdit *searchEdit=new DSearchEdit;
DSearchEdit *searchEdit = new DSearchEdit;
DTitlebar *titlebar;
DSpinner *spinner = new DSpinner;
int count = 0; // 记录当前搜索列表下载图标完成的个数
QMutex mutex; // 禁止多次搜索事件同时发生
@@ -159,6 +161,8 @@ private:
AeaQt::HttpClient *httpClient;
FlowLayout *applist_grid;
QHBoxLayout *main;
DownloadController *downloadController;
};
#endif // WIDGET_H

View File

@@ -365,11 +365,11 @@
<number>0</number>
</property>
<item>
<widget class="QWebEngineView" name="webEngineView" native="true">
<widget class="QWebEngineView" name="webEngineView">
<property name="contextMenuPolicy">
<enum>Qt::DefaultContextMenu</enum>
</property>
<property name="url" stdset="0">
<property name="url">
<url>
<string>about:blank</string>
</url>
@@ -489,8 +489,8 @@
<rect>
<x>0</x>
<y>0</y>
<width>889</width>
<height>854</height>
<width>582</width>
<height>849</height>
</rect>
</property>
<layout class="QVBoxLayout" name="verticalLayout_17">
@@ -984,8 +984,8 @@
<rect>
<x>0</x>
<y>0</y>
<width>851</width>
<height>323</height>
<width>98</width>
<height>28</height>
</rect>
</property>
<layout class="QHBoxLayout" name="horizontalLayout_4">
@@ -1114,8 +1114,8 @@
<rect>
<x>0</x>
<y>0</y>
<width>889</width>
<height>858</height>
<width>738</width>
<height>886</height>
</rect>
</property>
<layout class="QVBoxLayout" name="verticalLayout_23">

View File

@@ -1,121 +1,153 @@
#include "workerthreads.h"
#include <QProcess>
#include <QDir>
#include <QFile>
#include <QJsonDocument>
#include "workerthreads.h"
#include "widget.h"
#include "HttpClient.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");
httpClient = new AeaQt::HttpClient;
get_json.start("curl -o app.json " + targetUrl.toString());
if(waitDownload(get_json) == -1)
return;
if(get_json.exitCode())
httpClient->get(targetUrl.toString())
.header("content-type", "application/json")
.onResponse([this](QByteArray json_array)
{
Widget::sendNotification(tr("Failed to download app info. Please check internet connection."));
}
qDebug() << "请求应用信息 " << json_array;
QString urladdress, deatils, more, packagename, appweb;
bool isInstalled;
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("/");
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);
deburl = deburl.left(urladdress.length() - 1);
urladdress = "https://img.jerrywang.top/"; // 使用图片专用服务器请保留这行,删除后将使用源服务器
urladdress = urladdress.left(urladdress.length() - 1);
for (int i=3;i<downloadurl.size();i++) {
urladdress+="/"+downloadurl[i];
deburl+="/"+downloadurl[i];
for(int i = 3; i < downloadurl.size(); i++)
{
urladdress += "/" + downloadurl[i];
deburl += "/" + downloadurl[i];
}
// 路径转化完成
QJsonObject json= QJsonDocument::fromJson(json_array).object();
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("PkgName: ") + json["Pkgname"].toString() + "\n";
details += tr("Version: ") + json["Version"].toString() + "\n";
if(!json["Author"].toString().trimmed().isEmpty())
{
details += tr("Author: ") + json["Author"].toString() + "\n";
}
if(json["Website"].toString() != "" && json["Website"].toString() != " "){
if(!json["Website"].toString().trimmed().isEmpty())
{
details += tr("Official Site: ") + json["Website"].toString() + "\n";
//ui->pushButton_website->show(); move to setinfo slot
appweb=json["Website"].toString();
// 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";
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.start("dpkg -s " + json["Pkgname"].toString());
isInstall.waitForFinished();
int error=QString::fromStdString(isInstall.readAllStandardError().toStdString()).length();
if(error==0)
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(";");
// 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");
httpClient->get(urladdress+"icon.png")
.onResponse([this](QByteArray imgData)
{
QPixmap appicon;
appicon.loadFromData(imgData);
emit finishedIconLoad(&appicon);
}
else
})
.onError([this](QString errorStr)
{
Q_UNUSED(this)
Q_UNUSED(errorStr)
Widget::sendNotification(tr("Failed to load application icon."));
})
.block()
.timeout(5 * 100)
.exec();
// 截图展示加载
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;
}
for(int i = 0; i < 5; i++)
{
httpClient->get(urladdress + "screen_" + QString::number(i + 1) + ".png")
.onResponse([this, i, &screenshotCache](QByteArray imgData)
{
bool s = screenshotCache[i].loadFromData(imgData);
if(s)
{
emit finishedScreenshotLoad(&screenshotCache[i], i);
}
else
{
emit finishedScreenshotLoad(nullptr, i);
}
})
.onError([this](QString errorStr)
{
Q_UNUSED(this)
Q_UNUSED(errorStr)
qDebug() << "截图下载失败";
// Widget::sendNotification(tr("Failed to load application screenshot."));
})
.block()
.timeout(4 * 100)
.exec();
}
emit finishAllLoading();
}
httpClient->deleteLater();
})
.onError([](QString errorStr)
{
Q_UNUSED(errorStr)
Widget::sendNotification(tr("Failed to download app info. Please check internet connection."));
})
.timeout(5 * 100)
.block()
.exec();
}
void SpkAppInfoLoaderThread::setUrl(const QUrl &url)
{
targetUrl = url;
@@ -128,8 +160,9 @@ void SpkAppInfoLoaderThread::setServer(const QString &server)
void SpkAppInfoLoaderThread::downloadFinished(int exitcode, QProcess::ExitStatus status)
{
Q_UNUSED(exitcode);
Q_UNUSED(status);
Q_UNUSED(exitcode)
Q_UNUSED(status)
qDebug() << "Finish one download";
finishedDownload = true;
}
@@ -139,7 +172,10 @@ int SpkAppInfoLoaderThread::waitDownload(QProcess& downloader)
while(!downloader.waitForFinished(100))
{
if(downloader.state() == QProcess::NotRunning)
{
return -1;
}
if(this->isInterruptionRequested())
{
downloader.terminate();

View File

@@ -6,16 +6,35 @@
#include <QUrl>
#include <QProcess>
namespace AeaQt {
class HttpClient;
}
class SpkAppInfoLoaderThread Q_DECL_FINAL : public QThread
{
Q_OBJECT
public:
//explicit SpkAppInfoLoaderThread() = default;
// explicit SpkAppInfoLoaderThread() = default;
protected:
void run() Q_DECL_OVERRIDE;
private:
QUrl targetUrl;
QString serverUrl;
bool finishedDownload = false;
int downloaderRetval = 0;
AeaQt::HttpClient *httpClient;
int waitDownload(QProcess& downloader);
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);
@@ -23,14 +42,9 @@ signals:
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;
void finishedScreenshotLoad(QPixmap *icon, int index); // 该信号必须以 BlockingQueued 方式连接
void finishAllLoading(); // 该信号必须以 BlockingQueued 方式连接
};
#endif // WORKERTHREADS_H

Binary file not shown.

View File

@@ -28,47 +28,47 @@
<context>
<name>SpkAppInfoLoaderThread</name>
<message>
<location filename="../src/workerthreads.cpp" line="25"/>
<location filename="../src/workerthreads.cpp" line="117"/>
<source>Failed to download app info. Please check internet connection.</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../src/workerthreads.cpp" line="53"/>
<location filename="../src/workerthreads.cpp" line="44"/>
<source>PkgName: </source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../src/workerthreads.cpp" line="54"/>
<location filename="../src/workerthreads.cpp" line="45"/>
<source>Version: </source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../src/workerthreads.cpp" line="56"/>
<location filename="../src/workerthreads.cpp" line="47"/>
<source>Author: </source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../src/workerthreads.cpp" line="60"/>
<location filename="../src/workerthreads.cpp" line="51"/>
<source>Official Site: </source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../src/workerthreads.cpp" line="64"/>
<location filename="../src/workerthreads.cpp" line="55"/>
<source>Contributor: </source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../src/workerthreads.cpp" line="65"/>
<location filename="../src/workerthreads.cpp" line="56"/>
<source>Update Time: </source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../src/workerthreads.cpp" line="66"/>
<location filename="../src/workerthreads.cpp" line="57"/>
<source>Installed Size: </source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../src/workerthreads.cpp" line="95"/>
<location filename="../src/workerthreads.cpp" line="85"/>
<source>Failed to load application icon.</source>
<translation type="unfinished"></translation>
</message>
@@ -127,8 +127,7 @@
</message>
<message>
<location filename="../src/widget.ui" line="547"/>
<location filename="../src/widget.cpp" line="602"/>
<location filename="../src/widget.cpp" line="901"/>
<location filename="../src/widget.cpp" line="772"/>
<source>Install</source>
<translation type="unfinished"></translation>
</message>
@@ -411,128 +410,82 @@
<translation type="unfinished">0B</translation>
</message>
<message>
<location filename="../src/widget.cpp" line="165"/>
<location filename="../src/widget.cpp" line="172"/>
<source>Spark Store</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../src/widget.cpp" line="166"/>
<location filename="../src/widget.cpp" line="173"/>
<source>Search or enter spk://</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../src/widget.cpp" line="172"/>
<location filename="../src/widget.cpp" line="179"/>
<source>Submit App</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../src/widget.cpp" line="173"/>
<location filename="../src/widget.cpp" line="180"/>
<source>Settings</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../src/widget.cpp" line="275"/>
<location filename="../src/widget.cpp" line="295"/>
<source>Not Exist</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../src/widget.cpp" line="121"/>
<location filename="../src/widget.cpp" line="329"/>
<location filename="../src/widget.cpp" line="333"/>
<location filename="../src/widget.cpp" line="342"/>
<location filename="../src/widget.cpp" line="346"/>
<location filename="../src/widget.cpp" line="127"/>
<location filename="../src/widget.cpp" line="349"/>
<location filename="../src/widget.cpp" line="353"/>
<location filename="../src/widget.cpp" line="362"/>
<location filename="../src/widget.cpp" line="366"/>
<source>Spark\ Store</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../src/widget.cpp" line="546"/>
<source>Failed to download app info. Please check internet connection.</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../src/widget.cpp" line="576"/>
<source>PkgName: </source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../src/widget.cpp" line="577"/>
<source>Version: </source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../src/widget.cpp" line="579"/>
<source>Author: </source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../src/widget.cpp" line="583"/>
<source>Official Site: </source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../src/widget.cpp" line="587"/>
<source>Contributor: </source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../src/widget.cpp" line="588"/>
<source>Update Time: </source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../src/widget.cpp" line="589"/>
<source>Installed Size: </source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../src/widget.cpp" line="598"/>
<location filename="../src/widget.cpp" line="709"/>
<location filename="../src/widget.cpp" line="898"/>
<location filename="../src/widget.cpp" line="563"/>
<location filename="../src/widget.cpp" line="769"/>
<source>Reinstall</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../src/widget.cpp" line="637"/>
<source>Failed to load application icon.</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../src/widget.cpp" line="684"/>
<location filename="../src/widget.cpp" line="536"/>
<source>Failed to get the name to the file to be downloaded.</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../src/widget.cpp" line="1047"/>
<location filename="../src/widget.cpp" line="919"/>
<source>Updating, please wait...</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../src/widget.cpp" line="1100"/>
<location filename="../src/widget.cpp" line="972"/>
<source>Apt has reported an error. Please use apt update in terminal to locate the problem.</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../src/widget.cpp" line="1106"/>
<location filename="../src/widget.cpp" line="978"/>
<source>Unknown error!</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../src/widget.cpp" line="1289"/>
<location filename="../src/widget.cpp" line="1164"/>
<source>Yes</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../src/widget.cpp" line="1289"/>
<location filename="../src/widget.cpp" line="1164"/>
<source>No</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../src/widget.cpp" line="1290"/>
<location filename="../src/widget.cpp" line="1165"/>
<source>Information for Contributors</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../src/widget.cpp" line="1291"/>
<location filename="../src/widget.cpp" line="1166"/>
<source>Currently the translation contribution is limited to English,
and you will be redirected to our Gitee repository at which you are
supposed to be creating pull requests to contribute app info
@@ -543,27 +496,27 @@ Click yes to continue.</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../src/widget.cpp" line="1126"/>
<location filename="../src/widget.cpp" line="998"/>
<source>Uninstall succeeded</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../src/widget.cpp" line="749"/>
<location filename="../src/widget.cpp" line="607"/>
<source>Relative apps Not Found!</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../src/widget.cpp" line="757"/>
<location filename="../src/widget.cpp" line="615"/>
<source>Request Error: %1</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../src/widget.cpp" line="1140"/>
<location filename="../src/widget.cpp" line="1012"/>
<source>Temporary cache was cleaned</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../src/widget.cpp" line="1208"/>
<location filename="../src/widget.cpp" line="1081"/>
<source>The URL has been copied to the clipboard</source>
<translation type="unfinished"></translation>
</message>

Binary file not shown.

View File

@@ -48,47 +48,47 @@
<context>
<name>SpkAppInfoLoaderThread</name>
<message>
<location filename="../src/workerthreads.cpp" line="25"/>
<location filename="../src/workerthreads.cpp" line="117"/>
<source>Failed to download app info. Please check internet connection.</source>
<translation></translation>
</message>
<message>
<location filename="../src/workerthreads.cpp" line="53"/>
<location filename="../src/workerthreads.cpp" line="44"/>
<source>PkgName: </source>
<translation> </translation>
</message>
<message>
<location filename="../src/workerthreads.cpp" line="54"/>
<location filename="../src/workerthreads.cpp" line="45"/>
<source>Version: </source>
<translation> </translation>
</message>
<message>
<location filename="../src/workerthreads.cpp" line="56"/>
<location filename="../src/workerthreads.cpp" line="47"/>
<source>Author: </source>
<translation> </translation>
</message>
<message>
<location filename="../src/workerthreads.cpp" line="60"/>
<location filename="../src/workerthreads.cpp" line="51"/>
<source>Official Site: </source>
<translation> </translation>
</message>
<message>
<location filename="../src/workerthreads.cpp" line="64"/>
<location filename="../src/workerthreads.cpp" line="55"/>
<source>Contributor: </source>
<translation>稿 </translation>
</message>
<message>
<location filename="../src/workerthreads.cpp" line="65"/>
<location filename="../src/workerthreads.cpp" line="56"/>
<source>Update Time: </source>
<translation> </translation>
</message>
<message>
<location filename="../src/workerthreads.cpp" line="66"/>
<location filename="../src/workerthreads.cpp" line="57"/>
<source>Installed Size: </source>
<translation> </translation>
</message>
<message>
<location filename="../src/workerthreads.cpp" line="95"/>
<location filename="../src/workerthreads.cpp" line="85"/>
<source>Failed to load application icon.</source>
<translation></translation>
</message>
@@ -190,8 +190,7 @@
</message>
<message>
<location filename="../src/widget.ui" line="547"/>
<location filename="../src/widget.cpp" line="602"/>
<location filename="../src/widget.cpp" line="901"/>
<location filename="../src/widget.cpp" line="772"/>
<source>Install</source>
<translation></translation>
</message>
@@ -471,103 +470,93 @@
<translation></translation>
</message>
<message>
<location filename="../src/widget.cpp" line="165"/>
<location filename="../src/widget.cpp" line="172"/>
<source>Spark Store</source>
<translation>Spark </translation>
</message>
<message>
<location filename="../src/widget.cpp" line="166"/>
<location filename="../src/widget.cpp" line="173"/>
<source>Search or enter spk://</source>
<translation></translation>
</message>
<message>
<location filename="../src/widget.cpp" line="172"/>
<location filename="../src/widget.cpp" line="179"/>
<source>Submit App</source>
<translation></translation>
</message>
<message>
<location filename="../src/widget.cpp" line="173"/>
<location filename="../src/widget.cpp" line="180"/>
<source>Settings</source>
<translation></translation>
</message>
<message>
<location filename="../src/widget.cpp" line="275"/>
<location filename="../src/widget.cpp" line="295"/>
<source>Not Exist</source>
<translation></translation>
</message>
<message>
<location filename="../src/widget.cpp" line="121"/>
<location filename="../src/widget.cpp" line="329"/>
<location filename="../src/widget.cpp" line="333"/>
<location filename="../src/widget.cpp" line="342"/>
<location filename="../src/widget.cpp" line="346"/>
<location filename="../src/widget.cpp" line="127"/>
<location filename="../src/widget.cpp" line="349"/>
<location filename="../src/widget.cpp" line="353"/>
<location filename="../src/widget.cpp" line="362"/>
<location filename="../src/widget.cpp" line="366"/>
<source>Spark\ Store</source>
<translation></translation>
</message>
<message>
<location filename="../src/widget.cpp" line="546"/>
<source>Failed to download app info. Please check internet connection.</source>
<translation></translation>
<translation type="vanished"></translation>
</message>
<message>
<location filename="../src/widget.cpp" line="576"/>
<source>PkgName: </source>
<translation> </translation>
<translation type="vanished"> </translation>
</message>
<message>
<location filename="../src/widget.cpp" line="577"/>
<source>Version: </source>
<translation> </translation>
<translation type="vanished"> </translation>
</message>
<message>
<location filename="../src/widget.cpp" line="579"/>
<source>Author: </source>
<translation> </translation>
<translation type="vanished"> </translation>
</message>
<message>
<location filename="../src/widget.cpp" line="583"/>
<source>Official Site: </source>
<translation> </translation>
<translation type="vanished"> </translation>
</message>
<message>
<location filename="../src/widget.cpp" line="587"/>
<source>Contributor: </source>
<translation>稿 </translation>
<translation type="vanished">稿 </translation>
</message>
<message>
<location filename="../src/widget.cpp" line="588"/>
<source>Update Time: </source>
<translation> </translation>
<translation type="vanished"> </translation>
</message>
<message>
<location filename="../src/widget.cpp" line="589"/>
<source>Installed Size: </source>
<translation> </translation>
<translation type="vanished"> </translation>
</message>
<message>
<location filename="../src/widget.cpp" line="598"/>
<location filename="../src/widget.cpp" line="709"/>
<location filename="../src/widget.cpp" line="898"/>
<location filename="../src/widget.cpp" line="563"/>
<location filename="../src/widget.cpp" line="769"/>
<source>Reinstall</source>
<translation></translation>
</message>
<message>
<location filename="../src/widget.cpp" line="637"/>
<source>Failed to load application icon.</source>
<translation></translation>
<translation type="vanished"></translation>
</message>
<message>
<location filename="../src/widget.cpp" line="684"/>
<location filename="../src/widget.cpp" line="536"/>
<source>Failed to get the name to the file to be downloaded.</source>
<translation></translation>
</message>
<message>
<location filename="../src/widget.cpp" line="749"/>
<location filename="../src/widget.cpp" line="607"/>
<source>Relative apps Not Found!</source>
<translation></translation>
</message>
<message>
<location filename="../src/widget.cpp" line="757"/>
<location filename="../src/widget.cpp" line="615"/>
<source>Request Error: %1</source>
<translation>%1</translation>
</message>
@@ -576,37 +565,37 @@
<translation type="vanished"></translation>
</message>
<message>
<location filename="../src/widget.cpp" line="1047"/>
<location filename="../src/widget.cpp" line="919"/>
<source>Updating, please wait...</source>
<translation></translation>
</message>
<message>
<location filename="../src/widget.cpp" line="1100"/>
<location filename="../src/widget.cpp" line="972"/>
<source>Apt has reported an error. Please use apt update in terminal to locate the problem.</source>
<translation>使apt update来查看错误原因</translation>
</message>
<message>
<location filename="../src/widget.cpp" line="1106"/>
<location filename="../src/widget.cpp" line="978"/>
<source>Unknown error!</source>
<translation></translation>
</message>
<message>
<location filename="../src/widget.cpp" line="1289"/>
<location filename="../src/widget.cpp" line="1164"/>
<source>Yes</source>
<translation></translation>
</message>
<message>
<location filename="../src/widget.cpp" line="1289"/>
<location filename="../src/widget.cpp" line="1164"/>
<source>No</source>
<translation></translation>
</message>
<message>
<location filename="../src/widget.cpp" line="1290"/>
<location filename="../src/widget.cpp" line="1165"/>
<source>Information for Contributors</source>
<translation></translation>
</message>
<message>
<location filename="../src/widget.cpp" line="1291"/>
<location filename="../src/widget.cpp" line="1166"/>
<source>Currently the translation contribution is limited to English,
and you will be redirected to our Gitee repository at which you are
supposed to be creating pull requests to contribute app info
@@ -642,17 +631,17 @@ Click yes to continue.</source>
<translation type="vanished"></translation>
</message>
<message>
<location filename="../src/widget.cpp" line="1126"/>
<location filename="../src/widget.cpp" line="998"/>
<source>Uninstall succeeded</source>
<translation></translation>
</message>
<message>
<location filename="../src/widget.cpp" line="1140"/>
<location filename="../src/widget.cpp" line="1012"/>
<source>Temporary cache was cleaned</source>
<translation></translation>
</message>
<message>
<location filename="../src/widget.cpp" line="1208"/>
<location filename="../src/widget.cpp" line="1081"/>
<source>The URL has been copied to the clipboard</source>
<translation></translation>
</message>