Compare commits
54 Commits
3.0-alpha1
...
3.0.2
| Author | SHA1 | Date | |
|---|---|---|---|
| 0ab9f4dda6 | |||
| 5a97f6caef | |||
| 3da25b0904 | |||
|
|
116c824365 | ||
|
|
44edb08518 | ||
|
|
9a3d32ee11 | ||
|
|
e5fe80cb76 | ||
|
|
9314acd7e1 | ||
|
|
e64e7fcae2 | ||
| 536efeedfa | |||
|
|
6fd3c40e97 | ||
|
|
90513a8925 | ||
|
|
ed3d869b99 | ||
|
|
c80737a458 | ||
|
|
ebf30e67f9 | ||
|
|
90b684af87 | ||
|
|
3ff363d7b1 | ||
|
|
f7ced7739c | ||
|
|
e12f617f59 | ||
|
|
d164aec86d | ||
|
|
96cd1b9918 | ||
|
|
393c8220f5 | ||
|
|
01d1543cc4 | ||
|
|
4ccc8c0dae | ||
|
|
815036e28f | ||
|
|
9cc68fac86 | ||
|
|
2f8c11a30b | ||
| 1a4b1176fb | |||
| 3101f1fe70 | |||
| 58f32c119a | |||
| ccdcf407cc | |||
| 1a18a51d3c | |||
|
|
ab88af006b | ||
|
|
d02900cb10 | ||
|
|
3e473c091a | ||
|
|
84541d0c22 | ||
|
|
51f84bed1b | ||
| 4a0acf0575 | |||
|
|
e28d1c39ac | ||
|
|
f58201a612 | ||
| 405d3b6986 | |||
| b619d3cc7b | |||
|
|
14e3e7f9a2 | ||
|
|
1d0e0cc65c | ||
|
|
7a5b982dea | ||
|
|
91fcab56df | ||
|
|
4315f04023 | ||
|
|
736ede0742 | ||
|
|
a73a4416fc | ||
|
|
6f3e4398df | ||
|
|
3cca0d87fe | ||
|
|
66ef37c1ca | ||
|
|
8972425c7c | ||
|
|
2ae6e80785 |
2
.gitee/Dockerfile
Normal file
@@ -0,0 +1,2 @@
|
||||
FROM python:3
|
||||
RUN pip3 install requests
|
||||
31
.gitee/callback.py
Normal 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)
|
||||
5
.gitignore
vendored
@@ -1,3 +1,4 @@
|
||||
spark-store.pro.user*
|
||||
*.pro.user*
|
||||
build/
|
||||
.vscode/
|
||||
.vscode/
|
||||
Lib/
|
||||
|
||||
33
Jenkinsfile
vendored
Normal 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"
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,4 @@
|
||||
[](https://gitee.com/deepin-community-store/spark-store)
|
||||
# 星火应用商店[](https://gitee.com/deepin-community-store/spark-store/stargazers)
|
||||
# 星火应用商店
|
||||
|
||||
|
||||
众所周知,国内的Linux应用比较少,wine应用难以获取,优质工具分散在民间各大论坛,无法形成合力,难以改善生态
|
||||
@@ -22,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规则)
|
||||
|
||||
@@ -34,18 +34,18 @@
|
||||
<file>icons/refresh-page.svg</file>
|
||||
</qresource>
|
||||
<qresource prefix="/">
|
||||
<file>Logo-Spark.png</file>
|
||||
<file>big_image.cpp</file>
|
||||
<file>big_image.h</file>
|
||||
<file>downloadlist.cpp</file>
|
||||
<file>downloadlist.h</file>
|
||||
<file>image_show.cpp</file>
|
||||
<file>image_show.h</file>
|
||||
<file>main.cpp</file>
|
||||
<file>progressload.cpp</file>
|
||||
<file>progressload.h</file>
|
||||
<file>widget.cpp</file>
|
||||
<file>widget.h</file>
|
||||
<file>../Logo-Spark.png</file>
|
||||
<file>../src/big_image.cpp</file>
|
||||
<file>../src/big_image.h</file>
|
||||
<file>../src/downloadlist.cpp</file>
|
||||
<file>../src/downloadlist.h</file>
|
||||
<file>../src/image_show.cpp</file>
|
||||
<file>../src/image_show.h</file>
|
||||
<file>../src/main.cpp</file>
|
||||
<file>../src/progressload.cpp</file>
|
||||
<file>../src/progressload.h</file>
|
||||
<file>../src/widget.cpp</file>
|
||||
<file>../src/widget.h</file>
|
||||
<file>tags/a2d.png</file>
|
||||
<file>tags/community.svg</file>
|
||||
<file>tags/deepin.svg</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>
|
||||
3
assets/icons/category_active.svg
Normal file
@@ -0,0 +1,3 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
|
||||
<path fill="#536076" d="M10.138807,3.52000025 L10.138,12.5230002 L14.6066017,8.05523757 L15.3137085,8.76234435 L9.65685425,14.4191986 L4,8.76234435 L4.70710678,8.05523757 L9.138,12.4870002 L9.138807,3.52000025 L10.138807,3.52000025 Z" transform="rotate(90 9.657 11.518)"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 366 B |
|
Before Width: | Height: | Size: 3.3 KiB After Width: | Height: | Size: 3.3 KiB |
3
assets/icons/category_active_dark.svg
Normal file
@@ -0,0 +1,3 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
|
||||
<path fill="#536076" d="M10.138807,3.52000025 L10.138,12.5230002 L14.6066017,8.05523757 L15.3137085,8.76234435 L9.65685425,14.4191986 L4,8.76234435 L4.70710678,8.05523757 L9.138,12.4870002 L9.138807,3.52000025 L10.138807,3.52000025 Z" transform="rotate(90 9.657 11.518)"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 366 B |
|
Before Width: | Height: | Size: 3.3 KiB After Width: | Height: | Size: 3.3 KiB |
|
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 1.1 KiB |
|
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 1.1 KiB |
|
Before Width: | Height: | Size: 523 B After Width: | Height: | Size: 523 B |
|
Before Width: | Height: | Size: 553 B After Width: | Height: | Size: 553 B |
|
Before Width: | Height: | Size: 3.3 KiB After Width: | Height: | Size: 3.3 KiB |
|
Before Width: | Height: | Size: 3.3 KiB After Width: | Height: | Size: 3.3 KiB |
|
Before Width: | Height: | Size: 865 B After Width: | Height: | Size: 865 B |
|
Before Width: | Height: | Size: 895 B After Width: | Height: | Size: 895 B |
|
Before Width: | Height: | Size: 929 B After Width: | Height: | Size: 929 B |
|
Before Width: | Height: | Size: 959 B After Width: | Height: | Size: 959 B |
|
Before Width: | Height: | Size: 3.4 KiB After Width: | Height: | Size: 3.4 KiB |
|
Before Width: | Height: | Size: 3.5 KiB After Width: | Height: | Size: 3.5 KiB |
|
Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 1.2 KiB |
|
Before Width: | Height: | Size: 1.3 KiB After Width: | Height: | Size: 1.3 KiB |
|
Before Width: | Height: | Size: 1.3 KiB After Width: | Height: | Size: 1.3 KiB |
|
Before Width: | Height: | Size: 1.3 KiB After Width: | Height: | Size: 1.3 KiB |
|
Before Width: | Height: | Size: 810 B After Width: | Height: | Size: 810 B |
|
Before Width: | Height: | Size: 828 B After Width: | Height: | Size: 828 B |
|
Before Width: | Height: | Size: 2.0 KiB After Width: | Height: | Size: 2.0 KiB |
|
Before Width: | Height: | Size: 2.0 KiB After Width: | Height: | Size: 2.0 KiB |
|
Before Width: | Height: | Size: 1.9 KiB After Width: | Height: | Size: 1.9 KiB |
|
Before Width: | Height: | Size: 1.9 KiB After Width: | Height: | Size: 1.9 KiB |
|
Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 1.2 KiB |
|
Before Width: | Height: | Size: 2.6 KiB After Width: | Height: | Size: 2.6 KiB |
|
Before Width: | Height: | Size: 2.4 KiB After Width: | Height: | Size: 2.4 KiB |
|
Before Width: | Height: | Size: 2.4 KiB After Width: | Height: | Size: 2.4 KiB |
|
Before Width: | Height: | Size: 1.9 KiB After Width: | Height: | Size: 1.9 KiB |
|
Before Width: | Height: | Size: 1.8 KiB After Width: | Height: | Size: 1.8 KiB |
|
Before Width: | Height: | Size: 494 B After Width: | Height: | Size: 494 B |
|
Before Width: | Height: | Size: 1.9 KiB After Width: | Height: | Size: 1.9 KiB |
|
Before Width: | Height: | Size: 16 KiB After Width: | Height: | Size: 16 KiB |
|
Before Width: | Height: | Size: 248 KiB After Width: | Height: | Size: 248 KiB |
|
Before Width: | Height: | Size: 1.6 KiB After Width: | Height: | Size: 1.6 KiB |
|
Before Width: | Height: | Size: 32 KiB After Width: | Height: | Size: 32 KiB |
|
Before Width: | Height: | Size: 13 KiB After Width: | Height: | Size: 13 KiB |
|
Before Width: | Height: | Size: 1.9 KiB After Width: | Height: | Size: 1.9 KiB |
|
Before Width: | Height: | Size: 4.3 KiB After Width: | Height: | Size: 4.3 KiB |
|
Before Width: | Height: | Size: 954 B After Width: | Height: | Size: 954 B |
|
Before Width: | Height: | Size: 5.7 KiB After Width: | Height: | Size: 5.7 KiB |
|
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 1.1 KiB |
|
Before Width: | Height: | Size: 1.7 KiB After Width: | Height: | Size: 1.7 KiB |
|
Before Width: | Height: | Size: 2.0 KiB After Width: | Height: | Size: 2.0 KiB |
|
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 12 KiB |
|
Before Width: | Height: | Size: 83 KiB After Width: | Height: | Size: 83 KiB |
|
Before Width: | Height: | Size: 873 B After Width: | Height: | Size: 873 B |
|
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 1.1 KiB |
13
assets/tags/uos.svg
Normal file
@@ -0,0 +1,13 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 20 20">
|
||||
<defs>
|
||||
<linearGradient id="uos-托盘1-a" x1="15.968%" x2="100%" y1="14.224%" y2="60.554%">
|
||||
<stop offset="0%" stop-color="#0071FF"/>
|
||||
<stop offset="48.72%" stop-color="#00E8FC"/>
|
||||
<stop offset="100%" stop-color="#00A2FF"/>
|
||||
</linearGradient>
|
||||
</defs>
|
||||
<g fill="none" transform="translate(1 1)">
|
||||
<circle cx="9" cy="9" r="9" fill="url(#uos-托盘1-a)"/>
|
||||
<path fill="#FFF" d="M13,4.5 C13.5128358,4.5 13.9355072,4.88604019 13.9932723,5.38337887 L14,5.5 L14,9.5 C14,12.5 12,14.5 9,14.5 C6,14.5 4,12.5 4.0043492,9.70016408 L4,9.5 L4,5.5 C4,4.94771525 4.44771525,4.5 5,4.5 C5.51283584,4.5 5.93550716,4.88604019 5.99327227,5.38337887 L6,5.5 L6,9.5 C6,11.5 7.5,12.5 9,12.5 C10.5,12.5 12,11.5 12,9.5 L12,5.5 C12,4.94771525 12.4477153,4.5 13,4.5 Z"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 873 B |
@@ -1,46 +0,0 @@
|
||||
#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)
|
||||
{
|
||||
QHBoxLayout *layout=new QHBoxLayout;
|
||||
layout->addWidget(m_label);
|
||||
setLayout(layout);
|
||||
m_label->setText("layout");
|
||||
}
|
||||
|
||||
void image_show::setImage(QPixmap image)
|
||||
{
|
||||
QImage screen0;
|
||||
screen0=image.toImage();
|
||||
// QPainter painter(&screen0);
|
||||
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;
|
||||
}
|
||||
|
||||
m_label->setPixmap(QPixmap::fromImage(re_screen0));
|
||||
}
|
||||
|
||||
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);*/
|
||||
|
||||
}
|
||||
@@ -1,37 +0,0 @@
|
||||
#include "progressload.h"
|
||||
|
||||
ProgressLoad::ProgressLoad(QWidget *parent) : QWidget(parent)
|
||||
{
|
||||
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);
|
||||
m_progess->setFixedHeight(height());
|
||||
});
|
||||
}
|
||||
|
||||
void ProgressLoad::setValue(int v)
|
||||
{
|
||||
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));
|
||||
setAutoFillBackground(true);
|
||||
setPalette(plt);
|
||||
}
|
||||
m_progess->setStyleSheet("background-color:"+color.name());
|
||||
}
|
||||
9
spark-store-project.pro
Normal file
@@ -0,0 +1,9 @@
|
||||
TEMPLATE = subdirs
|
||||
|
||||
CONFIG += ordered
|
||||
|
||||
SUBDIRS += \
|
||||
third-party/QtNetworkService \
|
||||
src/spark-store.pro
|
||||
|
||||
spark-store.depends = third-party/QtNetworkService
|
||||
102
src/appitem.cpp
Normal file
@@ -0,0 +1,102 @@
|
||||
#include "appitem.h"
|
||||
#include "ui_appitem.h"
|
||||
#include <QtConcurrent>
|
||||
#include <QNetworkAccessManager>
|
||||
#include <QNetworkReply>
|
||||
#include <QNetworkRequest>
|
||||
#include <QEventLoop>
|
||||
#include <QPainter>
|
||||
#include <QGraphicsDropShadowEffect>
|
||||
|
||||
AppItem::AppItem(QWidget *parent) :
|
||||
QWidget(parent),
|
||||
ui(new Ui::AppItem)
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
AppItem::~AppItem()
|
||||
{
|
||||
delete ui;
|
||||
}
|
||||
|
||||
void AppItem::setTitle(QString title)
|
||||
{
|
||||
m_title = title;
|
||||
ui->lbl_title->setText(title);
|
||||
}
|
||||
|
||||
void AppItem::setDescription(QString description)
|
||||
{
|
||||
m_description = description;
|
||||
QString elidedText = ui->lbl_desc->fontMetrics().elidedText(
|
||||
description, Qt::ElideRight,
|
||||
ui->lbl_desc->width(), Qt::TextShowMnemonic);
|
||||
ui->lbl_desc->setText(elidedText);
|
||||
ui->lbl_desc->setAlignment(Qt::AlignTop);
|
||||
}
|
||||
|
||||
void AppItem::setIcon(QString icon)
|
||||
{
|
||||
m_icon = icon;
|
||||
if(!icon.isEmpty())
|
||||
{
|
||||
downloadIcon(icon);
|
||||
}
|
||||
}
|
||||
|
||||
void AppItem::setUrl(QString url)
|
||||
{
|
||||
m_url = url;
|
||||
}
|
||||
|
||||
void AppItem::mousePressEvent(QMouseEvent *event)
|
||||
{
|
||||
Q_UNUSED(event)
|
||||
|
||||
emit clicked(QUrl(m_url));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 下载图标
|
||||
* @param icon
|
||||
*/
|
||||
void AppItem::downloadIcon(QString icon)
|
||||
{
|
||||
QtConcurrent::run([=]()
|
||||
{
|
||||
auto reqManager = new QNetworkAccessManager();
|
||||
|
||||
QUrl url(icon);
|
||||
QNetworkReply *reply = reqManager->get(QNetworkRequest(url));
|
||||
QEventLoop loop;
|
||||
connect(reply, &QNetworkReply::finished, &loop, &QEventLoop::quit);
|
||||
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();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void AppItem::loadIcon(QPixmap pic)
|
||||
{
|
||||
ui->lbl_icon->setPixmap(pic);
|
||||
}
|
||||
45
src/appitem.h
Normal file
@@ -0,0 +1,45 @@
|
||||
#ifndef APPITEM_H
|
||||
#define APPITEM_H
|
||||
|
||||
#include <QWidget>
|
||||
#include <QUrl>
|
||||
|
||||
namespace Ui {
|
||||
class AppItem;
|
||||
}
|
||||
|
||||
class AppItem : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit AppItem(QWidget *parent = nullptr);
|
||||
~AppItem() override;
|
||||
|
||||
void setTitle(QString title);
|
||||
void setDescription(QString description);
|
||||
void setIcon(QString icon);
|
||||
void setUrl(QString url);
|
||||
|
||||
protected:
|
||||
void mousePressEvent(QMouseEvent *event) override;
|
||||
|
||||
private:
|
||||
Ui::AppItem *ui;
|
||||
|
||||
QString m_title;
|
||||
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
|
||||
160
src/appitem.ui
Normal file
@@ -0,0 +1,160 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>AppItem</class>
|
||||
<widget class="QWidget" name="AppItem">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>333</width>
|
||||
<height>133</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Form</string>
|
||||
</property>
|
||||
<property name="styleSheet">
|
||||
<string notr="true">QWidget#AppItem {
|
||||
width: 300px;
|
||||
height: 100px;
|
||||
margin: 15px;
|
||||
color: #6d6d6d;
|
||||
border-radius: 18px;
|
||||
background-color: width: 300px;
|
||||
height: 100px;
|
||||
margin: 15px;
|
||||
color: #6d6d6d;
|
||||
border-radius: 18px;
|
||||
background-color: #F4F4F6;
|
||||
}
|
||||
|
||||
QWidget#container {
|
||||
background-color: #F4F4F6;
|
||||
}
|
||||
|
||||
QLabel#lbl_icon {
|
||||
background: transparent;
|
||||
border-radius: 10px;
|
||||
}
|
||||
|
||||
QLabel#lbl_title {
|
||||
text-align: left;
|
||||
white-space: nowrap;
|
||||
padding-right: 10px;
|
||||
font-size: 19px;
|
||||
|
||||
}
|
||||
|
||||
QLabel#lbl_desc {
|
||||
text-align: left;
|
||||
font-weight: lighter;
|
||||
white-space: nowrap;
|
||||
font-size: 12px;
|
||||
color: grey;
|
||||
}</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||
<property name="spacing">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QWidget" name="container" native="true">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<property name="spacing">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QLabel" name="lbl_icon">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>100</width>
|
||||
<height>100</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="styleSheet">
|
||||
<string notr="true">width: 78px;
|
||||
height: 70px;
|
||||
padding: 10px;</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
<property name="scaledContents">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<widget class="QLabel" name="lbl_title">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>200</width>
|
||||
<height>50</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>200</width>
|
||||
<height>50</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="lbl_desc">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>200</width>
|
||||
<height>50</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>200</width>
|
||||
<height>50</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
||||
@@ -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();
|
||||
@@ -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
|
||||
@@ -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();
|
||||
@@ -21,25 +29,30 @@ downloadlist::downloadlist(QWidget *parent) :
|
||||
ui->pushButton_3->hide();
|
||||
ui->widget_spinner->start();
|
||||
ui->widget_spinner->hide();
|
||||
action_dpkg->setText(tr("dpkg"));
|
||||
action_gdebi->setText(tr("gdebi"));
|
||||
action_dpkg->setText(tr("Spark Store App Installer"));
|
||||
action_deepin->setText(tr("deepin deb installer"));
|
||||
connect(action_dpkg,&QAction::triggered,[=](){downloadlist::install(1);});
|
||||
connect(action_gdebi,&QAction::triggered,[=](){downloadlist::install(0);});
|
||||
connect(action_deepin,&QAction::triggered,[=](){downloadlist::install(2);});
|
||||
menu_install->addAction(action_gdebi);
|
||||
//ssinstall命令存在时再加入该选项
|
||||
QFile ssinstall("/bin/ssinstall");
|
||||
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("/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);
|
||||
}
|
||||
|
||||
menu_install->addAction(action_gdebi);
|
||||
}
|
||||
|
||||
downloadlist::~downloadlist()
|
||||
@@ -47,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)
|
||||
@@ -73,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 Failed,Check 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)
|
||||
@@ -112,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 gdebi -n /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("pkexec ssinstall /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("deepin-deb-installer /tmp/spark-store/"+ui->label_filename->text().toUtf8());
|
||||
break;
|
||||
}
|
||||
}else {
|
||||
switch (t) {
|
||||
case 0:
|
||||
installer.start("pkexec gdebi -n /tmp/spark-store/"+ui->label_filename->text().toUtf8());
|
||||
break;
|
||||
case 1:
|
||||
installer.start("pkexec ssinstall /tmp/spark-store/"+ui->label_filename->text().toUtf8());
|
||||
break;
|
||||
case 2:
|
||||
installer.start("deepin-deb-installer /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 aborted,you 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();
|
||||
@@ -194,7 +229,7 @@ void downloadlist::install(int t)
|
||||
|
||||
void downloadlist::on_pushButton_install_clicked()
|
||||
{
|
||||
//弹出菜单
|
||||
// 弹出菜单
|
||||
menu_install->exec(cursor().pos());
|
||||
}
|
||||
|
||||
@@ -203,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();
|
||||
}
|
||||
@@ -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
@@ -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
@@ -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
|
||||
223
src/flowlayout.cpp
Normal file
@@ -0,0 +1,223 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2016 The Qt Company Ltd.
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
** This file is part of the examples of the Qt Toolkit.
|
||||
**
|
||||
** $QT_BEGIN_LICENSE:BSD$
|
||||
** Commercial License Usage
|
||||
** Licensees holding valid commercial Qt licenses may use this file in
|
||||
** accordance with the commercial license agreement provided with the
|
||||
** Software or, alternatively, in accordance with the terms contained in
|
||||
** a written agreement between you and The Qt Company. For licensing terms
|
||||
** and conditions see https://www.qt.io/terms-conditions. For further
|
||||
** information use the contact form at https://www.qt.io/contact-us.
|
||||
**
|
||||
** BSD License Usage
|
||||
** Alternatively, you may use this file under the terms of the BSD license
|
||||
** as follows:
|
||||
**
|
||||
** "Redistribution and use in source and binary forms, with or without
|
||||
** modification, are permitted provided that the following conditions are
|
||||
** met:
|
||||
** * Redistributions of source code must retain the above copyright
|
||||
** notice, this list of conditions and the following disclaimer.
|
||||
** * Redistributions in binary form must reproduce the above copyright
|
||||
** notice, this list of conditions and the following disclaimer in
|
||||
** the documentation and/or other materials provided with the
|
||||
** distribution.
|
||||
** * Neither the name of The Qt Company Ltd nor the names of its
|
||||
** contributors may be used to endorse or promote products derived
|
||||
** from this software without specific prior written permission.
|
||||
**
|
||||
**
|
||||
** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
|
||||
**
|
||||
** $QT_END_LICENSE$
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#include <QtWidgets>
|
||||
|
||||
#include "flowlayout.h"
|
||||
//! [1]
|
||||
FlowLayout::FlowLayout(QWidget *parent, int margin, int hSpacing, int vSpacing)
|
||||
: QLayout(parent), m_hSpace(hSpacing), m_vSpace(vSpacing)
|
||||
{
|
||||
setContentsMargins(margin, margin, margin, margin);
|
||||
}
|
||||
|
||||
FlowLayout::FlowLayout(int margin, int hSpacing, int vSpacing)
|
||||
: m_hSpace(hSpacing), m_vSpace(vSpacing)
|
||||
{
|
||||
setContentsMargins(margin, margin, margin, margin);
|
||||
}
|
||||
//! [1]
|
||||
|
||||
//! [2]
|
||||
FlowLayout::~FlowLayout()
|
||||
{
|
||||
QLayoutItem *item;
|
||||
while ((item = takeAt(0)))
|
||||
delete item;
|
||||
}
|
||||
//! [2]
|
||||
|
||||
//! [3]
|
||||
void FlowLayout::addItem(QLayoutItem *item)
|
||||
{
|
||||
itemList.append(item);
|
||||
}
|
||||
//! [3]
|
||||
|
||||
//! [4]
|
||||
int FlowLayout::horizontalSpacing() const
|
||||
{
|
||||
if (m_hSpace >= 0) {
|
||||
return m_hSpace;
|
||||
} else {
|
||||
return smartSpacing(QStyle::PM_LayoutHorizontalSpacing);
|
||||
}
|
||||
}
|
||||
|
||||
int FlowLayout::verticalSpacing() const
|
||||
{
|
||||
if (m_vSpace >= 0) {
|
||||
return m_vSpace;
|
||||
} else {
|
||||
return smartSpacing(QStyle::PM_LayoutVerticalSpacing);
|
||||
}
|
||||
}
|
||||
//! [4]
|
||||
|
||||
//! [5]
|
||||
int FlowLayout::count() const
|
||||
{
|
||||
return itemList.size();
|
||||
}
|
||||
|
||||
QLayoutItem *FlowLayout::itemAt(int index) const
|
||||
{
|
||||
return itemList.value(index);
|
||||
}
|
||||
|
||||
QLayoutItem *FlowLayout::takeAt(int index)
|
||||
{
|
||||
if (index >= 0 && index < itemList.size())
|
||||
return itemList.takeAt(index);
|
||||
else
|
||||
return nullptr;
|
||||
}
|
||||
//! [5]
|
||||
|
||||
//! [6]
|
||||
Qt::Orientations FlowLayout::expandingDirections() const
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
//! [6]
|
||||
|
||||
//! [7]
|
||||
bool FlowLayout::hasHeightForWidth() const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
int FlowLayout::heightForWidth(int width) const
|
||||
{
|
||||
int height = doLayout(QRect(0, 0, width, 0), true);
|
||||
return height;
|
||||
}
|
||||
//! [7]
|
||||
|
||||
//! [8]
|
||||
void FlowLayout::setGeometry(const QRect &rect)
|
||||
{
|
||||
QLayout::setGeometry(rect);
|
||||
doLayout(rect, false);
|
||||
}
|
||||
|
||||
QSize FlowLayout::sizeHint() const
|
||||
{
|
||||
return minimumSize();
|
||||
}
|
||||
|
||||
QSize FlowLayout::minimumSize() const
|
||||
{
|
||||
QSize size;
|
||||
QLayoutItem *item;
|
||||
foreach (item, itemList)
|
||||
size = size.expandedTo(item->minimumSize());
|
||||
|
||||
size += QSize(2*margin(), 2*margin());
|
||||
return size;
|
||||
}
|
||||
//! [8]
|
||||
|
||||
//! [9]
|
||||
int FlowLayout::doLayout(const QRect &rect, bool testOnly) const
|
||||
{
|
||||
int left, top, right, bottom;
|
||||
getContentsMargins(&left, &top, &right, &bottom);
|
||||
QRect effectiveRect = rect.adjusted(+left, +top, -right, -bottom);
|
||||
int x = effectiveRect.x();
|
||||
int y = effectiveRect.y();
|
||||
int lineHeight = 0;
|
||||
//! [9]
|
||||
|
||||
//! [10]
|
||||
QLayoutItem *item;
|
||||
foreach (item, itemList) {
|
||||
QWidget *wid = item->widget();
|
||||
int spaceX = horizontalSpacing();
|
||||
if (spaceX == -1)
|
||||
spaceX = wid->style()->layoutSpacing(
|
||||
QSizePolicy::PushButton, QSizePolicy::PushButton, Qt::Horizontal);
|
||||
int spaceY = verticalSpacing();
|
||||
if (spaceY == -1)
|
||||
spaceY = wid->style()->layoutSpacing(
|
||||
QSizePolicy::PushButton, QSizePolicy::PushButton, Qt::Vertical);
|
||||
//! [10]
|
||||
//! [11]
|
||||
int nextX = x + item->sizeHint().width() + spaceX;
|
||||
if (nextX - spaceX > effectiveRect.right() && lineHeight > 0) {
|
||||
x = effectiveRect.x();
|
||||
y = y + lineHeight + spaceY;
|
||||
nextX = x + item->sizeHint().width() + spaceX;
|
||||
lineHeight = 0;
|
||||
}
|
||||
|
||||
if (!testOnly)
|
||||
item->setGeometry(QRect(QPoint(x, y), item->sizeHint()));
|
||||
|
||||
x = nextX;
|
||||
lineHeight = qMax(lineHeight, item->sizeHint().height());
|
||||
}
|
||||
return y + lineHeight - rect.y() + bottom;
|
||||
}
|
||||
//! [11]
|
||||
//! [12]
|
||||
int FlowLayout::smartSpacing(QStyle::PixelMetric pm) const
|
||||
{
|
||||
QObject *parent = this->parent();
|
||||
if (!parent) {
|
||||
return -1;
|
||||
} else if (parent->isWidgetType()) {
|
||||
QWidget *pw = static_cast<QWidget *>(parent);
|
||||
return pw->style()->pixelMetric(pm, nullptr, pw);
|
||||
} else {
|
||||
return static_cast<QLayout *>(parent)->spacing();
|
||||
}
|
||||
}
|
||||
//! [12]
|
||||
88
src/flowlayout.h
Normal file
@@ -0,0 +1,88 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2016 The Qt Company Ltd.
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
** This file is part of the examples of the Qt Toolkit.
|
||||
**
|
||||
** $QT_BEGIN_LICENSE:BSD$
|
||||
** Commercial License Usage
|
||||
** Licensees holding valid commercial Qt licenses may use this file in
|
||||
** accordance with the commercial license agreement provided with the
|
||||
** Software or, alternatively, in accordance with the terms contained in
|
||||
** a written agreement between you and The Qt Company. For licensing terms
|
||||
** and conditions see https://www.qt.io/terms-conditions. For further
|
||||
** information use the contact form at https://www.qt.io/contact-us.
|
||||
**
|
||||
** BSD License Usage
|
||||
** Alternatively, you may use this file under the terms of the BSD license
|
||||
** as follows:
|
||||
**
|
||||
** "Redistribution and use in source and binary forms, with or without
|
||||
** modification, are permitted provided that the following conditions are
|
||||
** met:
|
||||
** * Redistributions of source code must retain the above copyright
|
||||
** notice, this list of conditions and the following disclaimer.
|
||||
** * Redistributions in binary form must reproduce the above copyright
|
||||
** notice, this list of conditions and the following disclaimer in
|
||||
** the documentation and/or other materials provided with the
|
||||
** distribution.
|
||||
** * Neither the name of The Qt Company Ltd nor the names of its
|
||||
** contributors may be used to endorse or promote products derived
|
||||
** from this software without specific prior written permission.
|
||||
**
|
||||
**
|
||||
** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
|
||||
**
|
||||
** $QT_END_LICENSE$
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef FLOWLAYOUT_H
|
||||
#define FLOWLAYOUT_H
|
||||
|
||||
#include <QLayout>
|
||||
#include <QRect>
|
||||
#include <QStyle>
|
||||
//! [0]
|
||||
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() override;
|
||||
|
||||
void addItem(QLayoutItem *item) override;
|
||||
int horizontalSpacing() const;
|
||||
int verticalSpacing() const;
|
||||
Qt::Orientations expandingDirections() const override;
|
||||
bool hasHeightForWidth() const override;
|
||||
int heightForWidth(int) const override;
|
||||
int count() const override;
|
||||
QLayoutItem *itemAt(int index) const override;
|
||||
QSize minimumSize() const override;
|
||||
void setGeometry(const QRect &rect) override;
|
||||
QSize sizeHint() const override;
|
||||
QLayoutItem *takeAt(int index) override;
|
||||
|
||||
private:
|
||||
int doLayout(const QRect &rect, bool testOnly) const;
|
||||
int smartSpacing(QStyle::PixelMetric pm) const;
|
||||
|
||||
QList<QLayoutItem *> itemList;
|
||||
int m_hSpace;
|
||||
int m_vSpace;
|
||||
};
|
||||
//! [0]
|
||||
|
||||
#endif // FLOWLAYOUT_H
|
||||
51
src/image_show.cpp
Normal file
@@ -0,0 +1,51 @@
|
||||
#include "image_show.h"
|
||||
|
||||
#include <QHBoxLayout>
|
||||
#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;
|
||||
layout->addWidget(m_label);
|
||||
setLayout(layout);
|
||||
m_label->setText("layout");
|
||||
}
|
||||
|
||||
void image_show::setImage(QPixmap image)
|
||||
{
|
||||
QImage screen0;
|
||||
screen0 = image.toImage();
|
||||
QImage re_screen1;
|
||||
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));
|
||||
}
|
||||
|
||||
void image_show::mousePressEvent(QMouseEvent *)
|
||||
{
|
||||
m_dialog->setimage(m_image);
|
||||
m_dialog->showFullScreen();
|
||||
|
||||
// 识别主屏幕尺寸并设置 widget 大小
|
||||
m_dialog->setFixedSize(desktop_w, desktop_h);
|
||||
|
||||
m_dialog->move(0,0);
|
||||
}
|
||||
@@ -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
|
||||
@@ -1,17 +1,19 @@
|
||||
#include <DApplication>
|
||||
#include <DWidgetUtil> //Dtk::Widget::moveToCenter(&w); 要调用它,就得引用DWidgetUtil
|
||||
#include <QDesktopWidget>
|
||||
#include <widget.h>
|
||||
#include <QTranslator>
|
||||
#include <DAboutDialog>
|
||||
#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...)
|
||||
*
|
||||
@@ -19,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(
|
||||
@@ -39,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("2.0.2.5"));
|
||||
a.setApplicationVersion(DApplication::buildVersion("3.0"));
|
||||
a.setApplicationAcknowledgementPage("https://gitee.com/deepin-community-store/spark-store");
|
||||
a.setApplicationDescription(
|
||||
QObject::tr(
|
||||
@@ -50,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();
|
||||
44
src/progressload.cpp
Normal file
@@ -0,0 +1,44 @@
|
||||
#include "progressload.h"
|
||||
|
||||
#include <DApplicationHelper>
|
||||
|
||||
ProgressLoad::ProgressLoad(QWidget *parent) :
|
||||
QWidget(parent),
|
||||
m_progess(new QWidget(this)),
|
||||
timer(new QTimer),
|
||||
value(0)
|
||||
{
|
||||
m_progess->move(0,0);
|
||||
m_progess->show();
|
||||
|
||||
timer->setInterval(10);
|
||||
timer->start();
|
||||
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);
|
||||
}
|
||||
|
||||
void ProgressLoad::setTheme(bool dark, QColor color)
|
||||
{
|
||||
if(dark)
|
||||
{
|
||||
plt.setColor(QPalette::Background, QColor(40, 40, 40));
|
||||
setAutoFillBackground(true);
|
||||
setPalette(plt);
|
||||
}
|
||||
else
|
||||
{
|
||||
plt.setColor(QPalette::Background, QColor(255, 255, 255));
|
||||
setAutoFillBackground(true);
|
||||
setPalette(plt);
|
||||
}
|
||||
m_progess->setStyleSheet("background-color: " + color.name() + ";");
|
||||
}
|
||||
@@ -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
|
||||
@@ -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,44 +22,62 @@ 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\
|
||||
widget.cpp \
|
||||
downloadlist.cpp \
|
||||
image_show.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 \
|
||||
big_image.cpp \
|
||||
downloadlist.cpp \
|
||||
downloadworker.cpp \
|
||||
flowlayout.cpp \
|
||||
image_show.cpp \
|
||||
main.cpp \
|
||||
progressload.cpp \
|
||||
widget.cpp \
|
||||
workerthreads.cpp
|
||||
|
||||
HEADERS += \
|
||||
widget.h \
|
||||
downloadlist.h \
|
||||
image_show.h \
|
||||
HEADERS += \
|
||||
appitem.h \
|
||||
big_image.h \
|
||||
downloadlist.h \
|
||||
downloadworker.h \
|
||||
flowlayout.h \
|
||||
image_show.h \
|
||||
progressload.h \
|
||||
widget.h \
|
||||
workerthreads.h
|
||||
|
||||
FORMS += \
|
||||
widget.ui \
|
||||
downloadlist.ui
|
||||
appitem.ui \
|
||||
downloadlist.ui \
|
||||
widget.ui
|
||||
|
||||
RESOURCES += \
|
||||
icons.qrc
|
||||
../assets/icons.qrc
|
||||
|
||||
DISTFILES += \
|
||||
tags/a2d-small.png \
|
||||
tags/a2d.png \
|
||||
tags/community-small.png \
|
||||
tags/community.png \
|
||||
tags/deepin-small.png \
|
||||
tags/dtk-small.png \
|
||||
tags/ubuntu-small.png \
|
||||
tags/ubuntu.png \
|
||||
tags/uos-small.png \
|
||||
tags/community.svg \
|
||||
tags/deepin.svg \
|
||||
tags/logo_icon.svg \
|
||||
tags/uos.svg
|
||||
../assets/tags/a2d-small.png \
|
||||
../assets/tags/a2d.png \
|
||||
../assets/tags/community-small.png \
|
||||
../assets/tags/community.png \
|
||||
../assets/tags/deepin-small.png \
|
||||
../assets/tags/dtk-small.png \
|
||||
../assets/tags/ubuntu-small.png \
|
||||
../assets/tags/ubuntu.png \
|
||||
../assets/tags/uos-small.png \
|
||||
../assets/tags/community.svg \
|
||||
../assets/tags/deepin.svg \
|
||||
../assets/tags/logo_icon.svg \
|
||||
../assets/tags/uos.svg
|
||||
|
||||
TRANSLATIONS = ./trans/spark-store_en.ts \
|
||||
./trans/spark-store_zh_CN.ts \
|
||||
./trans/spark-store_fr.ts
|
||||
TRANSLATIONS += \
|
||||
../translations/spark-store_en.ts \
|
||||
../translations/spark-store_fr.ts \
|
||||
../translations/spark-store_zh_CN.ts
|
||||
1356
src/widget.cpp
Normal file
@@ -2,53 +2,61 @@
|
||||
#define WIDGET_H
|
||||
|
||||
#include <QWidget>
|
||||
#include <QUrl>
|
||||
#include <QFile>
|
||||
#include <QNetworkReply>
|
||||
#include <QNetworkAccessManager>
|
||||
#include <downloadlist.h>
|
||||
|
||||
#include <QJsonObject>
|
||||
#include <QProcess>
|
||||
#include <QFuture>
|
||||
#include <QFutureWatcher>
|
||||
#include <QToolButton>
|
||||
#include <QTimer>
|
||||
|
||||
#include <QJsonArray>
|
||||
#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 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);
|
||||
@@ -73,6 +81,9 @@ private slots:
|
||||
void sltAppinfoScreenshot(QPixmap *picture, int index);
|
||||
void sltAppinfoFinish();
|
||||
|
||||
void displaySearchApp(QJsonArray array); // 展示搜索的APP信息
|
||||
void downloadIconsFinished(int arraysize); // 当前搜索列表图标是否下载完成
|
||||
|
||||
void on_pushButton_download_clicked();
|
||||
void on_pushButton_return_clicked();
|
||||
void on_comboBox_server_currentIndexChanged(const QString &arg1);
|
||||
@@ -92,7 +103,6 @@ private slots:
|
||||
void on_pushButton_translate_clicked();
|
||||
|
||||
public:
|
||||
|
||||
QUrl url;
|
||||
|
||||
downloadlist download_list[LIST_MAX];
|
||||
@@ -112,7 +122,6 @@ public:
|
||||
private:
|
||||
void initUI();
|
||||
void initConfig();
|
||||
int loadappinfo(QUrl);
|
||||
void chooseLeftMenu(int index);
|
||||
void setfoot(int);
|
||||
void updatefoot();
|
||||
@@ -124,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;
|
||||
@@ -139,12 +149,20 @@ 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; // 禁止多次搜索事件同时发生
|
||||
|
||||
QList<image_show*> label_screen;
|
||||
SpkAppInfoLoaderThread appinfoLoadThread;
|
||||
|
||||
AeaQt::HttpClient *httpClient;
|
||||
FlowLayout *applist_grid;
|
||||
QHBoxLayout *main;
|
||||
DownloadController *downloadController;
|
||||
};
|
||||
|
||||
#endif // WIDGET_H
|
||||
@@ -7,7 +7,7 @@
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>1053</width>
|
||||
<height>674</height>
|
||||
<height>711</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
@@ -29,6 +29,38 @@
|
||||
<property name="spacing">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item row="1" column="1">
|
||||
<widget class="ProgressLoad" name="progressload" native="true">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>3</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>16777215</width>
|
||||
<height>3</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="toolTipDuration">
|
||||
<number>-1</number>
|
||||
</property>
|
||||
<property name="styleSheet">
|
||||
<string notr="true"/>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="DTitlebar" name="titlebar" native="true">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0" rowspan="4">
|
||||
<widget class="QWidget" name="widget_menuList" native="true">
|
||||
<property name="minimumSize">
|
||||
@@ -61,33 +93,21 @@
|
||||
<property name="rightMargin">
|
||||
<number>5</number>
|
||||
</property>
|
||||
<item row="6" column="0" colspan="6">
|
||||
<widget class="QPushButton" name="menu_video">
|
||||
<property name="text">
|
||||
<string>Video</string>
|
||||
<item row="1" column="0">
|
||||
<spacer name="verticalSpacer_7">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="16" column="0" colspan="6">
|
||||
<widget class="QPushButton" name="menu_download">
|
||||
<property name="text">
|
||||
<string>Download</string>
|
||||
<property name="sizeType">
|
||||
<enum>QSizePolicy::Fixed</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="12" column="0" colspan="6">
|
||||
<widget class="QPushButton" name="menu_system">
|
||||
<property name="text">
|
||||
<string>Tools</string>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="13" column="0" colspan="6">
|
||||
<widget class="QPushButton" name="menu_theme">
|
||||
<property name="text">
|
||||
<string>Beautify</string>
|
||||
</property>
|
||||
</widget>
|
||||
</spacer>
|
||||
</item>
|
||||
<item row="5" column="0" colspan="6">
|
||||
<widget class="QPushButton" name="menu_music">
|
||||
@@ -96,6 +116,20 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="7" column="0" colspan="6">
|
||||
<widget class="QPushButton" name="menu_photo">
|
||||
<property name="text">
|
||||
<string>Graphics</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="11" column="0" colspan="6">
|
||||
<widget class="QPushButton" name="menu_dev">
|
||||
<property name="text">
|
||||
<string>Development</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0" colspan="2">
|
||||
<widget class="QLabel" name="icon">
|
||||
<property name="minimumSize">
|
||||
@@ -115,22 +149,6 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<spacer name="verticalSpacer_7">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeType">
|
||||
<enum>QSizePolicy::Fixed</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item row="0" column="5">
|
||||
<spacer name="horizontalSpacer_8">
|
||||
<property name="orientation">
|
||||
@@ -147,10 +165,30 @@
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item row="11" column="0" colspan="6">
|
||||
<widget class="QPushButton" name="menu_dev">
|
||||
<item row="0" column="2">
|
||||
<spacer name="horizontalSpacer_9">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item row="12" column="0" colspan="6">
|
||||
<widget class="QPushButton" name="menu_system">
|
||||
<property name="text">
|
||||
<string>Development</string>
|
||||
<string>Tools</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="10" column="0" colspan="6">
|
||||
<widget class="QPushButton" name="menu_read">
|
||||
<property name="text">
|
||||
<string>Reading</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
@@ -161,6 +199,33 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="3">
|
||||
<widget class="QPushButton" name="pushButton_refresh">
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Reload</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="../assets/icons.qrc">
|
||||
<normaloff>:/icons/icons/refresh-page.svg</normaloff>:/icons/icons/refresh-page.svg</iconset>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="0" colspan="6">
|
||||
<widget class="QPushButton" name="menu_chat">
|
||||
<property name="text">
|
||||
<string>Chat</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="4">
|
||||
<widget class="QPushButton" name="pushButton_return">
|
||||
<property name="maximumSize">
|
||||
@@ -176,7 +241,7 @@
|
||||
<string/>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="icons.qrc">
|
||||
<iconset resource="../assets/icons.qrc">
|
||||
<normaloff>:/icons/icons/category_active.svg</normaloff>:/icons/icons/category_active.svg</iconset>
|
||||
</property>
|
||||
</widget>
|
||||
@@ -194,10 +259,24 @@
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item row="10" column="0" colspan="6">
|
||||
<widget class="QPushButton" name="menu_read">
|
||||
<item row="13" column="0" colspan="6">
|
||||
<widget class="QPushButton" name="menu_theme">
|
||||
<property name="text">
|
||||
<string>Reading</string>
|
||||
<string>Beautify</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0" colspan="6">
|
||||
<widget class="QPushButton" name="menu_network">
|
||||
<property name="text">
|
||||
<string>Network</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="8" column="0" colspan="6">
|
||||
<widget class="QPushButton" name="menu_game">
|
||||
<property name="text">
|
||||
<string>Games</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
@@ -221,31 +300,17 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="7" column="0" colspan="6">
|
||||
<widget class="QPushButton" name="menu_photo">
|
||||
<item row="16" column="0" colspan="6">
|
||||
<widget class="QPushButton" name="menu_download">
|
||||
<property name="text">
|
||||
<string>Graphics</string>
|
||||
<string>Download</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="8" column="0" colspan="6">
|
||||
<widget class="QPushButton" name="menu_game">
|
||||
<item row="6" column="0" colspan="6">
|
||||
<widget class="QPushButton" name="menu_video">
|
||||
<property name="text">
|
||||
<string>Games</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="0" colspan="6">
|
||||
<widget class="QPushButton" name="menu_chat">
|
||||
<property name="text">
|
||||
<string>Chat</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0" colspan="6">
|
||||
<widget class="QPushButton" name="menu_network">
|
||||
<property name="text">
|
||||
<string>Network</string>
|
||||
<string>Video</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
@@ -268,39 +333,6 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="2">
|
||||
<spacer name="horizontalSpacer_9">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item row="0" column="3">
|
||||
<widget class="QPushButton" name="pushButton_refresh">
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Reload</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="icons.qrc">
|
||||
<normaloff>:/icons/icons/refresh-page.svg</normaloff>:/icons/icons/refresh-page.svg</iconset>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
@@ -313,7 +345,7 @@
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="currentIndex">
|
||||
<number>3</number>
|
||||
<number>4</number>
|
||||
</property>
|
||||
<widget class="QWidget" name="page">
|
||||
<layout class="QVBoxLayout" name="verticalLayout_4">
|
||||
@@ -457,7 +489,7 @@
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>889</width>
|
||||
<width>582</width>
|
||||
<height>849</height>
|
||||
</rect>
|
||||
</property>
|
||||
@@ -952,8 +984,8 @@
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>851</width>
|
||||
<height>326</height>
|
||||
<width>98</width>
|
||||
<height>28</height>
|
||||
</rect>
|
||||
</property>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_4">
|
||||
@@ -1082,8 +1114,8 @@
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>889</width>
|
||||
<height>812</height>
|
||||
<width>738</width>
|
||||
<height>886</height>
|
||||
</rect>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_23">
|
||||
@@ -1354,38 +1386,48 @@
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="DTitlebar" name="titlebar" native="true">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="ProgressLoad" name="progressload" native="true">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>3</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>16777215</width>
|
||||
<height>3</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="toolTipDuration">
|
||||
<number>-1</number>
|
||||
</property>
|
||||
<property name="styleSheet">
|
||||
<string notr="true"/>
|
||||
</property>
|
||||
<widget class="QWidget" name="applist_page">
|
||||
<layout class="QVBoxLayout" name="verticalLayout_3">
|
||||
<property name="spacing">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QScrollArea" name="applist_scrollarea">
|
||||
<property name="enabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="frameShape">
|
||||
<enum>QFrame::NoFrame</enum>
|
||||
</property>
|
||||
<property name="widgetResizable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<widget class="QWidget" name="applist_scrollAreaWidget">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>903</width>
|
||||
<height>681</height>
|
||||
</rect>
|
||||
</property>
|
||||
</widget>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
@@ -1416,7 +1458,7 @@
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<resources>
|
||||
<include location="icons.qrc"/>
|
||||
<include location="../assets/icons.qrc"/>
|
||||
</resources>
|
||||
<connections/>
|
||||
</ui>
|
||||
188
src/workerthreads.cpp
Normal file
@@ -0,0 +1,188 @@
|
||||
#include "workerthreads.h"
|
||||
|
||||
#include <QProcess>
|
||||
#include <QDir>
|
||||
#include <QFile>
|
||||
#include <QJsonDocument>
|
||||
|
||||
#include "widget.h"
|
||||
#include "HttpClient.h"
|
||||
|
||||
void SpkAppInfoLoaderThread::run()
|
||||
{
|
||||
emit requestResetUi();
|
||||
|
||||
httpClient = new AeaQt::HttpClient;
|
||||
|
||||
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;
|
||||
|
||||
// 将路径转化为相应源的下载路径
|
||||
urladdress = targetUrl.toString().left(targetUrl.toString().length() - 8);
|
||||
QStringList downloadurl = urladdress.split("/");
|
||||
|
||||
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().trimmed().isEmpty())
|
||||
{
|
||||
details += tr("Author: ") + json["Author"].toString() + "\n";
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
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)
|
||||
{
|
||||
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++)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
void SpkAppInfoLoaderThread::setServer(const QString &server)
|
||||
{
|
||||
serverUrl = server;
|
||||
}
|
||||
|
||||
void SpkAppInfoLoaderThread::downloadFinished(int exitcode, QProcess::ExitStatus status)
|
||||
{
|
||||
Q_UNUSED(exitcode)
|
||||
Q_UNUSED(status)
|
||||
|
||||
qDebug() << "Finish one download";
|
||||
finishedDownload = true;
|
||||
}
|
||||
|
||||
int SpkAppInfoLoaderThread::waitDownload(QProcess& downloader)
|
||||
{
|
||||
while(!downloader.waitForFinished(100))
|
||||
{
|
||||
if(downloader.state() == QProcess::NotRunning)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
if(this->isInterruptionRequested())
|
||||
{
|
||||
downloader.terminate();
|
||||
downloader.waitForFinished(-1);
|
||||
qDebug() << "Appinfo loader thread was forcefully terminated";
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@@ -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
|
||||
42
third-party/QtNetworkService/HttpClient.cpp
vendored
Normal file
@@ -0,0 +1,42 @@
|
||||
/**********************************************************
|
||||
Author: Qt君
|
||||
微信公众号: Qt君(文章首发)
|
||||
Website: qtbig.com(后续更新)
|
||||
Email: 2088201923@qq.com
|
||||
QQ交流群: 732271126
|
||||
LISCENSE: MIT
|
||||
**********************************************************/
|
||||
#include "HttpClient.h"
|
||||
#include <QJsonObject>
|
||||
#include <QJsonDocument>
|
||||
#include <QBuffer>
|
||||
|
||||
using namespace AeaQt;
|
||||
|
||||
HttpClient::HttpClient()
|
||||
{
|
||||
}
|
||||
|
||||
HttpClient::~HttpClient()
|
||||
{
|
||||
}
|
||||
|
||||
HttpRequest HttpClient::get(const QString &url)
|
||||
{
|
||||
return HttpRequest(QNetworkAccessManager::GetOperation, this).url(url);
|
||||
}
|
||||
|
||||
HttpRequest HttpClient::post(const QString &url)
|
||||
{
|
||||
return HttpRequest(QNetworkAccessManager::PostOperation, this).url(url);
|
||||
}
|
||||
|
||||
HttpRequest HttpClient::put(const QString &url)
|
||||
{
|
||||
return HttpRequest(QNetworkAccessManager::PutOperation, this).url(url);
|
||||
}
|
||||
|
||||
HttpRequest HttpClient::send(const QString &url, QNetworkAccessManager::Operation op)
|
||||
{
|
||||
return HttpRequest(op, this).url(url);
|
||||
}
|
||||
36
third-party/QtNetworkService/HttpClient.h
vendored
Normal file
@@ -0,0 +1,36 @@
|
||||
/**********************************************************
|
||||
Author: Qt君
|
||||
微信公众号: Qt君(文章首发)
|
||||
Website: qtbig.com(后续更新)
|
||||
Email: 2088201923@qq.com
|
||||
QQ交流群: 732271126
|
||||
LISCENSE: MIT
|
||||
**********************************************************/
|
||||
#ifndef HTTP_CLIENT_H
|
||||
#define HTTP_CLIENT_H
|
||||
|
||||
#include "HttpRequest.h"
|
||||
#include "HttpResponse.h"
|
||||
#include <QNetworkRequest>
|
||||
#include <QNetworkReply>
|
||||
|
||||
namespace AeaQt {
|
||||
|
||||
class HttpClient : public QNetworkAccessManager
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
friend class HttpRequest;
|
||||
|
||||
HttpClient();
|
||||
~HttpClient();
|
||||
|
||||
HttpRequest get(const QString &url);
|
||||
HttpRequest post(const QString &url);
|
||||
HttpRequest put(const QString &url);
|
||||
|
||||
HttpRequest send(const QString &url, Operation op = GetOperation);
|
||||
};
|
||||
|
||||
}
|
||||
#endif
|
||||
268
third-party/QtNetworkService/HttpRequest.cpp
vendored
Normal file
@@ -0,0 +1,268 @@
|
||||
/**********************************************************
|
||||
Author: Qt君
|
||||
微信公众号: Qt君(文章首发)
|
||||
Website: qtbig.com(后续更新)
|
||||
Email: 2088201923@qq.com
|
||||
QQ交流群: 732271126
|
||||
LISCENSE: MIT
|
||||
**********************************************************/
|
||||
#include "HttpRequest.h"
|
||||
#include "HttpClient.h"
|
||||
|
||||
#include <QJsonDocument>
|
||||
#include <QUrlQuery>
|
||||
#include <QBuffer>
|
||||
#include <QMetaEnum>
|
||||
|
||||
using namespace AeaQt;
|
||||
|
||||
static const char *s_httpOperation[] = {
|
||||
"UnknownOperation",
|
||||
"HeadOperation",
|
||||
"GetOperation",
|
||||
"PutOperation",
|
||||
"PostOperation",
|
||||
"DeleteOperation",
|
||||
"CustomOperation"
|
||||
};
|
||||
|
||||
HttpRequest::HttpRequest()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
HttpRequest::~HttpRequest()
|
||||
{
|
||||
}
|
||||
|
||||
HttpRequest::HttpRequest(QNetworkAccessManager::Operation op, HttpClient *jsonHttpClient) :
|
||||
m_body(QByteArray()),
|
||||
m_op(op),
|
||||
m_httpService(jsonHttpClient),
|
||||
m_timeout(-1)
|
||||
{
|
||||
}
|
||||
|
||||
HttpRequest &HttpRequest::url(const QString &url)
|
||||
{
|
||||
m_networkRequest.setUrl(QUrl(url));
|
||||
return *this;
|
||||
}
|
||||
|
||||
HttpRequest &HttpRequest::header(const QString &key, const QVariant &value)
|
||||
{
|
||||
m_networkRequest.setRawHeader(QByteArray(key.toStdString().data()), QByteArray(value.toString().toStdString().data()));
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
HttpRequest &HttpRequest::headers(const QMap<QString, QVariant> &headers)
|
||||
{
|
||||
QMapIterator<QString, QVariant> iter(headers);
|
||||
while (iter.hasNext()) {
|
||||
iter.next();
|
||||
header(iter.key(), iter.value());
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
HttpRequest &HttpRequest::body(const QVariantMap &content)
|
||||
{
|
||||
m_body = QJsonDocument(QJsonObject::fromVariantMap(content)).toJson();
|
||||
return *this;
|
||||
}
|
||||
|
||||
HttpRequest &HttpRequest::body(const QJsonObject &content)
|
||||
{
|
||||
m_body = QJsonDocument(QJsonObject::fromVariantMap(content.toVariantMap())).toJson();
|
||||
return *this;
|
||||
}
|
||||
|
||||
HttpRequest &HttpRequest::body(const QByteArray &content)
|
||||
{
|
||||
m_body = content;
|
||||
return *this;
|
||||
}
|
||||
|
||||
#if 0
|
||||
HttpRequest &HttpRequest::body(const QVariant &body)
|
||||
{
|
||||
/// clear m_jsonBody
|
||||
m_jsonBody = QJsonObject();
|
||||
|
||||
if (type == X_Www_Form_Urlencoded) {
|
||||
QUrl url;
|
||||
QUrlQuery urlQuery(url);
|
||||
|
||||
if (body.type() == QVariant::Map
|
||||
|| body.typeName() == QMetaType::typeName(QMetaType::QJsonObject)) {
|
||||
|
||||
QMapIterator<QString, QVariant> i(body.toMap());
|
||||
while (i.hasNext()) {
|
||||
i.next();
|
||||
urlQuery.addQueryItem(i.key(), i.value().toString());
|
||||
}
|
||||
|
||||
url.setQuery(urlQuery);
|
||||
m_body = url.toString(QUrl::FullyEncoded).toUtf8().remove(0, 1);
|
||||
}
|
||||
else {
|
||||
m_body = body.toByteArray();
|
||||
}
|
||||
}
|
||||
else if (type == Raw_Text_Json) {
|
||||
if (body.type() == QVariant::Map
|
||||
|| body.typeName() == QMetaType::typeName(QMetaType::QJsonObject)) {
|
||||
|
||||
m_body = QJsonDocument(QJsonObject::fromVariantMap(body.toMap())).toJson();
|
||||
}
|
||||
else {
|
||||
log_warning << "This is not data in JSON format(QVariantMap or QJsonObject).";
|
||||
m_body = QByteArray();
|
||||
// warning output
|
||||
}
|
||||
}
|
||||
else {
|
||||
m_body = QByteArray();
|
||||
log_warning << "Disable body.";
|
||||
}
|
||||
|
||||
log_debugger << "Body Content:" << m_body;
|
||||
return *this;
|
||||
}
|
||||
#endif
|
||||
|
||||
HttpRequest &HttpRequest::onResponse(const QObject *receiver, const char *slot, HttpResponse::SupportMethod type)
|
||||
{
|
||||
m_slotsMap.insert(type, {slot, QVariant::fromValue((QObject *)receiver)});
|
||||
return *this;
|
||||
}
|
||||
|
||||
HttpRequest &HttpRequest::onResponse(std::function<void (QNetworkReply *)> lambda)
|
||||
{
|
||||
return onResponse(QVariant::fromValue(lambda));
|
||||
}
|
||||
|
||||
HttpRequest &HttpRequest::onResponse(std::function<void (QVariantMap)> lambda)
|
||||
{
|
||||
return onResponse(QVariant::fromValue(lambda));
|
||||
}
|
||||
|
||||
HttpRequest &HttpRequest::onResponse(std::function<void (QByteArray)> lambda)
|
||||
{
|
||||
return onResponse(QVariant::fromValue(lambda));
|
||||
}
|
||||
|
||||
HttpRequest &HttpRequest::onResponse(std::function<void (qint64, qint64)> lambda)
|
||||
{
|
||||
return onResponse(QVariant::fromValue(lambda));
|
||||
}
|
||||
|
||||
HttpRequest &HttpRequest::onError(const QObject *receiver, const char *slot)
|
||||
{
|
||||
return onResponse(receiver, slot, HttpResponse::AutoInfer);
|
||||
}
|
||||
|
||||
HttpRequest &HttpRequest::onError(std::function<void (QNetworkReply::NetworkError)> lambda)
|
||||
{
|
||||
return onResponse(QVariant::fromValue(lambda));
|
||||
}
|
||||
|
||||
HttpRequest &HttpRequest::onError(std::function<void (QString)> lambda)
|
||||
{
|
||||
return onResponse(QVariant::fromValue(lambda));
|
||||
}
|
||||
|
||||
HttpRequest &HttpRequest::onError(std::function<void (QNetworkReply::NetworkError, QNetworkReply *)> lambda)
|
||||
{
|
||||
return onResponse(QVariant::fromValue(lambda));
|
||||
}
|
||||
|
||||
HttpRequest &HttpRequest::onError(std::function<void (QString, QNetworkReply *)> lambda)
|
||||
{
|
||||
return onResponse(QVariant::fromValue(lambda));
|
||||
}
|
||||
|
||||
HttpRequest &HttpRequest::timeout(const int &msec)
|
||||
{
|
||||
m_timeout = msec;
|
||||
return *this;
|
||||
}
|
||||
|
||||
HttpRequest &HttpRequest::block()
|
||||
{
|
||||
m_isBlock = true;
|
||||
return *this;
|
||||
}
|
||||
|
||||
HttpRequest &HttpRequest::onResponse(QVariant lambda)
|
||||
{
|
||||
m_slotsMap.insert(HttpResponse::AutoInfer, {lambda.typeName(), lambda});
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
HttpResponse *HttpRequest::exec()
|
||||
{
|
||||
QNetworkReply* reply = NULL;
|
||||
QBuffer* sendBuffer = new QBuffer();
|
||||
if (! m_body.isEmpty()) {
|
||||
sendBuffer->setData(m_body);
|
||||
}
|
||||
|
||||
log_debugger << "Http Client info: ";
|
||||
log_debugger << "Type: " << s_httpOperation[m_op];
|
||||
log_debugger << "Url: " << m_networkRequest.url().toString();
|
||||
QString headers;
|
||||
for (int i = 0; i < m_networkRequest.rawHeaderList().count(); i++) {
|
||||
QString each = m_networkRequest.rawHeaderList().at(i);
|
||||
QString header = m_networkRequest.rawHeader(each.toUtf8());
|
||||
headers += QString("%1: %2;").arg(each)
|
||||
.arg(header);
|
||||
}
|
||||
log_debugger << "Header: " << headers;
|
||||
log_debugger << "Send buffer(Body):\r\n" << m_body;
|
||||
|
||||
reply = m_httpService->createRequest(m_op, m_networkRequest, sendBuffer);
|
||||
|
||||
if (reply == NULL) {
|
||||
sendBuffer->deleteLater();
|
||||
return NULL;
|
||||
}
|
||||
else {
|
||||
sendBuffer->setParent(reply);
|
||||
}
|
||||
|
||||
return new HttpResponse(reply, m_slotsMap, m_timeout, m_isBlock);
|
||||
}
|
||||
|
||||
HttpRequest &HttpRequest::queryParam(const QString &key, const QVariant &value)
|
||||
{
|
||||
QUrl url(m_networkRequest.url());
|
||||
QUrlQuery urlQuery(url);
|
||||
|
||||
urlQuery.addQueryItem(key, value.toString());
|
||||
url.setQuery(urlQuery);
|
||||
|
||||
m_networkRequest.setUrl(url);
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
HttpRequest &HttpRequest::queryParams(const QMap<QString, QVariant> ¶ms)
|
||||
{
|
||||
QMapIterator<QString, QVariant> iter(params);
|
||||
while (iter.hasNext()) {
|
||||
iter.next();
|
||||
queryParam(iter.key(), iter.value());
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
HttpRequest &HttpRequest::userAttribute(const QVariant &value)
|
||||
{
|
||||
m_networkRequest.setAttribute(QNetworkRequest::User, value);
|
||||
return *this;
|
||||
}
|
||||
115
third-party/QtNetworkService/HttpRequest.h
vendored
Normal file
@@ -0,0 +1,115 @@
|
||||
/**********************************************************
|
||||
Author: Qt君
|
||||
微信公众号: Qt君(文章首发)
|
||||
Website: qtbig.com(后续更新)
|
||||
Email: 2088201923@qq.com
|
||||
QQ交流群: 732271126
|
||||
LISCENSE: MIT
|
||||
**********************************************************/
|
||||
#ifndef HTTP_REQUEST_H
|
||||
#define HTTP_REQUEST_H
|
||||
|
||||
#include "HttpResponse.h"
|
||||
|
||||
#include <QNetworkRequest>
|
||||
#include <QNetworkAccessManager>
|
||||
#include <QJsonObject>
|
||||
#include <QDebug>
|
||||
|
||||
namespace AeaQt {
|
||||
|
||||
#ifdef QT_APP_DEBUG
|
||||
#define log_debugger qDebug().noquote().nospace() \
|
||||
<< "[AeaQt::Network] Debug: -> " \
|
||||
<< "function: " << __func__ << "; " \
|
||||
<< "line: " << __LINE__ << "; "
|
||||
#else
|
||||
#define log_debugger QString()
|
||||
#endif
|
||||
|
||||
#define log_warning qWarning().noquote().nospace() \
|
||||
<< "[AeaQt::Network] Warning: -> " \
|
||||
<< "function: " << __func__ << "; " \
|
||||
<< "line: " << __LINE__ << "; "
|
||||
|
||||
class HttpClient;
|
||||
|
||||
class HttpRequest
|
||||
{
|
||||
public:
|
||||
enum BodyType {
|
||||
None = 0, // This request does not have a body.
|
||||
X_Www_Form_Urlencoded, // x-www-form-urlencoded
|
||||
Raw_Text_Json, // application/json
|
||||
};
|
||||
|
||||
explicit HttpRequest(QNetworkAccessManager::Operation op, HttpClient *jsonHttpClient);
|
||||
virtual ~HttpRequest();
|
||||
|
||||
HttpRequest &url(const QString &url);
|
||||
HttpRequest &header(const QString &key, const QVariant &value);
|
||||
HttpRequest &headers(const QMap<QString, QVariant> &headers);
|
||||
|
||||
HttpRequest &queryParam(const QString &key, const QVariant &value);
|
||||
HttpRequest &queryParams(const QMap<QString, QVariant> ¶ms);
|
||||
|
||||
/* Mainly used for identification */
|
||||
HttpRequest &userAttribute(const QVariant &value);
|
||||
|
||||
HttpRequest &body(const QVariantMap &content);
|
||||
HttpRequest &body(const QJsonObject &content);
|
||||
HttpRequest &body(const QByteArray &content);
|
||||
|
||||
/*
|
||||
* @onRespone slot support type: void function(QVariantMap resultMap) OR
|
||||
* void function(QByteArray resultData) OR
|
||||
* void function(QNetworkReply* reply)
|
||||
* note: The same type is only triggered once
|
||||
*/
|
||||
HttpRequest &onResponse(const QObject *receiver, const char *slot, HttpResponse::SupportMethod type = HttpResponse::AutoInfer);
|
||||
HttpRequest &onResponse(std::function<void (QNetworkReply*)> lambda);
|
||||
HttpRequest &onResponse(std::function<void (QVariantMap)> lambda);
|
||||
HttpRequest &onResponse(std::function<void (QByteArray)> lambda);
|
||||
HttpRequest &onResponse(std::function<void (qint64, qint64)> lambda);
|
||||
/*
|
||||
* @onError slot support type: void function(QNetworkReply::NetworkError error)
|
||||
* void function(QString errorString);
|
||||
* void function(QNetworkReply::NetworkError error, QNetworkReply* reply);
|
||||
* void function(QString errorString, QNetworkReply* reply);
|
||||
* note: The same type is only triggered once
|
||||
*/
|
||||
HttpRequest &onError(const QObject *receiver, const char *slot);
|
||||
HttpRequest &onError(std::function<void (QNetworkReply::NetworkError)> lambda);
|
||||
HttpRequest &onError(std::function<void (QString)> lambda);
|
||||
HttpRequest &onError(std::function<void (QNetworkReply::NetworkError, QNetworkReply*)> lambda);
|
||||
HttpRequest &onError(std::function<void (QString, QNetworkReply*)> lambda);
|
||||
|
||||
/**
|
||||
* @brief msec <= 0, disable timeout
|
||||
* msec > 0, enable timeout
|
||||
*/
|
||||
HttpRequest &timeout(const int &msec = -1);
|
||||
|
||||
/**
|
||||
* @brief Block current thread, entering an event loop.
|
||||
*/
|
||||
HttpRequest &block();
|
||||
|
||||
HttpResponse *exec();
|
||||
|
||||
private:
|
||||
HttpRequest();
|
||||
HttpRequest &onResponse(QVariant lambda);
|
||||
|
||||
private:
|
||||
QNetworkRequest m_networkRequest;
|
||||
QByteArray m_body;
|
||||
QNetworkAccessManager::Operation m_op;
|
||||
HttpClient *m_httpService;
|
||||
int m_timeout;
|
||||
bool m_isBlock;
|
||||
QMultiMap<HttpResponse::SupportMethod, QPair<QString, QVariant>> m_slotsMap;
|
||||
};
|
||||
|
||||
}
|
||||
#endif // HTTP_REQUEST_H
|
||||
331
third-party/QtNetworkService/HttpResponse.cpp
vendored
Normal file
@@ -0,0 +1,331 @@
|
||||
/**********************************************************
|
||||
Author: Qt君
|
||||
微信公众号: Qt君(文章首发)
|
||||
Website: qtbig.com(后续更新)
|
||||
Email: 2088201923@qq.com
|
||||
QQ交流群: 732271126
|
||||
LISCENSE: MIT
|
||||
**********************************************************/
|
||||
#include "HttpResponse.h"
|
||||
|
||||
#include <QRegExp>
|
||||
#include <QStringList>
|
||||
#include <QByteArray>
|
||||
#include <QNetworkConfigurationManager>
|
||||
#include <QMetaEnum>
|
||||
#include <QEventLoop>
|
||||
#include <QJsonDocument>
|
||||
#include <QJsonObject>
|
||||
|
||||
#define T2S(t) (QString(#t).remove(QRegExp("\\s"))) //type to string
|
||||
|
||||
#define _exec(target, type, arg) \
|
||||
if (target.canConvert<std::function<void (type)> >()) { \
|
||||
std::function<void (type)> func = target.value<std::function<void (type)> >(); func(arg); \
|
||||
} \
|
||||
else
|
||||
|
||||
#define _exec2(target, type1, type2, arg1, arg2) \
|
||||
if (target.canConvert<std::function<void (type1, type2)> >()) { \
|
||||
std::function<void (type1, type2)> func = target.value<std::function<void (type1, type2)> >(); func(arg1, arg2); \
|
||||
} else
|
||||
|
||||
using namespace AeaQt;
|
||||
|
||||
static const QMap<HttpResponse::SupportMethod, QMap<QString, QVariant>> methodParams =
|
||||
{
|
||||
{
|
||||
HttpResponse::onResponse_QNetworkReply_A_Pointer,
|
||||
{
|
||||
{"types", QStringList({T2S(QNetworkReply*)})},
|
||||
{"lambda", T2S(std::function<void (QNetworkReply*)>)},
|
||||
{"signal", SIGNAL(finished(QNetworkReply*))},
|
||||
{"isAutoInfer", true}
|
||||
}
|
||||
},
|
||||
{
|
||||
HttpResponse::onResponse_QByteArray,
|
||||
{
|
||||
{"types", QStringList({T2S(QByteArray)})},
|
||||
{"lambda", T2S(std::function<void (QByteArray)>)},
|
||||
{"signal", SIGNAL(finished(QByteArray))},
|
||||
{"isAutoInfer", true}
|
||||
}
|
||||
},
|
||||
{
|
||||
HttpResponse::onResponse_QVariantMap,
|
||||
{
|
||||
{"types", QStringList({T2S(QVariantMap)})},
|
||||
{"lambda", T2S(std::function<void (QVariantMap)>)},
|
||||
{"signal", SIGNAL(finished(QVariantMap))},
|
||||
{"isAutoInfer", true}
|
||||
}
|
||||
},
|
||||
{
|
||||
HttpResponse::onDownloadProgress_qint64_qint64,
|
||||
{
|
||||
{"types", QStringList({T2S(qint64), T2S(qint64)})},
|
||||
{"lambda", T2S(std::function<void (qint64, qint64)>)},
|
||||
{"signal", SIGNAL(downloadProgress(qint64, qint64))},
|
||||
{"isAutoInfer", true}
|
||||
}
|
||||
},
|
||||
{
|
||||
HttpResponse::onError_QNetworkReply_To_NetworkError,
|
||||
{
|
||||
{"types", QStringList({T2S(QNetworkReply::NetworkError)})},
|
||||
{"lambda", T2S(std::function<void (QNetworkReply::NetworkError)>)},
|
||||
{"signal", SIGNAL(error(QNetworkReply::NetworkError))},
|
||||
{"isAutoInfer", true}
|
||||
}
|
||||
},
|
||||
{
|
||||
HttpResponse::onError_QString,
|
||||
{
|
||||
{"types", QStringList({T2S(QString)})},
|
||||
{"lambda", T2S(std::function<void (QString)>)},
|
||||
{"signal", SIGNAL(error(QString))},
|
||||
{"isAutoInfer", true}
|
||||
}
|
||||
},
|
||||
{
|
||||
HttpResponse::onError_QNetworkReply_To_NetworkError_QNetworkReply_A_Pointer,
|
||||
{
|
||||
{"types", QStringList({T2S(QNetworkReply::NetworkError), T2S(QNetworkReply*)})},
|
||||
{"lambda", T2S(std::function<void (QNetworkReply::NetworkError, QNetworkReply*)>)},
|
||||
{"signal", SIGNAL(error(QNetworkReply::NetworkError, QNetworkReply*))},
|
||||
{"isAutoInfer", true}
|
||||
}
|
||||
},
|
||||
{
|
||||
HttpResponse::onError_QString_QNetworkReply_A_Poniter,
|
||||
{
|
||||
{"types", QStringList({T2S(QString), T2S(QNetworkReply*)})},
|
||||
{"lambda", T2S(std::function<void (QString, QNetworkReply*)>)},
|
||||
{"signal", SIGNAL(error(QString, QNetworkReply*))},
|
||||
{"isAutoInfer", true}
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
static int extractCode(const char *member)
|
||||
{
|
||||
/* extract code, ensure QMETHOD_CODE <= code <= QSIGNAL_CODE */
|
||||
return (((int)(*member) - '0') & 0x3);
|
||||
}
|
||||
|
||||
HttpResponse::HttpResponse(QNetworkReply *networkReply,
|
||||
const QMultiMap<SupportMethod, QPair<QString, QVariant> > &slotsMap,
|
||||
const int &timeout,
|
||||
bool isBlock)
|
||||
: m_networkReply(networkReply),
|
||||
m_slotsMap(slotsMap),
|
||||
QObject(networkReply)
|
||||
{
|
||||
slotsMapOperation(m_slotsMap);
|
||||
new HttpResponseTimeout(networkReply, timeout);
|
||||
|
||||
connect(m_networkReply, SIGNAL(finished()), this, SLOT(onFinished()));
|
||||
connect(m_networkReply, SIGNAL(error(QNetworkReply::NetworkError)), this, SLOT(onError(QNetworkReply::NetworkError)));
|
||||
connect(m_networkReply, SIGNAL(downloadProgress(qint64,qint64)), this, SLOT(onDownloadProgress(qint64, qint64)));
|
||||
|
||||
if (isBlock) {
|
||||
QEventLoop loop;
|
||||
QObject::connect(m_networkReply, SIGNAL(finished()), &loop, SLOT(quit()));
|
||||
loop.exec();
|
||||
}
|
||||
}
|
||||
|
||||
HttpResponse::~HttpResponse()
|
||||
{
|
||||
}
|
||||
|
||||
QNetworkReply *HttpResponse::networkReply()
|
||||
{
|
||||
return m_networkReply;
|
||||
}
|
||||
|
||||
void HttpResponse::onFinished()
|
||||
{
|
||||
QNetworkReply *reply = m_networkReply;
|
||||
if (reply->error() != QNetworkReply::NoError)
|
||||
return;
|
||||
|
||||
if (m_slotsMap.contains(onResponse_QNetworkReply_A_Pointer)) {
|
||||
_exec(m_slotsMap.value(onResponse_QNetworkReply_A_Pointer).second, QNetworkReply*, reply) {
|
||||
emit finished(reply);
|
||||
}
|
||||
}
|
||||
else if (m_slotsMap.contains((onResponse_QByteArray))) {
|
||||
QByteArray result = reply->readAll();
|
||||
|
||||
_exec(m_slotsMap.value((onResponse_QByteArray)).second, QByteArray, result) {
|
||||
emit finished(result);
|
||||
}
|
||||
|
||||
reply->deleteLater();
|
||||
}
|
||||
else if (m_slotsMap.contains((onResponse_QVariantMap))) {
|
||||
QByteArray result = reply->readAll();
|
||||
QVariantMap resultMap = QJsonDocument::fromJson(result).object().toVariantMap();
|
||||
|
||||
_exec(m_slotsMap.value((onResponse_QVariantMap)).second, QVariantMap, resultMap){
|
||||
emit finished(resultMap);
|
||||
}
|
||||
|
||||
reply->deleteLater();
|
||||
}
|
||||
}
|
||||
|
||||
void HttpResponse::onError(QNetworkReply::NetworkError error)
|
||||
{
|
||||
QNetworkReply *reply = m_networkReply;
|
||||
const QMetaObject & metaObject = QNetworkReply::staticMetaObject;
|
||||
QMetaEnum metaEnum = metaObject.enumerator(metaObject.indexOfEnumerator("NetworkError"));
|
||||
QString errorString = reply->errorString().isEmpty() ? metaEnum.valueToKey(error) : reply->errorString();
|
||||
|
||||
if (m_slotsMap.contains((onError_QString_QNetworkReply_A_Poniter))) {
|
||||
_exec2(m_slotsMap.value((onError_QString_QNetworkReply_A_Poniter)).second, QString, QNetworkReply*, errorString, reply) {
|
||||
emit this->error(errorString, reply);
|
||||
}
|
||||
}
|
||||
else if (m_slotsMap.contains((onError_QNetworkReply_To_NetworkError_QNetworkReply_A_Pointer))) {
|
||||
_exec2(m_slotsMap.value((onError_QNetworkReply_To_NetworkError_QNetworkReply_A_Pointer)).second,
|
||||
QNetworkReply::NetworkError, QNetworkReply*,
|
||||
error, reply) {
|
||||
emit this->error(error, reply);
|
||||
}
|
||||
}
|
||||
else if (m_slotsMap.contains((onError_QString))) {
|
||||
_exec(m_slotsMap.value((onError_QString)).second, QString, errorString) {
|
||||
emit this->error(errorString);
|
||||
}
|
||||
|
||||
reply->deleteLater();
|
||||
}
|
||||
else if (m_slotsMap.contains((onError_QNetworkReply_To_NetworkError))) {
|
||||
_exec(m_slotsMap.value((onError_QNetworkReply_To_NetworkError)).second, QNetworkReply::NetworkError, error) {
|
||||
emit this->error(error);
|
||||
}
|
||||
|
||||
reply->deleteLater();
|
||||
}
|
||||
}
|
||||
|
||||
void HttpResponse::onDownloadProgress(qint64 bytesReceived, qint64 bytesTotal)
|
||||
{
|
||||
if (m_slotsMap.contains((onDownloadProgress_qint64_qint64))) {
|
||||
_exec2(m_slotsMap.value((onDownloadProgress_qint64_qint64)).second, qint64, qint64, bytesReceived, bytesTotal) {
|
||||
emit downloadProgress(bytesReceived, bytesTotal);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void extractSlot(const QString &respReceiverSlot, QString &extractSlot, QStringList &extractSlotTypes)
|
||||
{
|
||||
QString slot(respReceiverSlot);
|
||||
if (extractCode(respReceiverSlot.toStdString().data()) == QSLOT_CODE && !slot.isEmpty()) {
|
||||
slot.remove(0, 1);
|
||||
|
||||
QString unconvertedSlotType = slot;
|
||||
int startIndex = slot.indexOf('(');
|
||||
int endIndex = slot.indexOf(')');
|
||||
Q_ASSERT(startIndex != -1 && endIndex != -1);
|
||||
|
||||
extractSlot = slot.remove(startIndex, endIndex-startIndex+1);
|
||||
|
||||
extractSlotTypes = unconvertedSlotType.mid(startIndex+1, endIndex-startIndex-1)
|
||||
.remove(QRegExp("\\s"))
|
||||
.split(',');
|
||||
}
|
||||
}
|
||||
|
||||
/* from slotMap get [SupportMethod] */
|
||||
static HttpResponse::SupportMethod getSupportMethod(const QPair<QString, QVariant> &slotMap) {
|
||||
|
||||
QMapIterator<HttpResponse::SupportMethod, QMap<QString, QVariant>> iter(methodParams);
|
||||
|
||||
QString receiverSlot = slotMap.first;
|
||||
QString slot;
|
||||
QStringList slotTypes;
|
||||
extractSlot(receiverSlot, slot, slotTypes);
|
||||
|
||||
while (iter.hasNext()) {
|
||||
iter.next();
|
||||
HttpResponse::SupportMethod supportMethod = iter.key();
|
||||
QMap<QString, QVariant> value = iter.value();
|
||||
if (slotTypes == value.value("types").toStringList()) {
|
||||
return supportMethod;
|
||||
}
|
||||
else if (receiverSlot == value.value("lambda").toString()) {
|
||||
return supportMethod;
|
||||
}
|
||||
}
|
||||
|
||||
return HttpResponse::Invalid;
|
||||
}
|
||||
|
||||
static void autoInfterConvertedSupportMethod(QMultiMap<HttpResponse::SupportMethod, QPair<QString, QVariant> > &unconvertedSlotsMap)
|
||||
{
|
||||
QMultiMap<HttpResponse::SupportMethod, QPair<QString, QVariant> > convertedSlotsMap;
|
||||
QMapIterator<HttpResponse::SupportMethod, QPair<QString, QVariant> > iter(unconvertedSlotsMap);
|
||||
|
||||
while (iter.hasNext()) {
|
||||
iter.next();
|
||||
const HttpResponse::SupportMethod supportMethod = iter.key();
|
||||
const QPair<QString, QVariant> slotMap = iter.value();
|
||||
|
||||
if (supportMethod == HttpResponse::AutoInfer) {
|
||||
HttpResponse::SupportMethod supportMethod = getSupportMethod(slotMap);
|
||||
if (supportMethod == HttpResponse::Invalid) {
|
||||
qDebug()<<"Not find support Method!"<<slotMap.first;
|
||||
}
|
||||
else {
|
||||
if (methodParams[supportMethod].value("isAutoInfer").toBool())
|
||||
convertedSlotsMap.insert(supportMethod, slotMap);
|
||||
else
|
||||
qDebug()<<"This type["<<methodParams[supportMethod].value("types").toString()<<"] does not support automatic derivation";
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (methodParams[supportMethod].value("isAutoInfer").toBool())
|
||||
convertedSlotsMap.insert(supportMethod, slotMap);
|
||||
else
|
||||
qDebug()<<"This type["<<methodParams[supportMethod].value("types").toString()<<"] does not support automatic derivation";
|
||||
}
|
||||
}
|
||||
|
||||
unconvertedSlotsMap = convertedSlotsMap;
|
||||
|
||||
}
|
||||
|
||||
void HttpResponse::slotsMapOperation(QMultiMap<SupportMethod, QPair<QString, QVariant> > &slotsMap)
|
||||
{
|
||||
autoInfterConvertedSupportMethod(slotsMap);
|
||||
|
||||
QMapIterator<SupportMethod, QPair<QString, QVariant> > iter(slotsMap);
|
||||
while (iter.hasNext()) {
|
||||
iter.next();
|
||||
SupportMethod supportMethod = iter.key();
|
||||
const QPair<QString, QVariant> &slotMap = iter.value();
|
||||
|
||||
const QString &receiverSlot = slotMap.first;
|
||||
QVariant target = slotMap.second;
|
||||
const QObject *receiver = target.value<QObject*>();
|
||||
|
||||
if (receiver) {
|
||||
if (methodParams.contains(supportMethod)) {
|
||||
connect(this,
|
||||
methodParams[supportMethod].value("signal").toString().toStdString().data(),
|
||||
receiver,
|
||||
receiverSlot.toStdString().data(),
|
||||
Qt::QueuedConnection);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
HttpResponse::HttpResponse()
|
||||
{
|
||||
|
||||
}
|
||||
107
third-party/QtNetworkService/HttpResponse.h
vendored
Normal file
@@ -0,0 +1,107 @@
|
||||
/**********************************************************
|
||||
Author: Qt君
|
||||
微信公众号: Qt君(文章首发)
|
||||
Website: qtbig.com(后续更新)
|
||||
Email: 2088201923@qq.com
|
||||
QQ交流群: 732271126
|
||||
LISCENSE: MIT
|
||||
**********************************************************/
|
||||
#ifndef HTTP_RESPONSE_H
|
||||
#define HTTP_RESPONSE_H
|
||||
|
||||
#include <QNetworkReply>
|
||||
#include <QMultiMap>
|
||||
#include <functional>
|
||||
#include <QTimer>
|
||||
|
||||
namespace AeaQt {
|
||||
|
||||
class HttpResponseTimeout : public QObject {
|
||||
Q_OBJECT
|
||||
public:
|
||||
HttpResponseTimeout(QNetworkReply *parent = NULL, const int timeout = -1) : QObject(parent) {
|
||||
if (timeout > 0)
|
||||
QTimer::singleShot(timeout, this, SLOT(onTimeout()));
|
||||
}
|
||||
|
||||
private slots:
|
||||
void onTimeout() {
|
||||
QNetworkReply *reply = static_cast<QNetworkReply*>(parent());
|
||||
if (reply->isRunning()) {
|
||||
reply->abort();
|
||||
reply->deleteLater();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
class HttpResponse : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
/*
|
||||
* Support Reflex Method
|
||||
* default: AutoInfer
|
||||
* AutoInfer: Automatic derivation based on type
|
||||
*/
|
||||
enum SupportMethod {
|
||||
Invalid = 0,
|
||||
AutoInfer,
|
||||
onResponse_QNetworkReply_A_Pointer, /* method: void function(QNetworkReply* reply); Is_AutoInfer: true */
|
||||
onResponse_QByteArray, /* method: void function(QByteArray data); Is_AutoInfer: true */
|
||||
onResponse_QVariantMap, /* method: void function(QVariantMap map); Is_AutoInfer: true */
|
||||
onDownloadProgress_qint64_qint64, /* method: void function(qint64 bytesReceived, qint64 bytesTotal); Is_AutoInfer: true */
|
||||
onError_QNetworkReply_To_NetworkError, /* method: void function(QNetworkReply::NetworkError error); Is_AutoInfer: true */
|
||||
onError_QString, /* method: void function(QString errorString); Is_AutoInfer: true */
|
||||
onError_QNetworkReply_To_NetworkError_QNetworkReply_A_Pointer, /* method: void function(QNetworkReply::NetworkError error, QNetworkReply* reply); Is_AutoInfer: true */
|
||||
onError_QString_QNetworkReply_A_Poniter/* method: void function(QString errorString, QNetworkReply* reply); Is_AutoInfer: true */
|
||||
};
|
||||
|
||||
explicit HttpResponse(QNetworkReply *networkReply,
|
||||
const QMultiMap<SupportMethod, QPair<QString, QVariant> > &slotsMap,
|
||||
const int &timeout,
|
||||
bool isBlock);
|
||||
|
||||
virtual ~HttpResponse();
|
||||
|
||||
QNetworkReply *networkReply();
|
||||
|
||||
protected:
|
||||
void slotsMapOperation(QMultiMap<SupportMethod, QPair<QString, QVariant> > &slotsMap);
|
||||
|
||||
signals:
|
||||
void finished(QNetworkReply *reply);
|
||||
void finished(QByteArray data);
|
||||
void finished(QVariantMap map);
|
||||
void error(QString errorString);
|
||||
void error(QNetworkReply::NetworkError error);
|
||||
void error(QString errorString, QNetworkReply *reply);
|
||||
void error(QNetworkReply::NetworkError error, QNetworkReply *reply);
|
||||
void downloadProgress(qint64 bytesReceived, qint64 bytesTotal);
|
||||
|
||||
private slots:
|
||||
void onFinished();
|
||||
void onError(QNetworkReply::NetworkError error);
|
||||
void onDownloadProgress(qint64 bytesReceived, qint64 bytesTotal);
|
||||
|
||||
private:
|
||||
HttpResponse();
|
||||
|
||||
private:
|
||||
QMultiMap<SupportMethod, QPair<QString, QVariant> > m_slotsMap;
|
||||
QNetworkReply *m_networkReply;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
Q_DECLARE_METATYPE(std::function<void (QNetworkReply*)>)
|
||||
Q_DECLARE_METATYPE(std::function<void (QByteArray)>)
|
||||
Q_DECLARE_METATYPE(std::function<void (QVariantMap)>)
|
||||
|
||||
Q_DECLARE_METATYPE(std::function<void (QString)>)
|
||||
Q_DECLARE_METATYPE(std::function<void (QNetworkReply::NetworkError)>)
|
||||
Q_DECLARE_METATYPE(std::function<void (QNetworkReply::NetworkError, QNetworkReply *)>)
|
||||
Q_DECLARE_METATYPE(std::function<void (QString, QNetworkReply *)>)
|
||||
|
||||
Q_DECLARE_METATYPE(std::function<void (qint64, qint64)>)
|
||||
|
||||
#endif // HTTP_RESPONSE_H
|
||||
21
third-party/QtNetworkService/LICENSE
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2019 Qt君
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
15
third-party/QtNetworkService/QtNetworkService.pri
vendored
Normal file
@@ -0,0 +1,15 @@
|
||||
#**********************************************************
|
||||
#Author: Qt君
|
||||
#微信公众号: Qt君(文章首发)
|
||||
#Website: qtbig.com(后续更新)
|
||||
#Email: 2088201923@qq.com
|
||||
#QQ交流群: 732271126
|
||||
#LISCENSE: MIT
|
||||
#**********************************************************
|
||||
INCLUDEPATH += $$PWD/
|
||||
|
||||
QT += network
|
||||
|
||||
!CONFIG(QT_APP_MODE) {
|
||||
LIBS += -L$$OUT_PWD/../third-party/QtNetworkService/Lib -lQtNetworkService
|
||||
}
|
||||
37
third-party/QtNetworkService/QtNetworkService.pro
vendored
Normal file
@@ -0,0 +1,37 @@
|
||||
#**********************************************************
|
||||
#Author: Qt君
|
||||
#微信公众号: Qt君(文章首发)
|
||||
#Website: qtbig.com(后续更新)
|
||||
#Email: 2088201923@qq.com
|
||||
#QQ交流群: 732271126
|
||||
#LISCENSE: MIT
|
||||
#**********************************************************
|
||||
CONFIG += c++11
|
||||
|
||||
#CONFIG += QT_APP_MODE
|
||||
DEFINES += QT_APP_DEBUG
|
||||
|
||||
QT += network
|
||||
|
||||
TEMPLATE = lib
|
||||
CONFIG += staticlib
|
||||
unix:TARGET = $$OUT_PWD/Lib/QtNetworkService
|
||||
|
||||
win32: {
|
||||
DESTDIR = $$OUT_PWD/Lib/
|
||||
TARGET = QtNetworkService
|
||||
}
|
||||
|
||||
message(" ================ QtNetworkService Library ================ ")
|
||||
|
||||
SOURCES += \
|
||||
$$PWD/HttpResponse.cpp \
|
||||
$$PWD/HttpRequest.cpp \
|
||||
$$PWD/HttpClient.cpp
|
||||
|
||||
HEADERS += \
|
||||
$$PWD/HttpResponse.h \
|
||||
$$PWD/HttpRequest.h \
|
||||
$$PWD/HttpClient.h
|
||||
|
||||
include(QtNetworkService.pri)
|
||||
83
third-party/QtNetworkService/README.md
vendored
Normal file
@@ -0,0 +1,83 @@
|
||||
# 示例
|
||||
(1) 简单示例
|
||||
* 使用lambda特性
|
||||
```cpp
|
||||
static HttpClient http;
|
||||
http.post("https://example.com")
|
||||
.header("content-type", "application/json")
|
||||
.queryParam("key", "Hello world!")
|
||||
.body(R"({"user": "test"})")
|
||||
.onResponse([](QByteArray result) { /* 接收数据 */
|
||||
qDebug() << "Result: " << result;
|
||||
})
|
||||
.onResponse([](qint64 recv, qint64 total) { /* 接收进度 */
|
||||
qDebug() << "Total: " << total << "; Received: " << recv;
|
||||
})
|
||||
.onError([](QString errorStr) { /* 错误处理 */
|
||||
qDebug()<<"Error: "<<errorStr;
|
||||
})
|
||||
.timeout(30 * 1000) /* 超时操作(30s) */
|
||||
.block() /* 阻塞操作 */
|
||||
.exec();
|
||||
```
|
||||
|
||||
* 使用Qt信号与槽特性
|
||||
```cpp
|
||||
http.post("https://example.com")
|
||||
.header("content-type", "application/json")
|
||||
.queryParam("key", "Hello world!")
|
||||
.body(R"({"user": "test"})")
|
||||
.onResponse(this, SLOT(finish(QByteArray)))
|
||||
.onResponse(this, SLOT(downloadProgress(qint64, qint64)))
|
||||
.onError(this, SLOT(error(QString)))
|
||||
.timeout(30 * 1000) /* 超时操作(30s) */
|
||||
.block() /* 阻塞操作 */
|
||||
.exec();
|
||||
```
|
||||
|
||||
(2) 复杂示例
|
||||
```cpp
|
||||
/* 获取音乐url功能,请求嵌套请求 */
|
||||
static HttpService http;
|
||||
http.get("http://mobilecdn.kugou.com/api/v3/search/song")
|
||||
.queryParam("format", "json")
|
||||
.queryParam("keyword", "稻香")
|
||||
.queryParam("page", 1)
|
||||
.queryParam("pagesize", 3)
|
||||
.queryParam("showtype", 1)
|
||||
.onResopnse([](QVariantMap result){
|
||||
QVariantMap data;
|
||||
QList<QVariant> infos;
|
||||
if (!result.isEmpty())
|
||||
data = result.value("data").toMap();
|
||||
|
||||
if (!data.isEmpty())
|
||||
infos = data.value("info").toList();
|
||||
|
||||
static HttpService http;
|
||||
foreach (QVariant each, infos) {
|
||||
http.get("http://m.kugou.com/app/i/getSongInfo.php")
|
||||
.queryParam("cmd", "playInfo")
|
||||
.queryParam("hash", each.toMap()["hash"])
|
||||
.onResopnse([](QVariantMap result){
|
||||
qDebug()<<"mp3: "<<result["url"].toString();
|
||||
})
|
||||
.onError([](QString errorStr){ qDebug()<<"Error: "<<errorStr; })
|
||||
.exec();
|
||||
}
|
||||
})
|
||||
.onError([](QString errorStr){ qDebug()<<"Error: "<<errorStr; })
|
||||
.exec();
|
||||
```
|
||||
## 1.如何使用?
|
||||
* 以Qt子工程使用.再在其他子工程包含pri文件即可使用;
|
||||
* 通过引用库的方式使用.
|
||||
|
||||
## 2.如何启用demo测试?
|
||||
* 在QtNetworkService.pro文件中将"#CONFIG += QT_APP_MODE"这一行的#去除即可转为可执行文件形式,在Demo目录的main.cpp为主执行文件,如需要测试接口编辑便可。
|
||||
|
||||
## 3.扫码关注,第一时间获取推送
|
||||
<p align="center">
|
||||
<img src="http://www.qtbig.com/about/index/my_qrcode.jpg" alt="微信公众号:Qt君">
|
||||
<p align="center"><em>Qt君</em></p>
|
||||
</p>
|
||||
BIN
translations/spark-store_en.qm
Normal file
@@ -1,10 +1,18 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!DOCTYPE TS>
|
||||
<TS version="2.1" language="en">
|
||||
<context>
|
||||
<name>AppItem</name>
|
||||
<message>
|
||||
<location filename="../src/appitem.ui" line="14"/>
|
||||
<source>Form</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>QLabel</name>
|
||||
<message>
|
||||
<location filename="../main.cpp" line="37"/>
|
||||
<location filename="../src/main.cpp" line="39"/>
|
||||
<source>Spark Store</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
@@ -12,7 +20,7 @@
|
||||
<context>
|
||||
<name>QObject</name>
|
||||
<message>
|
||||
<location filename="../main.cpp" line="45"/>
|
||||
<location filename="../src/main.cpp" line="47"/>
|
||||
<source><span style='font-size:10pt;font-weight:60;'>An appstore powered by deepin community</span><br/><a href='https://www.spark-app.store/'>https://www.spark-app.store</a><br/><span style='font-size:12pt;'>Spark developers</span><br/><br/>Published under GPL V3</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
@@ -20,47 +28,47 @@
|
||||
<context>
|
||||
<name>SpkAppInfoLoaderThread</name>
|
||||
<message>
|
||||
<location filename="../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="../workerthreads.cpp" line="53"/>
|
||||
<location filename="../src/workerthreads.cpp" line="44"/>
|
||||
<source>PkgName: </source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../workerthreads.cpp" line="54"/>
|
||||
<location filename="../src/workerthreads.cpp" line="45"/>
|
||||
<source>Version: </source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../workerthreads.cpp" line="56"/>
|
||||
<location filename="../src/workerthreads.cpp" line="47"/>
|
||||
<source>Author: </source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../workerthreads.cpp" line="60"/>
|
||||
<location filename="../src/workerthreads.cpp" line="51"/>
|
||||
<source>Official Site: </source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../workerthreads.cpp" line="64"/>
|
||||
<location filename="../src/workerthreads.cpp" line="55"/>
|
||||
<source>Contributor: </source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../workerthreads.cpp" line="65"/>
|
||||
<location filename="../src/workerthreads.cpp" line="56"/>
|
||||
<source>Update Time: </source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../workerthreads.cpp" line="66"/>
|
||||
<location filename="../src/workerthreads.cpp" line="57"/>
|
||||
<source>Installed Size: </source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../workerthreads.cpp" line="95"/>
|
||||
<location filename="../src/workerthreads.cpp" line="85"/>
|
||||
<source>Failed to load application icon.</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
@@ -68,468 +76,416 @@
|
||||
<context>
|
||||
<name>Widget</name>
|
||||
<message>
|
||||
<location filename="../widget.ui" line="14"/>
|
||||
<location filename="../src/widget.ui" line="14"/>
|
||||
<source>Form</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../widget.ui" line="52"/>
|
||||
<location filename="../src/widget.ui" line="84"/>
|
||||
<source>background-color:#FFFFFF</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../widget.ui" line="81"/>
|
||||
<location filename="../src/widget.ui" line="184"/>
|
||||
<source>Tools</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../widget.ui" line="88"/>
|
||||
<location filename="../src/widget.ui" line="265"/>
|
||||
<source>Beautify</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../widget.ui" line="95"/>
|
||||
<location filename="../src/widget.ui" line="115"/>
|
||||
<source>Music</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../widget.ui" line="160"/>
|
||||
<location filename="../src/widget.ui" line="198"/>
|
||||
<source>Office</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../widget.ui" line="207"/>
|
||||
<location filename="../src/widget.ui" line="286"/>
|
||||
<source>Others</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../widget.ui" line="234"/>
|
||||
<location filename="../src/widget.ui" line="279"/>
|
||||
<source>Games</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../widget.ui" line="528"/>
|
||||
<location filename="../src/widget.ui" line="560"/>
|
||||
<source>Name</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../widget.ui" line="568"/>
|
||||
<location filename="../src/widget.ui" line="600"/>
|
||||
<source>ICON</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../widget.ui" line="515"/>
|
||||
<location filename="../widget.cpp" line="586"/>
|
||||
<location filename="../widget.cpp" line="808"/>
|
||||
<location filename="../src/widget.ui" line="547"/>
|
||||
<location filename="../src/widget.cpp" line="772"/>
|
||||
<source>Install</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../widget.ui" line="623"/>
|
||||
<location filename="../src/widget.ui" line="655"/>
|
||||
<source>Uninstall</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../widget.ui" line="639"/>
|
||||
<location filename="../src/widget.ui" line="671"/>
|
||||
<source>Site</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../widget.ui" line="712"/>
|
||||
<location filename="../widget.ui" line="715"/>
|
||||
<location filename="../src/widget.ui" line="744"/>
|
||||
<location filename="../src/widget.ui" line="747"/>
|
||||
<source><html><head/><body><p>This app is developed by community user,we give this tag to honor those who contribute to the Linux Ecology</p></body></html></source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../widget.ui" line="718"/>
|
||||
<location filename="../src/widget.ui" line="750"/>
|
||||
<source><html><head/><body><p><img src=":/tags/community-small.png"/></p></body></html></source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../widget.ui" line="731"/>
|
||||
<location filename="../widget.ui" line="734"/>
|
||||
<location filename="../src/widget.ui" line="763"/>
|
||||
<location filename="../src/widget.ui" line="766"/>
|
||||
<source><html><head/><body><p>Capable to Ubuntu 20.04</p></body></html></source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../widget.ui" line="737"/>
|
||||
<location filename="../src/widget.ui" line="769"/>
|
||||
<source><html><head/><body><p><img src=":/tags/ubuntu-small.png"/></p></body></html></source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../widget.ui" line="775"/>
|
||||
<location filename="../src/widget.ui" line="807"/>
|
||||
<source><html><head/><body><p><img src=":/tags/uos-small.png"/></p></body></html></source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../widget.ui" line="750"/>
|
||||
<location filename="../widget.ui" line="753"/>
|
||||
<location filename="../src/widget.ui" line="782"/>
|
||||
<location filename="../src/widget.ui" line="785"/>
|
||||
<source><html><head/><body><p>Capable to deepin 20</p></body></html></source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../widget.ui" line="67"/>
|
||||
<location filename="../src/widget.ui" line="313"/>
|
||||
<source>Video</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../widget.ui" line="74"/>
|
||||
<location filename="../src/widget.ui" line="306"/>
|
||||
<source>Download</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../widget.ui" line="173"/>
|
||||
<location filename="../src/widget.ui" line="238"/>
|
||||
<source>Back to category</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../widget.ui" line="200"/>
|
||||
<location filename="../src/widget.ui" line="191"/>
|
||||
<source>Reading</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../widget.ui" line="241"/>
|
||||
<location filename="../src/widget.ui" line="225"/>
|
||||
<source>Chat</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../widget.ui" line="293"/>
|
||||
<location filename="../src/widget.ui" line="211"/>
|
||||
<source>Reload</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../widget.ui" line="383"/>
|
||||
<location filename="../src/widget.ui" line="415"/>
|
||||
<source>The list is currently empty. Go and download some softwares!</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../widget.ui" line="415"/>
|
||||
<location filename="../src/widget.ui" line="447"/>
|
||||
<source>Open download directory</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../widget.ui" line="756"/>
|
||||
<location filename="../src/widget.ui" line="788"/>
|
||||
<source><html><head/><body><p><img src=":/tags/deepin-small.png"/></p></body></html></source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../widget.ui" line="769"/>
|
||||
<location filename="../widget.ui" line="772"/>
|
||||
<location filename="../src/widget.ui" line="801"/>
|
||||
<location filename="../src/widget.ui" line="804"/>
|
||||
<source><html><head/><body><p>Capable to UOS home 20</p></body></html></source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../widget.ui" line="788"/>
|
||||
<location filename="../widget.ui" line="791"/>
|
||||
<location filename="../src/widget.ui" line="820"/>
|
||||
<location filename="../src/widget.ui" line="823"/>
|
||||
<source><html><head/><body><p>This is a DTK5 app,which means it would have better effect on Deepin Desktop Environment</p></body></html></source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../widget.ui" line="794"/>
|
||||
<location filename="../src/widget.ui" line="826"/>
|
||||
<source><html><head/><body><p><img src=":/tags/dtk-small.png"/></p></body></html></source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../widget.ui" line="826"/>
|
||||
<location filename="../widget.ui" line="829"/>
|
||||
<location filename="../src/widget.ui" line="858"/>
|
||||
<location filename="../src/widget.ui" line="861"/>
|
||||
<source><html><head/><body><p>A deepin-wine5 app.If you are using ubuntu or other non-deepin distro,you should deploy deepin-wine5 by your self.</p></body></html></source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../widget.ui" line="845"/>
|
||||
<location filename="../widget.ui" line="848"/>
|
||||
<location filename="../src/widget.ui" line="877"/>
|
||||
<location filename="../src/widget.ui" line="880"/>
|
||||
<source><html><head/><body><p>An Appimage to deb app.</p></body></html></source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../widget.ui" line="851"/>
|
||||
<location filename="../src/widget.ui" line="883"/>
|
||||
<source><html><head/><body><p><img src=":/tags/a2d-small.png"/></p></body></html></source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../widget.ui" line="678"/>
|
||||
<location filename="../src/widget.ui" line="710"/>
|
||||
<source>Share</source>
|
||||
<translation type="unfinished">Spk share link</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../widget.ui" line="153"/>
|
||||
<location filename="../src/widget.ui" line="129"/>
|
||||
<source>Development</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../widget.ui" line="217"/>
|
||||
<location filename="../src/widget.ui" line="296"/>
|
||||
<source>Home</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../widget.ui" line="227"/>
|
||||
<location filename="../src/widget.ui" line="122"/>
|
||||
<source>Graphics</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../widget.ui" line="248"/>
|
||||
<location filename="../src/widget.ui" line="272"/>
|
||||
<source>Network</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../widget.ui" line="807"/>
|
||||
<location filename="../widget.ui" line="810"/>
|
||||
<location filename="../src/widget.ui" line="839"/>
|
||||
<location filename="../src/widget.ui" line="842"/>
|
||||
<source><html><head/><body><p>A deepin-wine2 app.If you are using ubuntu or other non-deepin distro,you should deploy deepin-wine2 by your self.</p></body></html></source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../widget.ui" line="813"/>
|
||||
<location filename="../src/widget.ui" line="845"/>
|
||||
<source><html><head/><body><p><img src=":/tags/dwine2-small.png"/></p></body></html></source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../widget.ui" line="832"/>
|
||||
<location filename="../src/widget.ui" line="864"/>
|
||||
<source><html><head/><body><p><img src=":/tags/dwine5-small.png"/></p></body></html></source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../widget.ui" line="874"/>
|
||||
<location filename="../src/widget.ui" line="906"/>
|
||||
<source>Contribute translation</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../widget.ui" line="892"/>
|
||||
<location filename="../src/widget.ui" line="924"/>
|
||||
<source>Info</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../widget.ui" line="899"/>
|
||||
<location filename="../src/widget.ui" line="931"/>
|
||||
<source><html><head/><body><p>An app store developed by community enthusiasts</p></body></html></source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../widget.ui" line="938"/>
|
||||
<location filename="../src/widget.ui" line="970"/>
|
||||
<source>Screenshots</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../widget.ui" line="1101"/>
|
||||
<location filename="../src/widget.ui" line="1133"/>
|
||||
<source>Line Settings</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../widget.ui" line="1117"/>
|
||||
<location filename="../src/widget.ui" line="1149"/>
|
||||
<source>Choose Line:</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../widget.ui" line="1140"/>
|
||||
<location filename="../src/widget.ui" line="1172"/>
|
||||
<source>Refresh</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../widget.ui" line="1182"/>
|
||||
<location filename="../src/widget.ui" line="1214"/>
|
||||
<source><html><head/><body><p>The role of the source server is to ensure that the software is updated, and supports the use of the apt tool to get the software. We usually prefer that you use the first line as the update source, which is generally the most stable. </p></body></html></source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../widget.ui" line="1192"/>
|
||||
<location filename="../src/widget.ui" line="1224"/>
|
||||
<source>Update</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../widget.ui" line="1199"/>
|
||||
<location filename="../src/widget.ui" line="1231"/>
|
||||
<source>Source Server</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../widget.ui" line="1219"/>
|
||||
<location filename="../src/widget.ui" line="1251"/>
|
||||
<source>Server</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../widget.ui" line="1240"/>
|
||||
<location filename="../src/widget.ui" line="1272"/>
|
||||
<source>Temp</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../widget.ui" line="1263"/>
|
||||
<location filename="../src/widget.ui" line="1295"/>
|
||||
<source>Clean</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../widget.ui" line="1273"/>
|
||||
<location filename="../src/widget.ui" line="1305"/>
|
||||
<source>Since the dictionary is at /tmp,It would be cleaned automatically when system reboot.</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../widget.ui" line="1286"/>
|
||||
<location filename="../src/widget.ui" line="1318"/>
|
||||
<source>Size:</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../widget.ui" line="1300"/>
|
||||
<location filename="../src/widget.ui" line="1332"/>
|
||||
<source>Location:/tmp/spark-store</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../widget.ui" line="1321"/>
|
||||
<location filename="../src/widget.ui" line="1353"/>
|
||||
<source>About us</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../widget.ui" line="1328"/>
|
||||
<location filename="../src/widget.ui" line="1360"/>
|
||||
<source><html><head/><body><p>We are <span style=" font-weight:600;">NOT</span> the official team, just like you, we are just one of the many Linux/deepin system enthusiasts and users, we develop and run the &quot;Spark Store&quot;! &quot;, is to bring the community together to share useful software, or to participate in development together, so that we all use the latest and greatest software. </p><p>We don't make a profit from this, all developers and maintainers don't get paid, and we rely on the community's donations to us for most of our expenses, which we are grateful for and which allow us not to spend too much energy worrying about funding. </p><p>Our service and software are free for everyone to use, communicate, and learn, but you must comply with local laws and regulations in the process of your use, otherwise any problems have nothing to do with us. </p><p>If any part of the store infringes your rights, please tell us &lt;jifengshenmo@outlook.com&gt; we will remove the infringing content as soon as possible. </p><p>If you'd like to get involved with us too, whether you're involved in development, design, pitching or submitting work, we welcome you to join us. </p><p>QQ group:872690351<br/></p></body></html></source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../widget.ui" line="114"/>
|
||||
<location filename="../src/widget.ui" line="148"/>
|
||||
<source>icon</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../widget.ui" line="342"/>
|
||||
<location filename="../src/widget.ui" line="374"/>
|
||||
<source>about:blank</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../widget.ui" line="540"/>
|
||||
<location filename="../src/widget.ui" line="572"/>
|
||||
<source><html><head/><body><p><br/></p></body></html></source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../widget.ui" line="1153"/>
|
||||
<location filename="../src/widget.ui" line="1185"/>
|
||||
<source>Take effect when restart</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../widget.ui" line="1293"/>
|
||||
<location filename="../src/widget.ui" line="1325"/>
|
||||
<source>0B</source>
|
||||
<translation type="unfinished">0B</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../widget.cpp" line="157"/>
|
||||
<location filename="../src/widget.cpp" line="172"/>
|
||||
<source>Spark Store</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../widget.cpp" line="158"/>
|
||||
<location filename="../src/widget.cpp" line="173"/>
|
||||
<source>Search or enter spk://</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../widget.cpp" line="164"/>
|
||||
<location filename="../src/widget.cpp" line="179"/>
|
||||
<source>Submit App</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../widget.cpp" line="165"/>
|
||||
<location filename="../src/widget.cpp" line="180"/>
|
||||
<source>Settings</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../widget.cpp" line="264"/>
|
||||
<location filename="../src/widget.cpp" line="295"/>
|
||||
<source>Not Exist</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../widget.cpp" line="113"/>
|
||||
<location filename="../widget.cpp" line="319"/>
|
||||
<location filename="../widget.cpp" line="323"/>
|
||||
<location filename="../widget.cpp" line="332"/>
|
||||
<location filename="../widget.cpp" line="336"/>
|
||||
<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="../widget.cpp" line="530"/>
|
||||
<source>Failed to download app info. Please check internet connection.</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../widget.cpp" line="560"/>
|
||||
<source>PkgName: </source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../widget.cpp" line="561"/>
|
||||
<source>Version: </source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../widget.cpp" line="563"/>
|
||||
<source>Author: </source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../widget.cpp" line="567"/>
|
||||
<source>Official Site: </source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../widget.cpp" line="571"/>
|
||||
<source>Contributor: </source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../widget.cpp" line="572"/>
|
||||
<source>Update Time: </source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../widget.cpp" line="573"/>
|
||||
<source>Installed Size: </source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../widget.cpp" line="582"/>
|
||||
<location filename="../widget.cpp" line="693"/>
|
||||
<location filename="../widget.cpp" line="805"/>
|
||||
<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="../widget.cpp" line="621"/>
|
||||
<source>Failed to load application icon.</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../widget.cpp" line="668"/>
|
||||
<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="../widget.cpp" line="716"/>
|
||||
<source>Spark store could only process spk:// links for now. The search feature is coming soon!</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../widget.cpp" line="944"/>
|
||||
<location filename="../src/widget.cpp" line="919"/>
|
||||
<source>Updating, please wait...</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../widget.cpp" line="997"/>
|
||||
<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="../widget.cpp" line="1003"/>
|
||||
<location filename="../src/widget.cpp" line="978"/>
|
||||
<source>Unknown error!</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../widget.cpp" line="1185"/>
|
||||
<location filename="../src/widget.cpp" line="1164"/>
|
||||
<source>Yes</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../widget.cpp" line="1185"/>
|
||||
<location filename="../src/widget.cpp" line="1164"/>
|
||||
<source>No</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../widget.cpp" line="1186"/>
|
||||
<location filename="../src/widget.cpp" line="1165"/>
|
||||
<source>Information for Contributors</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../widget.cpp" line="1187"/>
|
||||
<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
|
||||
@@ -540,17 +496,27 @@ Click yes to continue.</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../widget.cpp" line="1023"/>
|
||||
<location filename="../src/widget.cpp" line="998"/>
|
||||
<source>Uninstall succeeded</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../widget.cpp" line="1037"/>
|
||||
<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="615"/>
|
||||
<source>Request Error: %1</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/widget.cpp" line="1012"/>
|
||||
<source>Temporary cache was cleaned</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../widget.cpp" line="1104"/>
|
||||
<location filename="../src/widget.cpp" line="1081"/>
|
||||
<source>The URL has been copied to the clipboard</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
@@ -558,107 +524,107 @@ Click yes to continue.</source>
|
||||
<context>
|
||||
<name>downloadlist</name>
|
||||
<message>
|
||||
<location filename="../downloadlist.ui" line="20"/>
|
||||
<location filename="../src/downloadlist.ui" line="20"/>
|
||||
<source>Form</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../downloadlist.ui" line="50"/>
|
||||
<location filename="../src/downloadlist.ui" line="50"/>
|
||||
<source>icon</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../downloadlist.ui" line="82"/>
|
||||
<location filename="../src/downloadlist.ui" line="82"/>
|
||||
<source>TextLabel</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../downloadlist.ui" line="106"/>
|
||||
<location filename="../src/downloadlist.ui" line="106"/>
|
||||
<source>Name</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../downloadlist.ui" line="189"/>
|
||||
<location filename="../src/downloadlist.ui" line="189"/>
|
||||
<source>Waiting to download</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../downloadlist.ui" line="240"/>
|
||||
<location filename="../src/downloadlist.ui" line="240"/>
|
||||
<source>Install</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../downloadlist.ui" line="259"/>
|
||||
<location filename="../src/downloadlist.ui" line="259"/>
|
||||
<source>Cancel</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../downloadlist.ui" line="278"/>
|
||||
<location filename="../src/downloadlist.ui" line="278"/>
|
||||
<source>Info</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../downloadlist.cpp" line="24"/>
|
||||
<source>dpkg</source>
|
||||
<location filename="../src/downloadlist.cpp" line="24"/>
|
||||
<source>Spark Store App Installer</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../downloadlist.cpp" line="25"/>
|
||||
<location filename="../src/downloadlist.cpp" line="25"/>
|
||||
<source>gdebi</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../downloadlist.cpp" line="26"/>
|
||||
<location filename="../src/downloadlist.cpp" line="26"/>
|
||||
<source>deepin deb installer</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../downloadlist.cpp" line="55"/>
|
||||
<location filename="../src/downloadlist.cpp" line="57"/>
|
||||
<source>Downloaded, waiting to install</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../downloadlist.cpp" line="80"/>
|
||||
<location filename="../src/downloadlist.cpp" line="82"/>
|
||||
<source>Failed to download %1</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../downloadlist.cpp" line="82"/>
|
||||
<location filename="../src/downloadlist.cpp" line="84"/>
|
||||
<source>Download Failed,Check Your Connection</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../downloadlist.cpp" line="92"/>
|
||||
<location filename="../src/downloadlist.cpp" line="94"/>
|
||||
<source>Finished downloading %1, awaiting to install</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../downloadlist.cpp" line="125"/>
|
||||
<location filename="../src/downloadlist.cpp" line="127"/>
|
||||
<source>Installing</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../downloadlist.cpp" line="172"/>
|
||||
<location filename="../src/downloadlist.cpp" line="174"/>
|
||||
<source>Finish</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../downloadlist.cpp" line="176"/>
|
||||
<location filename="../src/downloadlist.cpp" line="178"/>
|
||||
<source>Retry</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../downloadlist.cpp" line="177"/>
|
||||
<location filename="../src/downloadlist.cpp" line="179"/>
|
||||
<source>Error happened in dpkg progress , you can try it again</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../downloadlist.cpp" line="181"/>
|
||||
<location filename="../src/downloadlist.cpp" line="183"/>
|
||||
<source>dpkg progress had been aborted,you can retry installation</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../downloadlist.cpp" line="203"/>
|
||||
<location filename="../src/downloadlist.cpp" line="205"/>
|
||||
<source>Download canceled</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||