!17 多线程下载合并
* Update README.md * Improve Features * 修改获取线路的域名 * 修改默认源 * 修改多线程下载域名和图片服务器 * 修正取消下载的闪退问题 * 将图片下载由 curl 转为 QtNetworkService * 切换多域名下载,提高下载速度 * 完成并发请求下载
This commit is contained in:
parent
1a4b1176fb
commit
f7ced7739c
|
@ -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规则)
|
||||
|
|
|
@ -4,4 +4,4 @@ CONFIG += ordered
|
|||
SUBDIRS = third-party/QtNetworkService \
|
||||
src/spark-store.pro
|
||||
|
||||
spark-store.depends = third-party/QtNetworkService
|
||||
spark-store.depends = third-party/QtNetworkService
|
||||
|
|
|
@ -0,0 +1,259 @@
|
|||
#include "downloadworker.h"
|
||||
#include <QIODevice>
|
||||
#include <QEventLoop>
|
||||
#include <QNetworkAccessManager>
|
||||
#include <QNetworkRequest>
|
||||
#include <QNetworkReply>
|
||||
#include <QDebug>
|
||||
#include <QThread>
|
||||
#include <QRegularExpression>
|
||||
#include <QFileInfo>
|
||||
#include <QDir>
|
||||
|
||||
DownloadWorker::DownloadWorker(QObject *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)
|
||||
{
|
||||
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() > 4 ? 4 : 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;
|
||||
}
|
||||
|
|
@ -0,0 +1,75 @@
|
|||
#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);
|
||||
|
||||
signals:
|
||||
void resultReady(int identifier, QByteArray data);
|
||||
void testSignals();
|
||||
void workFinished();
|
||||
void downloadProcess();
|
||||
|
||||
private:
|
||||
int identifier;
|
||||
QString url;
|
||||
qint64 startPos;
|
||||
qint64 endPos;
|
||||
qint64 receivedPos = 0;
|
||||
QNetworkReply *reply;
|
||||
QNetworkAccessManager *mgr;
|
||||
QFile *file;
|
||||
};
|
||||
|
||||
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);
|
||||
|
||||
public slots:
|
||||
void handleProcess();
|
||||
void chunkDownloadFinish();
|
||||
|
||||
signals:
|
||||
void errorOccur(const QString& msg);
|
||||
void downloadProcess(qint64, qint64);
|
||||
void downloadFinished();
|
||||
|
||||
private:
|
||||
int threadNum;
|
||||
QString filename;
|
||||
qint64 fileSize;
|
||||
QVector<QPair<qint64, qint64>> ranges;
|
||||
QFile *file;
|
||||
QList<DownloadWorker*> workers;
|
||||
int finish = 0;
|
||||
QVector<QString> domains;
|
||||
};
|
||||
|
||||
#endif // FILEDOWNLOADWORKER_H
|
|
@ -25,8 +25,12 @@ 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
|
||||
|
||||
# 禁止输出 qWarning / qDebug 信息
|
||||
CONFIG(release, debug|release): DEFINES += QT_NO_WARNING_OUTPUT QT_NO_DEBUG_OUTPUT
|
||||
|
||||
SOURCES += main.cpp\
|
||||
appitem.cpp \
|
||||
downloadworker.cpp \
|
||||
widget.cpp \
|
||||
downloadlist.cpp \
|
||||
image_show.cpp \
|
||||
|
@ -37,6 +41,7 @@ SOURCES += main.cpp\
|
|||
|
||||
HEADERS += \
|
||||
appitem.h \
|
||||
downloadworker.h \
|
||||
widget.h \
|
||||
downloadlist.h \
|
||||
image_show.h \
|
||||
|
|
248
src/widget.cpp
248
src/widget.cpp
|
@ -33,6 +33,7 @@
|
|||
#include "HttpClient.h"
|
||||
#include "appitem.h"
|
||||
#include "flowlayout.h"
|
||||
#include "downloadworker.h"
|
||||
|
||||
DWIDGET_USE_NAMESPACE
|
||||
|
||||
|
@ -48,6 +49,8 @@ Widget::Widget(DBlurEffectWidget *parent) :
|
|||
m_loadweb->show();
|
||||
|
||||
httpClient = new AeaQt::HttpClient;
|
||||
// 并发下载
|
||||
downloadController = new DownloadController(this);
|
||||
|
||||
connect(ui->menu_main,&QPushButton::clicked,[=](){Widget::chooseLeftMenu(0);});
|
||||
connect(ui->menu_network,&QPushButton::clicked,[=](){Widget::chooseLeftMenu(1);});
|
||||
|
@ -72,6 +75,7 @@ Widget::Widget(DBlurEffectWidget *parent) :
|
|||
connect(&appinfoLoadThread, &SpkAppInfoLoaderThread::finishedScreenshotLoad, this, &Widget::sltAppinfoScreenshot, Qt::ConnectionType::BlockingQueuedConnection);
|
||||
connect(&appinfoLoadThread, &SpkAppInfoLoaderThread::finishAllLoading, this, &Widget::sltAppinfoFinish, Qt::ConnectionType::BlockingQueuedConnection);
|
||||
|
||||
|
||||
// 搜索事件
|
||||
connect(searchEdit, &DSearchEdit::returnPressed, this, [=]()
|
||||
{
|
||||
|
@ -127,6 +131,7 @@ Widget::~Widget()
|
|||
{
|
||||
notify_uninit();
|
||||
|
||||
// delete httpFinished;
|
||||
delete ui;
|
||||
qDebug()<<"exit";
|
||||
DApplication::quit();
|
||||
|
@ -231,8 +236,15 @@ void Widget::initConfig()
|
|||
while (getline(serverList,lineTmp)) {
|
||||
ui->comboBox_server->addItem(QString::fromStdString(lineTmp));
|
||||
}
|
||||
for(int i = 0; i < ui->comboBox_server->count(); i++)
|
||||
{
|
||||
if(ui->comboBox_server->itemText(i) == "开发者模式 Dev only")
|
||||
{
|
||||
ui->comboBox_server->model()->setData(ui->comboBox_server->model()->index(i, 0), QVariant(0), Qt::UserRole - 1);
|
||||
}
|
||||
}
|
||||
}else {
|
||||
ui->comboBox_server->addItem("http://sucdn.jerrywang.top/");
|
||||
ui->comboBox_server->addItem("https://d.store.deepinos.org.cn/");
|
||||
}
|
||||
|
||||
// 读取服务器URL并初始化菜单项的链接
|
||||
|
@ -241,7 +253,7 @@ void Widget::initConfig()
|
|||
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
|
||||
appinfoLoadThread.setServer(serverUrl="https://d.store.deenos.org.cn/"); // 默认URL
|
||||
}
|
||||
configCanSave=true; // 防止触发保存配置信号
|
||||
menuUrl[0]=serverUrl + "store/#/";
|
||||
|
@ -266,8 +278,8 @@ void Widget::initConfig()
|
|||
ui->webfoot->hide();
|
||||
|
||||
//初始化首页
|
||||
ui->webEngineView->setUrl(menuUrl[0]);
|
||||
// ui->webEngineView->setUrl(menuUrl[1]);
|
||||
chooseLeftMenu(0);
|
||||
// ui->webEngineView->setUrl(menuUrl[0]);
|
||||
|
||||
//给下载列表赋值到数组,方便调用
|
||||
for (int i =0; i<LIST_MAX;i++){
|
||||
|
@ -512,174 +524,6 @@ void Widget::updatefoot()
|
|||
ui->webfoot->setFixedHeight(allh-foot);
|
||||
}
|
||||
|
||||
int Widget::loadappinfo(QUrl arg1)
|
||||
{
|
||||
if(arg1.isEmpty()){
|
||||
return 1;
|
||||
}
|
||||
|
||||
// 先隐藏详情页负责显示截图的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();
|
||||
|
||||
QProcess get_json;
|
||||
QDir dir("/tmp");
|
||||
dir.mkdir("spark-store");
|
||||
QDir::setCurrent("/tmp/spark-store");
|
||||
|
||||
get_json.start("curl -o app.json "+arg1.toString());
|
||||
get_json.waitForFinished();
|
||||
if(get_json.exitCode())
|
||||
{
|
||||
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=arg1.toString().left(arg1.toString().length()-8);
|
||||
QStringList downloadurl=urladdress.split("/");
|
||||
urladdress=ui->comboBox_server->currentText();
|
||||
QString deburl=urladdress;
|
||||
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();
|
||||
appName = json["Name"].toString();
|
||||
url=deburl + json["Filename"].toString();
|
||||
qDebug()<<url;
|
||||
ui->label_appname->setText(appName);
|
||||
system("rm -r *.png");
|
||||
ui->label_show->show();
|
||||
// 软件信息加载
|
||||
QString info;
|
||||
info= tr("PkgName: ")+json["Pkgname"].toString()+"\n";
|
||||
info+=tr("Version: ")+json["Version"].toString()+"\n";
|
||||
if(json["Author"].toString()!="" && json["Author"].toString()!=" "){
|
||||
info+=tr("Author: ")+json["Author"].toString()+"\n";
|
||||
}
|
||||
|
||||
if(json["Website"].toString()!="" && json["Website"].toString()!=" "){
|
||||
info+=tr("Official Site: ")+json["Website"].toString()+"\n";
|
||||
ui->pushButton_website->show();
|
||||
appweb=json["Website"].toString();
|
||||
}
|
||||
info+=tr("Contributor: ")+json["Contributor"].toString()+"\n";
|
||||
info+=tr("Update Time: ")+json["Update"].toString()+"\n";
|
||||
info+=tr("Installed Size: ")+json["Size"].toString()+"\n";
|
||||
ui->label_info->setText(info);
|
||||
ui->label_more->setText(json["More"].toString());
|
||||
QProcess isInstall;
|
||||
pkgName=json["Pkgname"].toString();
|
||||
isInstall.start("dpkg -s "+json["Pkgname"].toString());
|
||||
isInstall.waitForFinished();
|
||||
int error=QString::fromStdString(isInstall.readAllStandardError().toStdString()).length();
|
||||
if(error==0){
|
||||
ui->pushButton_download->setText(tr("Reinstall"));
|
||||
ui->pushButton_uninstall->show();
|
||||
|
||||
}else {
|
||||
ui->pushButton_download->setText(tr("Install"));
|
||||
}
|
||||
//tag加载
|
||||
QString tags=json["Tags"].toString();
|
||||
QStringList tagList=tags.split(";");
|
||||
for (int i=0;i<tagList.size();i++) {
|
||||
if(tagList[i]=="community")
|
||||
ui->tag_community->show();
|
||||
if(tagList[i]=="ubuntu")
|
||||
ui->tag_ubuntu->show();
|
||||
if(tagList[i]=="deepin")
|
||||
ui->tag_deepin->show();
|
||||
if(tagList[i]=="uos")
|
||||
ui->tag_uos->show();
|
||||
if(tagList[i]=="dtk5")
|
||||
ui->tag_dtk5->show();
|
||||
if(tagList[i]=="dwine2")
|
||||
ui->tag_dwine2->show();
|
||||
if(tagList[i]=="dwine5")
|
||||
ui->tag_dwine5->show();
|
||||
if(tagList[i]=="a2d")
|
||||
ui->tag_a2d->show();
|
||||
}
|
||||
// 图标加载
|
||||
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);
|
||||
}
|
||||
else
|
||||
sendNotification(tr("Failed to load application icon."));
|
||||
|
||||
|
||||
// 截图展示加载
|
||||
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);
|
||||
get_json.waitForFinished();
|
||||
bool s = screen[i].load("screen_"+QString::number(i+1)+".png");
|
||||
if(s){
|
||||
label_screen[i]->setImage(screen[i]);
|
||||
label_screen[i]->show();
|
||||
/*
|
||||
switch(i){ // 故意为之,为了清除多余截图
|
||||
case 0:
|
||||
label_screen[1]->hide();
|
||||
case 1:
|
||||
label_screen[2]->hide();
|
||||
case 2:
|
||||
label_screen[3]->hide();
|
||||
case 3:
|
||||
label_screen[4]->hide();
|
||||
|
||||
}*/
|
||||
}else{
|
||||
QFile::remove("screen_"+QString::number(i+1)+".png");
|
||||
break;
|
||||
}
|
||||
}
|
||||
ui->label_show->setText("");
|
||||
ui->label_show->hide();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void Widget::on_pushButton_download_clicked()
|
||||
{
|
||||
chooseLeftMenu(13);
|
||||
|
@ -705,31 +549,37 @@ void Widget::on_pushButton_download_clicked()
|
|||
system("cp icon.png icon_"+QString::number(allDownload-1).toUtf8()+".png");
|
||||
download_list[allDownload-1].seticon(icon);
|
||||
if(!isBusy){
|
||||
file = new QFile(fileName);
|
||||
if(!file->open(QIODevice::WriteOnly)){
|
||||
delete file;
|
||||
file = nullptr;
|
||||
return ;
|
||||
}
|
||||
// file = new QFile(fileName);
|
||||
// if(!file->open(QIODevice::WriteOnly)){
|
||||
// delete file;
|
||||
// file = nullptr;
|
||||
// return ;
|
||||
// }
|
||||
|
||||
nowDownload+=1;
|
||||
startRequest(urList.at(nowDownload-1)); // 进行链接请求
|
||||
|
||||
startRequest(urList.at(nowDownload-1), fileName); // 进行链接请求
|
||||
}
|
||||
if(ui->pushButton_download->text()==tr("Reinstall")){
|
||||
download_list[allDownload-1].reinstall=true;
|
||||
}
|
||||
}
|
||||
|
||||
void Widget::startRequest(QUrl url)
|
||||
void Widget::startRequest(QUrl url, QString fileName)
|
||||
{
|
||||
ui->listWidget->show();
|
||||
ui->label->hide();
|
||||
isBusy=true;
|
||||
isdownload=true;
|
||||
download_list[allDownload-1].free=false;
|
||||
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)));
|
||||
|
||||
connect(downloadController, &DownloadController::downloadProcess, this, &Widget::updateDataReadProgress);
|
||||
connect(downloadController, &DownloadController::downloadFinished, this, &Widget::httpFinished);
|
||||
connect(downloadController, &DownloadController::errorOccur, [this](QString msg){
|
||||
this->sendNotification(msg);
|
||||
});
|
||||
downloadController->setFilename(fileName);
|
||||
downloadController->startDownload(url.toString());
|
||||
}
|
||||
|
||||
void Widget::searchApp(QString text)
|
||||
|
@ -846,6 +696,8 @@ void Widget::updateDataReadProgress(qint64 bytesRead, qint64 totalBytes)
|
|||
download_list[nowDownload-1].setValue((bytesRead*10000)/totalBytes); // 当前值
|
||||
download_size=bytesRead;
|
||||
if(download_list[nowDownload-1].close){ // 随时检测下载是否被取消
|
||||
downloadController->disconnect();
|
||||
downloadController->stopDownload();
|
||||
download_list[nowDownload-1].closeDownload();
|
||||
httpFinished();
|
||||
}
|
||||
|
@ -958,12 +810,6 @@ void Widget::sltAppinfoFinish()
|
|||
|
||||
void Widget::httpFinished() // 完成下载
|
||||
{
|
||||
file->flush();
|
||||
file->close();
|
||||
reply->deleteLater();
|
||||
reply = nullptr;
|
||||
delete file;
|
||||
file = nullptr;
|
||||
isdownload=false;
|
||||
isBusy=false;
|
||||
download_list[nowDownload-1].readyInstall();
|
||||
|
@ -974,14 +820,7 @@ void Widget::httpFinished() // 完成下载
|
|||
nowDownload+=1;
|
||||
}
|
||||
QString fileName=download_list[nowDownload-1].getName();
|
||||
file = new QFile(fileName);
|
||||
if(!file->open(QIODevice::WriteOnly))
|
||||
{
|
||||
delete file;
|
||||
file = nullptr;
|
||||
return ;
|
||||
}
|
||||
startRequest(urList.at(nowDownload-1));
|
||||
startRequest(urList.at(nowDownload-1), fileName);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1049,7 +888,7 @@ void Widget::on_pushButton_updateServer_clicked()
|
|||
ui->pushButton_updateServer->setEnabled(false);
|
||||
ui->comboBox_server->clear();
|
||||
QFile::remove(QDir::homePath().toUtf8()+"/.config/spark-store/server.list");
|
||||
system("curl -o "+QDir::homePath().toUtf8()+"/.config/spark-store/server.list http://dcstore.shenmo.tech/store/server.list");
|
||||
system("curl -o "+QDir::homePath().toUtf8()+"/.config/spark-store/server.list https://d.store.deepinos.org.cn/store/server.list");
|
||||
std::fstream server;
|
||||
server.open(QDir::homePath().toUtf8()+"/.config/spark-store/server.list",std::ios::in);
|
||||
std::string lineTmp;
|
||||
|
@ -1058,10 +897,18 @@ void Widget::on_pushButton_updateServer_clicked()
|
|||
ui->comboBox_server->addItem(QString::fromStdString(lineTmp));
|
||||
}
|
||||
}else {
|
||||
ui->comboBox_server->addItem("http://sucdn.jerrywang.top/");
|
||||
ui->comboBox_server->addItem("https://d.store.deepinos.org.cn/");
|
||||
}
|
||||
ui->pushButton_updateServer->setEnabled(true);
|
||||
ui->comboBox_server->setCurrentIndex(0);
|
||||
|
||||
for(int i = 0; i < ui->comboBox_server->count(); i++)
|
||||
{
|
||||
if(ui->comboBox_server->itemText(i) == "开发者模式 Dev only")
|
||||
{
|
||||
ui->comboBox_server->model()->setData(ui->comboBox_server->model()->index(i, 0), QVariant(0), Qt::UserRole - 1);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -1269,6 +1116,7 @@ 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;
|
||||
qDebug()<< "链接地址:" << arg1;
|
||||
/*
|
||||
load.cancel();//打开并发加载线程前关闭正在执行的线程
|
||||
load = QtConcurrent::run([=](){
|
||||
|
|
|
@ -39,6 +39,7 @@ class Widget;
|
|||
|
||||
|
||||
class FlowLayout;
|
||||
class DownloadController;
|
||||
|
||||
namespace AeaQt {
|
||||
class HttpClient;
|
||||
|
@ -51,7 +52,7 @@ class Widget : public DBlurEffectWidget
|
|||
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;
|
||||
|
@ -122,7 +123,6 @@ public:
|
|||
private:
|
||||
void initUI();
|
||||
void initConfig();
|
||||
int loadappinfo(QUrl);
|
||||
void chooseLeftMenu(int index);
|
||||
void setfoot(int);
|
||||
void updatefoot();
|
||||
|
@ -163,6 +163,7 @@ private:
|
|||
AeaQt::HttpClient *httpClient;
|
||||
FlowLayout *applist_grid;
|
||||
QHBoxLayout *main;
|
||||
DownloadController *downloadController;
|
||||
};
|
||||
|
||||
#endif // WIDGET_H
|
||||
|
|
|
@ -5,117 +5,124 @@
|
|||
#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())
|
||||
{
|
||||
Widget::sendNotification(tr("Failed to download app info. Please check internet connection."));
|
||||
}
|
||||
httpClient->get(targetUrl.toString())
|
||||
.header("content-type", "application/json")
|
||||
.onResponse([this](QByteArray json_array) {
|
||||
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);
|
||||
QString deburl = serverUrl;
|
||||
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];
|
||||
}
|
||||
|
||||
// 路径转化完成
|
||||
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;
|
||||
for (int i=3;i<downloadurl.size();i++) {
|
||||
urladdress+="/"+downloadurl[i];
|
||||
deburl+="/"+downloadurl[i];
|
||||
}
|
||||
}
|
||||
emit finishAllLoading();
|
||||
}
|
||||
|
||||
// 路径转化完成
|
||||
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);
|
||||
|
||||
// 图标加载
|
||||
httpClient->get(urladdress+"icon.png")
|
||||
.onResponse([this](QByteArray imgData){
|
||||
QPixmap appicon;
|
||||
appicon.loadFromData(imgData);
|
||||
emit finishedIconLoad(&appicon);
|
||||
})
|
||||
.onError([this](QString errorStr) {
|
||||
Widget::sendNotification(tr("Failed to load application icon."));
|
||||
})
|
||||
.block()
|
||||
.timeout(5 * 100)
|
||||
.exec();
|
||||
|
||||
|
||||
// 截图展示加载
|
||||
QPixmap screenshotCache[5];
|
||||
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) {
|
||||
qDebug() << "截图下载失败";
|
||||
// Widget::sendNotification(tr("Failed to load application screenshot."));
|
||||
})
|
||||
.block()
|
||||
.timeout(4 * 100)
|
||||
.exec();
|
||||
}
|
||||
emit finishAllLoading();
|
||||
|
||||
httpClient->deleteLater();
|
||||
})
|
||||
.onError([](QString 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;
|
||||
|
|
|
@ -6,6 +6,11 @@
|
|||
#include <QUrl>
|
||||
#include <QProcess>
|
||||
|
||||
|
||||
namespace AeaQt {
|
||||
class HttpClient;
|
||||
}
|
||||
|
||||
class SpkAppInfoLoaderThread Q_DECL_FINAL : public QThread
|
||||
{
|
||||
Q_OBJECT
|
||||
|
@ -31,6 +36,8 @@ private:
|
|||
QString serverUrl;
|
||||
bool finishedDownload = false;
|
||||
int downloaderRetval = 0;
|
||||
|
||||
AeaQt::HttpClient *httpClient;
|
||||
};
|
||||
|
||||
#endif // WORKERTHREADS_H
|
||||
|
|
Binary file not shown.
|
@ -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.
|
@ -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>
|
||||
|
|
Loading…
Reference in New Issue