更新目录结构
73
Components/MultiplethreadDownload/.gitignore
vendored
Normal file
@@ -0,0 +1,73 @@
|
||||
# This file is used to ignore files which are generated
|
||||
# ----------------------------------------------------------------------------
|
||||
|
||||
*~
|
||||
*.autosave
|
||||
*.a
|
||||
*.core
|
||||
*.moc
|
||||
*.o
|
||||
*.obj
|
||||
*.orig
|
||||
*.rej
|
||||
*.so
|
||||
*.so.*
|
||||
*_pch.h.cpp
|
||||
*_resource.rc
|
||||
*.qm
|
||||
.#*
|
||||
*.*#
|
||||
core
|
||||
!core/
|
||||
tags
|
||||
.DS_Store
|
||||
.directory
|
||||
*.debug
|
||||
Makefile*
|
||||
*.prl
|
||||
*.app
|
||||
moc_*.cpp
|
||||
ui_*.h
|
||||
qrc_*.cpp
|
||||
Thumbs.db
|
||||
*.res
|
||||
*.rc
|
||||
/.qmake.cache
|
||||
/.qmake.stash
|
||||
|
||||
# qtcreator generated files
|
||||
*.pro.user*
|
||||
|
||||
# xemacs temporary files
|
||||
*.flc
|
||||
|
||||
# Vim temporary files
|
||||
.*.swp
|
||||
|
||||
# Visual Studio generated files
|
||||
*.ib_pdb_index
|
||||
*.idb
|
||||
*.ilk
|
||||
*.pdb
|
||||
*.sln
|
||||
*.suo
|
||||
*.vcproj
|
||||
*vcproj.*.*.user
|
||||
*.ncb
|
||||
*.sdf
|
||||
*.opensdf
|
||||
*.vcxproj
|
||||
*vcxproj.*
|
||||
|
||||
# MinGW generated files
|
||||
*.Debug
|
||||
*.Release
|
||||
|
||||
# Python byte code
|
||||
*.pyc
|
||||
|
||||
# Binaries
|
||||
# --------
|
||||
*.dll
|
||||
*.exe
|
||||
|
||||
28
Components/MultiplethreadDownload/MultiplethreadDownload.pro
Normal file
@@ -0,0 +1,28 @@
|
||||
QT += core gui network concurrent
|
||||
|
||||
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
|
||||
|
||||
CONFIG += c++17
|
||||
|
||||
# You can make your code fail to compile if it uses deprecated APIs.
|
||||
# In order to do so, uncomment the following line.
|
||||
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0
|
||||
|
||||
SOURCES += \
|
||||
downloadworker.cpp \
|
||||
main.cpp \
|
||||
utils.cpp \
|
||||
widget.cpp
|
||||
|
||||
HEADERS += \
|
||||
downloadworker.h \
|
||||
utils.h \
|
||||
widget.h
|
||||
|
||||
FORMS += \
|
||||
widget.ui
|
||||
|
||||
# Default rules for deployment.
|
||||
qnx: target.path = /tmp/$${TARGET}/bin
|
||||
else: unix:!android: target.path = /opt/$${TARGET}/bin
|
||||
!isEmpty(target.path): INSTALLS += target
|
||||
103
Components/MultiplethreadDownload/REAMDE.md
Normal file
@@ -0,0 +1,103 @@
|
||||
文件大小为: 2521709
|
||||
开始下载文件
|
||||
开始下载数据: 1891281~2521709 -> writePos Start 1891281
|
||||
开始下载数据: 0~630426 -> writePos Start 0
|
||||
开始下载数据: 630427~1260853 -> writePos Start 630427
|
||||
开始下载数据: 1260854~1891280 -> writePos Start 1260854
|
||||
|
||||
|
||||
文件大小为: 89937570
|
||||
开始下载文件
|
||||
开始下载数据: " 0~22484391 -> writePos Start 0"
|
||||
开始下载数据: " 22484392~44968783 -> writePos Start 22484392"
|
||||
开始下载数据: " 44968784~67453175 -> writePos Start 44968784"
|
||||
开始下载数据: " 67453176~89937570 -> writePos Start 67453176
|
||||
|
||||
|
||||
# 星火商店多线程下载说明
|
||||
现在的这个多线程下载已经可以了,但是暂停恢复不太好控制,所以还是用 QThread 来做暂停控制,即使线程数超过CPU
|
||||
核数问题也不大,因为下载并不是CPU密集操作,完全没问题的。总体的精细的线程池控制后续技术强大了再来封装好了。
|
||||
|
||||
先做好这个功能,后续再来研究DTK库,各个组件的使用,已经如何自己封装漂亮的控件,摆脱DTK的依赖。
|
||||
再后面,写一个Qt开发Linux应用的教程,先建立起星火商店单独的开发者博客,专门用来发技术文章。
|
||||
|
||||
星火商店的几个源服务器,源列表写在
|
||||
```sh
|
||||
$ cat /etc/apt/sources.list.d/sparkstore.list
|
||||
deb [by-hash=force] https://sucdn.jerrywang.top /
|
||||
```
|
||||
|
||||
服务器源列表 http://dcstore.shenmo.tech/store/server.list
|
||||
```js
|
||||
https://sucdn.jerrywang.top/
|
||||
国内推荐 China Lines
|
||||
https://sucdn.jerrywang.top/
|
||||
https://store.deepinos.org.cn/
|
||||
国外推荐 Global Lines
|
||||
开发者模式 Dev only
|
||||
http://localhost:8080/
|
||||
用户贡献 Community lines
|
||||
```
|
||||
|
||||
也就是目前的就两个服务器了
|
||||
* https://sucdn.jerrywang.top/
|
||||
* https://store.deepinos.org.cn/
|
||||
|
||||
|
||||
原来的单线程相关代码
|
||||
```cpp
|
||||
// 在处理下载进度的代码中,会一直检测下载是否取消
|
||||
void Widget::updateDataReadProgress(qint64 bytesRead, qint64 totalBytes)
|
||||
{
|
||||
if(totalBytes <= 0) return;
|
||||
download_list[nowDownload-1].setMax(10000); // 最大值
|
||||
download_list[nowDownload-1].setValue((bytesRead*10000)/totalBytes); // 当前值
|
||||
download_size=bytesRead;
|
||||
if(download_list[nowDownload-1].close){ // 随时检测下载是否被取消
|
||||
download_list[nowDownload-1].closeDownload();
|
||||
httpFinished();
|
||||
}
|
||||
}
|
||||
// 但是这里的 download_list[nowDownload-1].close 是在哪里修改的呢?
|
||||
downloadlist download_list[LIST_MAX];
|
||||
download_list 是一个下载进度组件,维持动画的,还不错。
|
||||
|
||||
// 星火商店记录下载进度的代码
|
||||
void Widget::updateDataReadProgress(qint64 bytesRead, qint64 totalBytes)
|
||||
{
|
||||
if(totalBytes <= 0) return;
|
||||
download_list[nowDownload-1].setMax(10000); // 最大值
|
||||
download_list[nowDownload-1].setValue((bytesRead*10000)/totalBytes); // 当前值
|
||||
download_size=bytesRead;
|
||||
if(download_list[nowDownload-1].close){ // 随时检测下载是否被取消
|
||||
download_list[nowDownload-1].closeDownload();
|
||||
httpFinished();
|
||||
}
|
||||
}
|
||||
|
||||
void Widget::httpFinished() // 完成下载
|
||||
{
|
||||
file->flush();
|
||||
file->close();
|
||||
reply->deleteLater();
|
||||
reply = nullptr;
|
||||
delete file;
|
||||
file = nullptr;
|
||||
isdownload=false;
|
||||
isBusy=false;
|
||||
}
|
||||
```
|
||||
|
||||
然后那个多线程下载组件需要的几个功能点:
|
||||
* 下载进度,以及下载速度记录
|
||||
* 下载取消功能
|
||||
* 读取设置,允许设置单线程下载 这个可以放到后面做,优先实现上面两个
|
||||
|
||||
多域名测试下载,现在单个域名至多5M,DNS解析均衡有延迟,因为DNS会有缓存。
|
||||
```url
|
||||
sucdn1.jerrywang.top
|
||||
sucdn2.jerrywang.top
|
||||
sucdn3.jerrywang.top
|
||||
sucdn4.jerrywang.top
|
||||
sucdn5.jerrywang.top
|
||||
```
|
||||
183
Components/MultiplethreadDownload/downloadworker.cpp
Normal file
@@ -0,0 +1,183 @@
|
||||
#include "downloadworker.h"
|
||||
#include <QIODevice>
|
||||
#include <QEventLoop>
|
||||
#include <QNetworkAccessManager>
|
||||
#include <QNetworkRequest>
|
||||
#include <QNetworkReply>
|
||||
#include <QDebug>
|
||||
#include <QThread>
|
||||
|
||||
DownloadWorker::DownloadWorker(QObject *parent)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void DownloadWorker::setIdentifier(int identifier)
|
||||
{
|
||||
this->identifier = identifier;
|
||||
}
|
||||
|
||||
void DownloadWorker::setParamter(const QString &url, QPair<qint64, qint64> range, QFile *file)
|
||||
{
|
||||
this->url = url;
|
||||
this->startPos = range.first;
|
||||
this->endPos = range.second;
|
||||
this->file = file;
|
||||
}
|
||||
|
||||
qint64 DownloadWorker::getReceivedPos()
|
||||
{
|
||||
return receivedPos;
|
||||
}
|
||||
|
||||
void DownloadWorker::doWork()
|
||||
{
|
||||
mgr = new QNetworkAccessManager(this);
|
||||
QNetworkRequest request;
|
||||
request.setUrl(url);
|
||||
request.setAttribute(QNetworkRequest::FollowRedirectsAttribute, true);
|
||||
request.setRawHeader("Range", QString("bytes=%1-%2").arg(startPos)
|
||||
.arg(endPos).toLocal8Bit());
|
||||
reply = mgr->get(request);
|
||||
qDebug() << "开始下载数据:" << QString(" %1~%2 -> writePos Start %3")
|
||||
.arg(startPos).arg(endPos).arg(receivedPos);
|
||||
connect(reply, &QNetworkReply::errorOccurred, [this](QNetworkReply::NetworkError error){
|
||||
if (error != QNetworkReply::NoError) {
|
||||
qDebug() << "出错了:" << reply->errorString();
|
||||
}
|
||||
});
|
||||
connect(reply, &QNetworkReply::finished, mgr, &QNetworkAccessManager::deleteLater);
|
||||
connect(reply, &QNetworkReply::finished, reply, &QNetworkReply::deleteLater);
|
||||
connect(reply, &QNetworkReply::readyRead, this, &DownloadWorker::dataReady);
|
||||
connect(reply, &QNetworkReply::finished, this, &DownloadWorker::slotFinish);
|
||||
connect(reply, &QNetworkReply::downloadProgress, this, &DownloadWorker::handleProcess);
|
||||
|
||||
}
|
||||
|
||||
void DownloadWorker::doStop()
|
||||
{
|
||||
reply->deleteLater();
|
||||
reply = nullptr;
|
||||
mgr->deleteLater();
|
||||
mgr = nullptr;
|
||||
}
|
||||
|
||||
void DownloadWorker::dataReady()
|
||||
{
|
||||
qDebug() << QString("测试是否执行: %1 %2").arg(startPos).arg(receivedPos);
|
||||
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)
|
||||
{
|
||||
this->threadNum = 4;
|
||||
}
|
||||
|
||||
void DownloadController::setFilename(QString filename)
|
||||
{
|
||||
this->filename = filename;
|
||||
}
|
||||
|
||||
void DownloadController::setThreadNum(int threadNum)
|
||||
{
|
||||
this->threadNum = threadNum;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 开始下载
|
||||
*/
|
||||
void DownloadController::startDownload(const QString &url, qint64 fileSize)
|
||||
{
|
||||
finish = 0;
|
||||
|
||||
// 下载任务等分,计算每个线程的下载数据
|
||||
this->fileSize = fileSize;
|
||||
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; // 余数部分加入最后一个
|
||||
|
||||
// 打开文件
|
||||
file = new QFile;
|
||||
file->setFileName(filename);
|
||||
if (file->exists())
|
||||
file->remove();
|
||||
if (!file->open(QIODevice::WriteOnly)) {
|
||||
delete file;
|
||||
file = nullptr;
|
||||
emit errorOccur(file->errorString());
|
||||
return;
|
||||
}
|
||||
file->resize(fileSize);
|
||||
|
||||
// 创建下载线程
|
||||
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);
|
||||
worker->setIdentifier(i);
|
||||
worker->setParamter(url, 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();
|
||||
}
|
||||
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++;
|
||||
if (finish == threadNum) {
|
||||
emit downloadFinished();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
71
Components/MultiplethreadDownload/downloadworker.h
Normal file
@@ -0,0 +1,71 @@
|
||||
#ifndef DOWNLOADWORKER_H
|
||||
#define DOWNLOADWORKER_H
|
||||
|
||||
#include <QObject>
|
||||
#include <QList>
|
||||
#include <QFile>
|
||||
#include <QNetworkReply>
|
||||
|
||||
class DownloadWorker : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit DownloadWorker(QObject *parent = nullptr);
|
||||
void setIdentifier(int identifier);
|
||||
void setParamter(const QString &url, QPair<qint64, qint64> range, QFile *flle);
|
||||
qint64 getReceivedPos();
|
||||
|
||||
public slots:
|
||||
void doWork();
|
||||
void doStop();
|
||||
void dataReady();
|
||||
void slotFinish();
|
||||
void handleProcess(qint64, qint64);
|
||||
|
||||
signals:
|
||||
void resultReady(int identifier, QByteArray data);
|
||||
void testSignals();
|
||||
void workFinished();
|
||||
void downloadProcess();
|
||||
|
||||
private:
|
||||
int identifier;
|
||||
QString url;
|
||||
qint64 startPos;
|
||||
qint64 endPos;
|
||||
qint64 receivedPos = 0;
|
||||
QNetworkReply *reply;
|
||||
QNetworkAccessManager *mgr;
|
||||
QFile *file;
|
||||
};
|
||||
|
||||
class DownloadController : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit DownloadController(QObject *parent = nullptr);
|
||||
void setFilename(QString filename);
|
||||
void setThreadNum(int threadNum);
|
||||
void startDownload(const QString &url, qint64 fileSize);
|
||||
void stopDownload();
|
||||
|
||||
public slots:
|
||||
void handleProcess();
|
||||
void chunkDownloadFinish();
|
||||
|
||||
signals:
|
||||
void errorOccur(const QString& msg);
|
||||
void downloadProcess(qint64, qint64);
|
||||
void downloadFinished();
|
||||
|
||||
private:
|
||||
int threadNum;
|
||||
QString filename;
|
||||
qint64 fileSize;
|
||||
QVector<QPair<qint64, qint64>> ranges;
|
||||
QFile *file;
|
||||
QList<DownloadWorker*> workers;
|
||||
int finish = 0;
|
||||
};
|
||||
|
||||
#endif // FILEDOWNLOADWORKER_H
|
||||
13
Components/MultiplethreadDownload/main.cpp
Normal file
@@ -0,0 +1,13 @@
|
||||
#include "widget.h"
|
||||
|
||||
#include <QApplication>
|
||||
#include <QScreen>
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
QApplication a(argc, argv);
|
||||
Widget w;
|
||||
w.show();
|
||||
w.move(QApplication::screens().at(0)->geometry().center() - w.frameGeometry().center());
|
||||
return a.exec();
|
||||
}
|
||||
2104
Components/MultiplethreadDownload/process.csv
Normal file
BIN
Components/MultiplethreadDownload/screenshot.png
Normal file
|
After Width: | Height: | Size: 41 KiB |
21
Components/MultiplethreadDownload/utils.cpp
Normal file
@@ -0,0 +1,21 @@
|
||||
#include "utils.h"
|
||||
#include <QStringList>
|
||||
#include <QLocale>
|
||||
|
||||
|
||||
QString Utils::sizeFormat(qint64 bytes)
|
||||
{
|
||||
qreal size = bytes;
|
||||
QStringList list;
|
||||
list << "KB" << "MB" << "GB" << "TB";
|
||||
|
||||
QStringListIterator i(list);
|
||||
QString unit("bytes");
|
||||
|
||||
while (size >= 1024.0 && i.hasNext()) {
|
||||
unit = i.next();
|
||||
size /= 1024.0;
|
||||
}
|
||||
return QString().setNum(size, 'f', 2) + " " + unit;
|
||||
}
|
||||
|
||||
12
Components/MultiplethreadDownload/utils.h
Normal file
@@ -0,0 +1,12 @@
|
||||
#ifndef UTILS_H
|
||||
#define UTILS_H
|
||||
|
||||
#include <QtGlobal>
|
||||
|
||||
class Utils
|
||||
{
|
||||
public:
|
||||
static QString sizeFormat(qint64 bytes);
|
||||
};
|
||||
|
||||
#endif // UTILS_H
|
||||
262
Components/MultiplethreadDownload/widget.cpp
Normal file
@@ -0,0 +1,262 @@
|
||||
#include "widget.h"
|
||||
#include "ui_widget.h"
|
||||
#include "utils.h"
|
||||
#include <QUrl>
|
||||
#include <QNetworkReply>
|
||||
#include <QNetworkRequest>
|
||||
#include <QMessageBox>
|
||||
#include <QRegExp>
|
||||
#include <QRegExpValidator>
|
||||
#include <QFileDialog>
|
||||
#include <QDir>
|
||||
#include <QThread>
|
||||
#include <QEventLoop>
|
||||
#include <QFuture>
|
||||
#include <QtConcurrent/QtConcurrent>
|
||||
#include <QMutex>
|
||||
#include <downloadworker.h>
|
||||
|
||||
Widget::Widget(QWidget *parent)
|
||||
: QWidget(parent)
|
||||
, ui(new Ui::Widget)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
|
||||
// 设置URL链接验证器
|
||||
QRegExp regex(R"(https?:\/\/.+)");
|
||||
auto *validator = new QRegExpValidator(regex, nullptr);
|
||||
ui->urlInput->setValidator(validator);
|
||||
|
||||
// 设置最大的线程并发数
|
||||
int processer_num = QThread::idealThreadCount();
|
||||
processer_num = processer_num > maxThreadNum ? maxThreadNum : processer_num;
|
||||
ui->threadCountSpinbox->setMaximum(processer_num);
|
||||
ui->threadCountSpinbox->setValue(processer_num);
|
||||
|
||||
// 设置保存路径为当前程序运行路径
|
||||
ui->savePathInput->setText(QDir::currentPath());
|
||||
|
||||
requestManager = new QNetworkAccessManager(this);
|
||||
}
|
||||
|
||||
Widget::~Widget()
|
||||
{
|
||||
delete ui;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief 展示错误信息
|
||||
* @param msg
|
||||
*/
|
||||
void Widget::showError(const QString& msg)
|
||||
{
|
||||
auto msgBox = new QMessageBox(this);
|
||||
msgBox->setWindowTitle(tr("请求出错"));
|
||||
msgBox->setIcon(QMessageBox::Critical);
|
||||
msgBox->setText(msg);
|
||||
msgBox->exec();
|
||||
ui->downloadBtn->setEnabled(true);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 获取要下载的文件大小
|
||||
* @param url
|
||||
*/
|
||||
qint64 Widget::getFileSize(const QString& url)
|
||||
{
|
||||
QEventLoop event;
|
||||
QNetworkRequest request;
|
||||
request.setUrl(QUrl(url));
|
||||
request.setAttribute(QNetworkRequest::FollowRedirectsAttribute, true);
|
||||
QNetworkReply *reply = requestManager->head(request);
|
||||
connect(reply, &QNetworkReply::errorOccurred, [this, reply](QNetworkReply::NetworkError error){
|
||||
if (error != QNetworkReply::NoError) {
|
||||
return showError(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;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief 开始下载文件
|
||||
* @param url
|
||||
* @param filename
|
||||
*/
|
||||
void Widget::singleDownload(const QString& url, const QString& filename)
|
||||
{
|
||||
QFile file(filename);
|
||||
if (file.exists())
|
||||
file.remove();
|
||||
if (!file.open(QIODevice::WriteOnly)) {
|
||||
return showError(file.errorString());
|
||||
}
|
||||
|
||||
QEventLoop event;
|
||||
QNetworkAccessManager mgr;
|
||||
QNetworkRequest request;
|
||||
request.setUrl(QUrl(url));
|
||||
request.setAttribute(QNetworkRequest::FollowRedirectsAttribute, true);
|
||||
QNetworkReply *reply = mgr.get(request);
|
||||
connect(reply, &QNetworkReply::readyRead, this, [&file, reply](){
|
||||
file.write(reply->readAll());
|
||||
});
|
||||
connect(reply, &QNetworkReply::finished, &event, &QEventLoop::quit);
|
||||
connect(reply, &QNetworkReply::downloadProgress, this, &Widget::download_progress_change);
|
||||
connect(reply, &QNetworkReply::errorOccurred, [this, reply](QNetworkReply::NetworkError error){
|
||||
if (error != QNetworkReply::NoError) showError(reply->errorString());
|
||||
});
|
||||
event.exec();
|
||||
file.flush();
|
||||
file.close();
|
||||
ui->downloadBtn->setEnabled(true);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief 点击开始下载
|
||||
*/
|
||||
void Widget::on_downloadBtn_clicked()
|
||||
{
|
||||
QString url = ui->urlInput->text().trimmed();
|
||||
if (url.isEmpty()) {
|
||||
return showError(tr("请求链接不允许为空!"));
|
||||
return ;
|
||||
}
|
||||
|
||||
// 选择保存路径
|
||||
QString savePath = ui->savePathInput->text().trimmed();
|
||||
if (savePath.isEmpty()) {
|
||||
savePath = QFileDialog::getExistingDirectory();
|
||||
if (savePath.isEmpty()) return;
|
||||
} else {
|
||||
if(!QDir(savePath).exists()) {
|
||||
return showError(tr("路径不存在!"));
|
||||
}
|
||||
}
|
||||
|
||||
ui->downloadBtn->setEnabled(false);
|
||||
ui->downProgressBar->setValue(0);
|
||||
qint64 fileSize = getFileSize(url);
|
||||
QString sizeText = fileSize == 0 ? "未知大小" : Utils::sizeFormat(fileSize);
|
||||
ui->filesizeLabel->setText(sizeText);
|
||||
|
||||
int process_num = ui->threadCountSpinbox->text().toInt();
|
||||
|
||||
QDir::setCurrent(savePath);
|
||||
QString filename = QFileInfo(url).fileName();
|
||||
if (fileSize == 0 || process_num == 1) {
|
||||
singleDownload(url, filename);
|
||||
} else {
|
||||
multiDownloadWithQThread(url, fileSize, filename, process_num);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 设置保存下载文件的路径
|
||||
*/
|
||||
void Widget::on_brwoserPathBtn_clicked()
|
||||
{
|
||||
QString savePath = QFileDialog::getExistingDirectory();
|
||||
if (!savePath.isEmpty()) {
|
||||
ui->savePathInput->setText(savePath);
|
||||
}
|
||||
}
|
||||
|
||||
void Widget::download_progress_change(qint64 bytesReceived, qint64 bytesTotal)
|
||||
{
|
||||
if (bytesTotal <= 0)
|
||||
return;
|
||||
ui->downProgressBar->setMaximum(10000); // 最大值
|
||||
ui->downProgressBar->setValue((bytesReceived * 10000) / bytesTotal); // 当前值
|
||||
ui->downProgressBar->setTextVisible(true);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 多线程下载
|
||||
* @param url
|
||||
* @param fileSize
|
||||
* @param filename
|
||||
* @param threadCount
|
||||
*/
|
||||
void Widget::multiDownloadWithQtConcurrent(const QString &url, qint64 fileSize, const QString &filename, int threadCount)
|
||||
{
|
||||
QFile file(filename);
|
||||
if (file.exists())
|
||||
file.remove();
|
||||
if (!file.open(QIODevice::WriteOnly)) {
|
||||
return showError(file.errorString());
|
||||
}
|
||||
file.resize(fileSize);
|
||||
|
||||
qDebug() << "开始下载文件";
|
||||
// 任务等分
|
||||
qint64 segmentSize = fileSize / threadCount;
|
||||
QVector<QPair<qint64, qint64>> vec(threadCount);
|
||||
for (int i = 0; i < threadCount; i++) {
|
||||
vec[i].first = i * segmentSize;
|
||||
vec[i].second = i * segmentSize + segmentSize - 1;
|
||||
}
|
||||
vec[threadCount-1].second = fileSize; // 余数部分加入最后一个
|
||||
|
||||
qint64 bytesReceived = 0; // 下载接收的总字节数
|
||||
QMutex lock;
|
||||
// 任务队列
|
||||
auto mapCaller = [&, this](const QPair<qint64, qint64>& pair) -> qint64 {
|
||||
QEventLoop event;
|
||||
QNetworkAccessManager mgr;
|
||||
QNetworkRequest request;
|
||||
request.setUrl(url);
|
||||
request.setAttribute(QNetworkRequest::FollowRedirectsAttribute, true);
|
||||
request.setRawHeader("Range", QString("bytes=%1-%2").arg(pair.first).arg(pair.second).toLocal8Bit());
|
||||
QNetworkReply *reply = mgr.get(request);
|
||||
qint64 writePos = pair.first;
|
||||
qDebug() << "开始下载数据:" << QString(" %1~%2 -> writePos Start %3")
|
||||
.arg(pair.first).arg(pair.second).arg(writePos);
|
||||
connect(reply, &QNetworkReply::readyRead, [&lock, &writePos, &file, &bytesReceived, reply](){
|
||||
QByteArray data = reply->readAll();
|
||||
{
|
||||
QMutexLocker mLock(&lock);
|
||||
// qDebug() << "调整文件的数据指针:" << writePos;
|
||||
file.seek(writePos);
|
||||
file.write(data);
|
||||
bytesReceived += data.size();
|
||||
qDebug() << QString("%1, %2, %3")
|
||||
.arg(writePos).arg(bytesReceived).arg(data.size());
|
||||
}
|
||||
writePos += data.size();
|
||||
});
|
||||
connect(reply, &QNetworkReply::finished, &event, &QEventLoop::quit);
|
||||
event.exec();
|
||||
return writePos - pair.first;
|
||||
};
|
||||
QFuture<void> future = QtConcurrent::map(vec, mapCaller);
|
||||
QFutureWatcher<void> futureWatcher;
|
||||
QEventLoop loop;
|
||||
connect(&futureWatcher, &QFutureWatcher<void>::finished, &loop, &QEventLoop::quit, Qt::QueuedConnection);
|
||||
futureWatcher.setFuture(future);
|
||||
if (!future.isFinished()) {
|
||||
loop.exec();
|
||||
}
|
||||
file.close();
|
||||
qDebug() << "下载完毕!!";
|
||||
ui->downloadBtn->setEnabled(true);
|
||||
}
|
||||
|
||||
void Widget::multiDownloadWithQThread(const QString& url, qint64 fileSize, const QString& filename, int threadCount)
|
||||
{
|
||||
DownloadController *download = new DownloadController(this);
|
||||
download->setFilename(filename);
|
||||
download->startDownload(url, fileSize);
|
||||
connect(download, &DownloadController::downloadProcess, this, &Widget::download_progress_change);
|
||||
}
|
||||
38
Components/MultiplethreadDownload/widget.h
Normal file
@@ -0,0 +1,38 @@
|
||||
#ifndef WIDGET_H
|
||||
#define WIDGET_H
|
||||
|
||||
#include <QWidget>
|
||||
#include <QNetworkAccessManager>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
namespace Ui { class Widget; }
|
||||
QT_END_NAMESPACE
|
||||
|
||||
class Widget : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
Widget(QWidget *parent = nullptr);
|
||||
~Widget();
|
||||
|
||||
protected:
|
||||
void showError(const QString& msg);
|
||||
qint64 getFileSize(const QString& url);
|
||||
void singleDownload(const QString& url, const QString& filename);
|
||||
void multiDownloadWithQtConcurrent(const QString& url, qint64 fileSize, const QString& filename, int threadCount);
|
||||
void multiDownloadWithQThread(const QString& url, qint64 fileSize, const QString& filename, int threadCount);
|
||||
|
||||
|
||||
private slots:
|
||||
void on_downloadBtn_clicked();
|
||||
void on_brwoserPathBtn_clicked();
|
||||
void download_progress_change(qint64 bytesReceived, qint64 bytesTotal);
|
||||
|
||||
private:
|
||||
QNetworkAccessManager *requestManager;
|
||||
const int maxThreadNum = 8;
|
||||
|
||||
Ui::Widget *ui;
|
||||
};
|
||||
#endif // WIDGET_H
|
||||
169
Components/MultiplethreadDownload/widget.ui
Normal file
@@ -0,0 +1,169 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>Widget</class>
|
||||
<widget class="QWidget" name="Widget">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>635</width>
|
||||
<height>209</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>16777215</width>
|
||||
<height>209</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>多线程下载文件Demo</string>
|
||||
</property>
|
||||
<property name="styleSheet">
|
||||
<string notr="true">font-family: "Microsoft Yahei";</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<property name="sizeConstraint">
|
||||
<enum>QLayout::SetDefaultConstraint</enum>
|
||||
</property>
|
||||
<item>
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="text">
|
||||
<string>URL:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QLineEdit" name="urlInput">
|
||||
<property name="text">
|
||||
<string>http://sucdn.jerrywang.top/store/network/microsoft-edge-dev/microsoft-edge-dev_89.0.731.0-1_amd64.deb </string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="2">
|
||||
<widget class="QPushButton" name="downloadBtn">
|
||||
<property name="text">
|
||||
<string>下载</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="label_2">
|
||||
<property name="text">
|
||||
<string>保存路径:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QLineEdit" name="savePathInput"/>
|
||||
</item>
|
||||
<item row="1" column="2">
|
||||
<widget class="QPushButton" name="brwoserPathBtn">
|
||||
<property name="text">
|
||||
<string>浏览</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="label_3">
|
||||
<property name="text">
|
||||
<string>原始线程数:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QSpinBox" name="threadCountSpinbox">
|
||||
<property name="minimum">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<property name="value">
|
||||
<number>1</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="2">
|
||||
<widget class="QPushButton" name="pauseBtn">
|
||||
<property name="text">
|
||||
<string>暂停</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<widget class="QLabel" name="label_4">
|
||||
<property name="text">
|
||||
<string>下载进度:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1">
|
||||
<widget class="QProgressBar" name="downProgressBar">
|
||||
<property name="value">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="textVisible">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="textDirection">
|
||||
<enum>QProgressBar::TopToBottom</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="2">
|
||||
<widget class="QCheckBox" name="dwnFinishedOpenChbox">
|
||||
<property name="font">
|
||||
<font>
|
||||
<family>Microsoft Yahei</family>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>下载完成是否打开</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<item>
|
||||
<widget class="QLabel" name="label_5">
|
||||
<property name="text">
|
||||
<string>下载速度:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="downloadSpeedLabel">
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="label_7">
|
||||
<property name="text">
|
||||
<string>文件大小:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="filesizeLabel">
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
||||
73
Components/QProxyStyleTest/.gitignore
vendored
Normal file
@@ -0,0 +1,73 @@
|
||||
# This file is used to ignore files which are generated
|
||||
# ----------------------------------------------------------------------------
|
||||
|
||||
*~
|
||||
*.autosave
|
||||
*.a
|
||||
*.core
|
||||
*.moc
|
||||
*.o
|
||||
*.obj
|
||||
*.orig
|
||||
*.rej
|
||||
*.so
|
||||
*.so.*
|
||||
*_pch.h.cpp
|
||||
*_resource.rc
|
||||
*.qm
|
||||
.#*
|
||||
*.*#
|
||||
core
|
||||
!core/
|
||||
tags
|
||||
.DS_Store
|
||||
.directory
|
||||
*.debug
|
||||
Makefile*
|
||||
*.prl
|
||||
*.app
|
||||
moc_*.cpp
|
||||
ui_*.h
|
||||
qrc_*.cpp
|
||||
Thumbs.db
|
||||
*.res
|
||||
*.rc
|
||||
/.qmake.cache
|
||||
/.qmake.stash
|
||||
|
||||
# qtcreator generated files
|
||||
*.pro.user*
|
||||
|
||||
# xemacs temporary files
|
||||
*.flc
|
||||
|
||||
# Vim temporary files
|
||||
.*.swp
|
||||
|
||||
# Visual Studio generated files
|
||||
*.ib_pdb_index
|
||||
*.idb
|
||||
*.ilk
|
||||
*.pdb
|
||||
*.sln
|
||||
*.suo
|
||||
*.vcproj
|
||||
*vcproj.*.*.user
|
||||
*.ncb
|
||||
*.sdf
|
||||
*.opensdf
|
||||
*.vcxproj
|
||||
*vcxproj.*
|
||||
|
||||
# MinGW generated files
|
||||
*.Debug
|
||||
*.Release
|
||||
|
||||
# Python byte code
|
||||
*.pyc
|
||||
|
||||
# Binaries
|
||||
# --------
|
||||
*.dll
|
||||
*.exe
|
||||
|
||||
29
Components/QProxyStyleTest/QProxyStyleTest.pro
Normal file
@@ -0,0 +1,29 @@
|
||||
QT += core gui
|
||||
|
||||
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
|
||||
|
||||
CONFIG += c++11
|
||||
|
||||
# You can make your code fail to compile if it uses deprecated APIs.
|
||||
# In order to do so, uncomment the following line.
|
||||
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0
|
||||
|
||||
SOURCES += \
|
||||
main.cpp \
|
||||
menubtnstyle.cpp \
|
||||
widget.cpp
|
||||
|
||||
HEADERS += \
|
||||
menubtnstyle.h \
|
||||
widget.h
|
||||
|
||||
FORMS += \
|
||||
widget.ui
|
||||
|
||||
RESOURCES += \
|
||||
icons.qrc
|
||||
|
||||
# Default rules for deployment.
|
||||
qnx: target.path = /tmp/$${TARGET}/bin
|
||||
else: unix:!android: target.path = /opt/$${TARGET}/bin
|
||||
!isEmpty(target.path): INSTALLS += target
|
||||
36
Components/QProxyStyleTest/icons.qrc
Normal file
@@ -0,0 +1,36 @@
|
||||
<RCC>
|
||||
<qresource prefix="/icons">
|
||||
<file>icons/category_chat_dark.svg</file>
|
||||
<file>icons/category_chat.svg</file>
|
||||
<file>icons/category_develop_dark.svg</file>
|
||||
<file>icons/category_develop.svg</file>
|
||||
<file>icons/category_game_dark.svg</file>
|
||||
<file>icons/category_game.svg</file>
|
||||
<file>icons/category_graphic_dark.svg</file>
|
||||
<file>icons/category_graphic.svg</file>
|
||||
<file>icons/category_music_dark.svg</file>
|
||||
<file>icons/category_music.svg</file>
|
||||
<file>icons/category_network_dark.svg</file>
|
||||
<file>icons/category_network.svg</file>
|
||||
<file>icons/category_office_dark.svg</file>
|
||||
<file>icons/category_office.svg</file>
|
||||
<file>icons/category_others_dark.svg</file>
|
||||
<file>icons/category_others.svg</file>
|
||||
<file>icons/category_reading_dark.svg</file>
|
||||
<file>icons/category_reading.svg</file>
|
||||
<file>icons/category_system_dark.svg</file>
|
||||
<file>icons/category_system.svg</file>
|
||||
<file>icons/category_video_dark.svg</file>
|
||||
<file>icons/category_video.svg</file>
|
||||
<file>icons/downloads-symbolic_dark.svg</file>
|
||||
<file>icons/downloads-symbolic.svg</file>
|
||||
<file>icons/theme-symbolic_dark.svg</file>
|
||||
<file>icons/theme-symbolic.svg</file>
|
||||
<file>icons/homepage.svg</file>
|
||||
<file>icons/homepage_dark.svg</file>
|
||||
<file>icons/category_active_dark.svg</file>
|
||||
<file>icons/category_active.svg</file>
|
||||
<file>icons/refresh-page-dark.svg</file>
|
||||
<file>icons/refresh-page.svg</file>
|
||||
</qresource>
|
||||
</RCC>
|
||||
125
Components/QProxyStyleTest/icons/category_active.svg
Normal file
@@ -0,0 +1,125 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
width="16px"
|
||||
height="16px"
|
||||
viewBox="0 0 16 16"
|
||||
version="1.1"
|
||||
id="svg22"
|
||||
sodipodi:docname="category_active_16px_l.svg"
|
||||
inkscape:version="0.92.4 (5da689c313, 2019-01-14)">
|
||||
<metadata
|
||||
id="metadata26">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title>category_active_16px</dc:title>
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<sodipodi:namedview
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1"
|
||||
objecttolerance="10"
|
||||
gridtolerance="10"
|
||||
guidetolerance="10"
|
||||
inkscape:pageopacity="0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:window-width="1920"
|
||||
inkscape:window-height="987"
|
||||
id="namedview24"
|
||||
showgrid="false"
|
||||
inkscape:zoom="14.75"
|
||||
inkscape:cx="-4"
|
||||
inkscape:cy="8"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="0"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="svg22" />
|
||||
<!-- Generator: Sketch 3.6.1 (26313) - http://www.bohemiancoding.com/sketch -->
|
||||
<title
|
||||
id="title2">category_active_16px</title>
|
||||
<desc
|
||||
id="desc4">Created with Sketch.</desc>
|
||||
<defs
|
||||
id="defs6" />
|
||||
<g
|
||||
id="Page-1"
|
||||
stroke="none"
|
||||
stroke-width="1"
|
||||
fill="none"
|
||||
fill-rule="evenodd"
|
||||
style="fill:#000000;fill-opacity:0.94999999">
|
||||
<g
|
||||
id="category_active_16px"
|
||||
style="fill:#000000;fill-opacity:0.94999999">
|
||||
<rect
|
||||
id="Rectangle-1-Copy-44"
|
||||
fill="#747568"
|
||||
opacity="0"
|
||||
x="0"
|
||||
y="0"
|
||||
width="16"
|
||||
height="16"
|
||||
style="fill:#000000;fill-opacity:0.94999999" />
|
||||
<g
|
||||
id="Group-2"
|
||||
transform="translate(2.000000, 2.000000)"
|
||||
fill="#FFFFFF"
|
||||
style="fill:#000000;fill-opacity:0.94999999">
|
||||
<rect
|
||||
id="Rectangle-94"
|
||||
x="0"
|
||||
y="0"
|
||||
width="2"
|
||||
height="2"
|
||||
style="fill:#000000;fill-opacity:0.94999999" />
|
||||
<rect
|
||||
id="Rectangle-97"
|
||||
x="3"
|
||||
y="0"
|
||||
width="9"
|
||||
height="2"
|
||||
style="fill:#000000;fill-opacity:0.94999999" />
|
||||
<rect
|
||||
id="rect11"
|
||||
x="0"
|
||||
y="5"
|
||||
width="2"
|
||||
height="2"
|
||||
style="fill:#000000;fill-opacity:0.94999999" />
|
||||
<rect
|
||||
id="rect13"
|
||||
x="3"
|
||||
y="5"
|
||||
width="9"
|
||||
height="2"
|
||||
style="fill:#000000;fill-opacity:0.94999999" />
|
||||
<rect
|
||||
id="rect15"
|
||||
x="0"
|
||||
y="10"
|
||||
width="2"
|
||||
height="2"
|
||||
style="fill:#000000;fill-opacity:0.94999999" />
|
||||
<rect
|
||||
id="rect17"
|
||||
x="3"
|
||||
y="10"
|
||||
width="9"
|
||||
height="2"
|
||||
style="fill:#000000;fill-opacity:0.94999999" />
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 3.3 KiB |
124
Components/QProxyStyleTest/icons/category_active_dark.svg
Normal file
@@ -0,0 +1,124 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
width="16px"
|
||||
height="16px"
|
||||
viewBox="0 0 16 16"
|
||||
version="1.1"
|
||||
id="svg22"
|
||||
sodipodi:docname="category_active_16px.svg"
|
||||
inkscape:version="0.92.4 (5da689c313, 2019-01-14)">
|
||||
<metadata
|
||||
id="metadata26">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<sodipodi:namedview
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1"
|
||||
objecttolerance="10"
|
||||
gridtolerance="10"
|
||||
guidetolerance="10"
|
||||
inkscape:pageopacity="0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:window-width="1920"
|
||||
inkscape:window-height="987"
|
||||
id="namedview24"
|
||||
showgrid="false"
|
||||
inkscape:zoom="14.75"
|
||||
inkscape:cx="8"
|
||||
inkscape:cy="8"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="0"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="svg22" />
|
||||
<!-- Generator: Sketch 3.6.1 (26313) - http://www.bohemiancoding.com/sketch -->
|
||||
<title
|
||||
id="title2">category_active_16px</title>
|
||||
<desc
|
||||
id="desc4">Created with Sketch.</desc>
|
||||
<defs
|
||||
id="defs6" />
|
||||
<g
|
||||
id="Page-1"
|
||||
stroke="none"
|
||||
stroke-width="1"
|
||||
fill="none"
|
||||
fill-rule="evenodd"
|
||||
style="fill:#ffffff;fill-opacity:0.60000002">
|
||||
<g
|
||||
id="category_active_16px"
|
||||
style="fill:#ffffff;fill-opacity:0.60000002">
|
||||
<rect
|
||||
id="Rectangle-1-Copy-44"
|
||||
fill="#747568"
|
||||
opacity="0"
|
||||
x="0"
|
||||
y="0"
|
||||
width="16"
|
||||
height="16"
|
||||
style="fill:#ffffff;fill-opacity:0.60000002" />
|
||||
<g
|
||||
id="Group-2"
|
||||
transform="translate(2.000000, 2.000000)"
|
||||
fill="#FFFFFF"
|
||||
style="fill:#ffffff;fill-opacity:0.60000002">
|
||||
<rect
|
||||
id="Rectangle-94"
|
||||
x="0"
|
||||
y="0"
|
||||
width="2"
|
||||
height="2"
|
||||
style="fill:#ffffff;fill-opacity:0.60000002" />
|
||||
<rect
|
||||
id="Rectangle-97"
|
||||
x="3"
|
||||
y="0"
|
||||
width="9"
|
||||
height="2"
|
||||
style="fill:#ffffff;fill-opacity:0.60000002" />
|
||||
<rect
|
||||
id="rect11"
|
||||
x="0"
|
||||
y="5"
|
||||
width="2"
|
||||
height="2"
|
||||
style="fill:#ffffff;fill-opacity:0.60000002" />
|
||||
<rect
|
||||
id="rect13"
|
||||
x="3"
|
||||
y="5"
|
||||
width="9"
|
||||
height="2"
|
||||
style="fill:#ffffff;fill-opacity:0.60000002" />
|
||||
<rect
|
||||
id="rect15"
|
||||
x="0"
|
||||
y="10"
|
||||
width="2"
|
||||
height="2"
|
||||
style="fill:#ffffff;fill-opacity:0.60000002" />
|
||||
<rect
|
||||
id="rect17"
|
||||
x="3"
|
||||
y="10"
|
||||
width="9"
|
||||
height="2"
|
||||
style="fill:#ffffff;fill-opacity:0.60000002" />
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 3.3 KiB |
3
Components/QProxyStyleTest/icons/category_chat.svg
Normal file
@@ -0,0 +1,3 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
|
||||
<path fill-rule="evenodd" d="M0.09791679,7.31479943 C0.09791679,3.53173257 3.65198565,0.5 8,0.5 C12.3485596,0.5 15.9020832,3.53150012 15.9020832,7.31479943 C15.9020832,11.0972813 12.3485704,14.127954 8,14.127954 C7.06316558,14.127954 6.1471898,13.9862478 5.28311727,13.7134084 L2.55321759,15.327403 C2.15529088,15.5626687 1.67860204,15.1782665 1.82419813,14.7395213 L2.62951677,12.3127412 C1.03368368,11.0385392 0.09791679,9.24513974 0.09791679,7.31479943 Z M4.7455,6.9148 C4.7455,6.2248 4.1855,5.6648 3.4955,5.6648 C2.8055,5.6648 2.2455,6.2248 2.2455,6.9148 C2.2455,7.6048 2.8055,8.1648 3.4955,8.1648 C4.1855,8.1648 4.7455,7.6048 4.7455,6.9148 Z M9.2504,6.9148 C9.2504,6.2248 8.6904,5.6648 8.0004,5.6648 C7.3104,5.6648 6.7504,6.2248 6.7504,6.9148 C6.7504,7.6048 7.3104,8.1648 8.0004,8.1648 C8.6904,8.1648 9.2504,7.6048 9.2504,6.9148 Z M13.766,6.9148 C13.766,6.2248 13.206,5.6648 12.516,5.6648 C11.826,5.6648 11.266,6.2248 11.266,6.9148 C11.266,7.6048 11.826,8.1648 12.516,8.1648 C13.206,8.1648 13.766,7.6048 13.766,6.9148 Z"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.1 KiB |
3
Components/QProxyStyleTest/icons/category_chat_dark.svg
Normal file
@@ -0,0 +1,3 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
|
||||
<path fill="#FFF" fill-opacity=".6" fill-rule="evenodd" d="M0.09791679,7.31479943 C0.09791679,3.53173257 3.65198565,0.5 8,0.5 C12.3485596,0.5 15.9020832,3.53150012 15.9020832,7.31479943 C15.9020832,11.0972813 12.3485704,14.127954 8,14.127954 C7.06316558,14.127954 6.1471898,13.9862478 5.28311727,13.7134084 L2.55321759,15.327403 C2.15529088,15.5626687 1.67860204,15.1782665 1.82419813,14.7395213 L2.62951677,12.3127412 C1.03368368,11.0385392 0.09791679,9.24513974 0.09791679,7.31479943 Z M4.7455,6.9148 C4.7455,6.2248 4.1855,5.6648 3.4955,5.6648 C2.8055,5.6648 2.2455,6.2248 2.2455,6.9148 C2.2455,7.6048 2.8055,8.1648 3.4955,8.1648 C4.1855,8.1648 4.7455,7.6048 4.7455,6.9148 Z M9.2504,6.9148 C9.2504,6.2248 8.6904,5.6648 8.0004,5.6648 C7.3104,5.6648 6.7504,6.2248 6.7504,6.9148 C6.7504,7.6048 7.3104,8.1648 8.0004,8.1648 C8.6904,8.1648 9.2504,7.6048 9.2504,6.9148 Z M13.766,6.9148 C13.766,6.2248 13.206,5.6648 12.516,5.6648 C11.826,5.6648 11.266,6.2248 11.266,6.9148 C11.266,7.6048 11.826,8.1648 12.516,8.1648 C13.206,8.1648 13.766,7.6048 13.766,6.9148 Z"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.1 KiB |
3
Components/QProxyStyleTest/icons/category_develop.svg
Normal file
@@ -0,0 +1,3 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
|
||||
<path fill-rule="evenodd" d="M3,2 L13,2 C14.1045695,2 15,2.8954305 15,4 L15,12 C15,13.1045695 14.1045695,14 13,14 L3,14 C1.8954305,14 1,13.1045695 1,12 L1,4 C1,2.8954305 1.8954305,2 3,2 Z M3.76776695,5.35355339 L6.03553391,7.62132034 L3.76776695,9.8890873 L4.47487373,10.5961941 L7.44974747,7.62132034 L4.47487373,4.64644661 L3.76776695,5.35355339 Z M5.91666667,12 L11.0833333,12 L11.0833333,11 L5.91666667,11 L5.91666667,12 Z"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 523 B |
@@ -0,0 +1,3 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
|
||||
<path fill="#FFF" fill-opacity=".6" fill-rule="evenodd" d="M3,2 L13,2 C14.1045695,2 15,2.8954305 15,4 L15,12 C15,13.1045695 14.1045695,14 13,14 L3,14 C1.8954305,14 1,13.1045695 1,12 L1,4 C1,2.8954305 1.8954305,2 3,2 Z M3.76776695,5.35355339 L6.03553391,7.62132034 L3.76776695,9.8890873 L4.47487373,10.5961941 L7.44974747,7.62132034 L4.47487373,4.64644661 L3.76776695,5.35355339 Z M5.91666667,12 L11.0833333,12 L11.0833333,11 L5.91666667,11 L5.91666667,12 Z"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 553 B |
3
Components/QProxyStyleTest/icons/category_game.svg
Normal file
@@ -0,0 +1,3 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
|
||||
<path fill-rule="evenodd" d="M11.3114315,3 C13.357501,3 15.0067163,5.17017281 15.7133188,8.05794777 C16.4086522,10.8996678 15.9150863,13.3535714 14.0872428,13.3535714 C13.3629901,13.3535714 12.7141246,13.0969142 11.9239825,12.5819693 C11.7832522,12.4902536 11.638281,12.3909224 11.461347,12.2660165 C11.3686071,12.200547 11.0517692,11.9743261 11.0062924,11.9420563 C9.76649639,11.0623107 9.01108239,10.715 8.00430016,10.715 C6.77138366,10.715 5.99921712,11.0762729 4.96661589,11.9397238 C4.93060093,11.9698391 4.48571222,12.3483964 4.35343872,12.4563717 C3.49008067,13.1611339 2.80601727,13.4628505 1.87123269,13.3869162 C0.0836355556,13.241098 -0.391076934,10.7851693 0.309935396,7.98500253 C1.02394135,5.13293317 2.67988585,3 4.7263796,3 C5.07581055,3 5.40379038,3.09122326 5.76942208,3.26509058 C5.87841375,3.31691894 5.98930228,3.37514875 6.12219409,3.44909841 C6.19628024,3.49032478 6.44963239,3.6346061 6.45727206,3.63892075 C7.10277068,4.00347855 7.50182674,4.14857143 8.01851079,4.14857143 C8.51588602,4.14857143 8.90120605,4.00650828 9.55466919,3.63859493 C9.69986269,3.55637602 9.78224829,3.50972827 9.84835639,3.47295723 C9.96412339,3.40856473 10.0609743,3.35696675 10.1556729,3.31001061 C10.567507,3.10580322 10.9247171,3 11.3114315,3 Z M5.07357978,10.107 C6.56572905,10.107 7.78410609,8.9267355 7.78410609,7.46414286 C7.78410609,6.00155021 6.56572905,4.82128571 5.07357978,4.82128571 C3.57990894,4.82128571 2.36305346,6.00089051 2.36305346,7.46414286 C2.36305346,8.9273952 3.57990894,10.107 5.07357978,10.107 Z M5.07357978,9.107 C4.12535588,9.107 3.36305346,8.36803337 3.36305346,7.46414286 C3.36305346,6.56025235 4.12535588,5.82128571 5.07357978,5.82128571 C6.02043115,5.82128571 6.78410609,6.56107184 6.78410609,7.46414286 C6.78410609,8.36721388 6.02043115,9.107 5.07357978,9.107 Z M5.03983241,8.37864286 C5.54751662,8.37864286 5.9601482,7.97792857 5.9601482,7.48935714 C5.9601482,6.99292857 5.54751662,6.59364286 5.03983241,6.59364286 C4.53067452,6.59364286 4.11804294,6.99292857 4.11804294,7.48935714 C4.11804294,7.97792857 4.53067452,8.37864286 5.03983241,8.37864286 Z M9.65408509,8.38564286 C10.1617693,8.38564286 10.5744008,7.9835 10.5744008,7.49135714 C10.5744008,6.99135714 10.1617693,6.58992857 9.65408509,6.58992857 C9.14492719,6.58992857 8.73229557,6.99135714 8.73229557,7.49135714 C8.73229557,7.9835 9.14492719,8.38564286 9.65408509,8.38564286 Z M11.3288535,9.99071429 C11.8365377,9.99071429 12.2491693,9.58928571 12.2491693,9.09214286 C12.2491693,8.59571429 11.8365377,8.19357143 11.3288535,8.19357143 C10.8196956,8.19357143 10.407064,8.59571429 10.407064,9.09214286 C10.407064,9.58928571 10.8196956,9.99071429 11.3288535,9.99071429 Z M11.3281166,6.77357143 C11.8372745,6.77357143 12.2491693,6.37142857 12.2491693,5.87357143 C12.2491693,5.37714286 11.8372745,4.97428571 11.3281166,4.97428571 C10.8174851,4.97428571 10.407064,5.37714286 10.407064,5.87357143 C10.407064,6.37142857 10.8174851,6.77357143 11.3281166,6.77357143 Z M12.9731166,8.38421429 C13.4852219,8.38421429 13.8971166,7.98135714 13.8971166,7.48921429 C13.8971166,6.98992857 13.4852219,6.5885 12.9731166,6.5885 C12.4676429,6.5885 12.0550114,6.98992857 12.0550114,7.48921429 C12.0550114,7.98135714 12.4676429,8.38421429 12.9731166,8.38421429 Z"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 3.3 KiB |
3
Components/QProxyStyleTest/icons/category_game_dark.svg
Normal file
@@ -0,0 +1,3 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
|
||||
<path fill="#FFF" fill-opacity=".6" fill-rule="evenodd" d="M11.3114315,3 C13.357501,3 15.0067163,5.17017281 15.7133188,8.05794777 C16.4086522,10.8996678 15.9150863,13.3535714 14.0872428,13.3535714 C13.3629901,13.3535714 12.7141246,13.0969142 11.9239825,12.5819693 C11.7832522,12.4902536 11.638281,12.3909224 11.461347,12.2660165 C11.3686071,12.200547 11.0517692,11.9743261 11.0062924,11.9420563 C9.76649639,11.0623107 9.01108239,10.715 8.00430016,10.715 C6.77138366,10.715 5.99921712,11.0762729 4.96661589,11.9397238 C4.93060093,11.9698391 4.48571222,12.3483964 4.35343872,12.4563717 C3.49008067,13.1611339 2.80601727,13.4628505 1.87123269,13.3869162 C0.0836355556,13.241098 -0.391076934,10.7851693 0.309935396,7.98500253 C1.02394135,5.13293317 2.67988585,3 4.7263796,3 C5.07581055,3 5.40379038,3.09122326 5.76942208,3.26509058 C5.87841375,3.31691894 5.98930228,3.37514875 6.12219409,3.44909841 C6.19628024,3.49032478 6.44963239,3.6346061 6.45727206,3.63892075 C7.10277068,4.00347855 7.50182674,4.14857143 8.01851079,4.14857143 C8.51588602,4.14857143 8.90120605,4.00650828 9.55466919,3.63859493 C9.69986269,3.55637602 9.78224829,3.50972827 9.84835639,3.47295723 C9.96412339,3.40856473 10.0609743,3.35696675 10.1556729,3.31001061 C10.567507,3.10580322 10.9247171,3 11.3114315,3 Z M5.07357978,10.107 C6.56572905,10.107 7.78410609,8.9267355 7.78410609,7.46414286 C7.78410609,6.00155021 6.56572905,4.82128571 5.07357978,4.82128571 C3.57990894,4.82128571 2.36305346,6.00089051 2.36305346,7.46414286 C2.36305346,8.9273952 3.57990894,10.107 5.07357978,10.107 Z M5.07357978,9.107 C4.12535588,9.107 3.36305346,8.36803337 3.36305346,7.46414286 C3.36305346,6.56025235 4.12535588,5.82128571 5.07357978,5.82128571 C6.02043115,5.82128571 6.78410609,6.56107184 6.78410609,7.46414286 C6.78410609,8.36721388 6.02043115,9.107 5.07357978,9.107 Z M5.03983241,8.37864286 C5.54751662,8.37864286 5.9601482,7.97792857 5.9601482,7.48935714 C5.9601482,6.99292857 5.54751662,6.59364286 5.03983241,6.59364286 C4.53067452,6.59364286 4.11804294,6.99292857 4.11804294,7.48935714 C4.11804294,7.97792857 4.53067452,8.37864286 5.03983241,8.37864286 Z M9.65408509,8.38564286 C10.1617693,8.38564286 10.5744008,7.9835 10.5744008,7.49135714 C10.5744008,6.99135714 10.1617693,6.58992857 9.65408509,6.58992857 C9.14492719,6.58992857 8.73229557,6.99135714 8.73229557,7.49135714 C8.73229557,7.9835 9.14492719,8.38564286 9.65408509,8.38564286 Z M11.3288535,9.99071429 C11.8365377,9.99071429 12.2491693,9.58928571 12.2491693,9.09214286 C12.2491693,8.59571429 11.8365377,8.19357143 11.3288535,8.19357143 C10.8196956,8.19357143 10.407064,8.59571429 10.407064,9.09214286 C10.407064,9.58928571 10.8196956,9.99071429 11.3288535,9.99071429 Z M11.3281166,6.77357143 C11.8372745,6.77357143 12.2491693,6.37142857 12.2491693,5.87357143 C12.2491693,5.37714286 11.8372745,4.97428571 11.3281166,4.97428571 C10.8174851,4.97428571 10.407064,5.37714286 10.407064,5.87357143 C10.407064,6.37142857 10.8174851,6.77357143 11.3281166,6.77357143 Z M12.9731166,8.38421429 C13.4852219,8.38421429 13.8971166,7.98135714 13.8971166,7.48921429 C13.8971166,6.98992857 13.4852219,6.5885 12.9731166,6.5885 C12.4676429,6.5885 12.0550114,6.98992857 12.0550114,7.48921429 C12.0550114,7.98135714 12.4676429,8.38421429 12.9731166,8.38421429 Z"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 3.3 KiB |
3
Components/QProxyStyleTest/icons/category_graphic.svg
Normal file
@@ -0,0 +1,3 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
|
||||
<path fill-rule="evenodd" d="M13,2 C14.1045695,2 15,2.8954305 15,4 L15,12 C15,13.1045695 14.1045695,14 13,14 L3,14 C1.8954305,14 1,13.1045695 1,12 L1,4 C1,2.8954305 1.8954305,2 3,2 L13,2 Z M9.38816736,7.22265239 L7.95626236,10.0443009 C7.82854357,10.2959779 7.59618367,10.3016397 7.44581474,10.0701011 L6.5212474,8.6464491 C6.2918509,8.42797452 5.91137533,8.45796439 5.72281255,8.70938339 L3.09783322,12.2093834 C2.84963451,12.5403176 3.0980227,13 3.52503993,13 L12.9749655,13 C13.3830419,13 13.6350993,12.5760169 13.4251458,12.2427546 L10.2751706,7.24275461 C10.0768804,6.92800582 9.60195261,6.91724249 9.38816736,7.22265239 Z M4.5,4 C3.67157288,4 3,4.67157288 3,5.5 C3,6.32842712 3.67157288,7 4.5,7 C5.32842712,7 6,6.32842712 6,5.5 C6,4.67157288 5.32842712,4 4.5,4 Z"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 865 B |
@@ -0,0 +1,3 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
|
||||
<path fill="#FFF" fill-opacity=".6" fill-rule="evenodd" d="M13,2 C14.1045695,2 15,2.8954305 15,4 L15,12 C15,13.1045695 14.1045695,14 13,14 L3,14 C1.8954305,14 1,13.1045695 1,12 L1,4 C1,2.8954305 1.8954305,2 3,2 L13,2 Z M9.38816736,7.22265239 L7.95626236,10.0443009 C7.82854357,10.2959779 7.59618367,10.3016397 7.44581474,10.0701011 L6.5212474,8.6464491 C6.2918509,8.42797452 5.91137533,8.45796439 5.72281255,8.70938339 L3.09783322,12.2093834 C2.84963451,12.5403176 3.0980227,13 3.52503993,13 L12.9749655,13 C13.3830419,13 13.6350993,12.5760169 13.4251458,12.2427546 L10.2751706,7.24275461 C10.0768804,6.92800582 9.60195261,6.91724249 9.38816736,7.22265239 Z M4.5,4 C3.67157288,4 3,4.67157288 3,5.5 C3,6.32842712 3.67157288,7 4.5,7 C5.32842712,7 6,6.32842712 6,5.5 C6,4.67157288 5.32842712,4 4.5,4 Z"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 895 B |
3
Components/QProxyStyleTest/icons/category_music.svg
Normal file
@@ -0,0 +1,3 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
|
||||
<path fill-rule="evenodd" d="M13.9529472,2.53458892 C13.9842218,2.67532449 14,2.81906015 14,2.9632288 L14,11.5 C14,12.6045695 13.1045695,13.5 12,13.5 C10.8954305,13.5 10,12.6045695 10,11.5 C10,10.3954305 10.8954305,9.5 12,9.5 C12.364732,9.5 12.7066608,9.5976323 13.0010775,9.76818814 L13,3.81473429 C13,3.45097522 12.705115,3.15609023 12.3413559,3.15609023 C12.2949677,3.15609023 12.2487093,3.16099086 12.2033508,3.17071053 L6.52063898,4.38843451 C6.21695744,4.45350912 6,4.7218827 6,5.03245826 L6,13.5 C6,14.6045695 5.1045695,15.5 4,15.5 C2.8954305,15.5 2,14.6045695 2,13.5 C2,12.3954305 2.8954305,11.5 4,11.5 C4.364732,11.5 4.70666076,11.5976323 5.0010775,11.7681881 L5,4.08503671 C5,3.15891996 5.64322914,2.35706019 6.54729233,2.15615726 L11.5954279,1.03434935 C12.6607186,0.797618084 13.716216,1.46929822 13.9529472,2.53458892 Z"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 929 B |
3
Components/QProxyStyleTest/icons/category_music_dark.svg
Normal file
@@ -0,0 +1,3 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
|
||||
<path fill="#FFF" fill-opacity=".6" fill-rule="evenodd" d="M13.9529472,2.53458892 C13.9842218,2.67532449 14,2.81906015 14,2.9632288 L14,11.5 C14,12.6045695 13.1045695,13.5 12,13.5 C10.8954305,13.5 10,12.6045695 10,11.5 C10,10.3954305 10.8954305,9.5 12,9.5 C12.364732,9.5 12.7066608,9.5976323 13.0010775,9.76818814 L13,3.81473429 C13,3.45097522 12.705115,3.15609023 12.3413559,3.15609023 C12.2949677,3.15609023 12.2487093,3.16099086 12.2033508,3.17071053 L6.52063898,4.38843451 C6.21695744,4.45350912 6,4.7218827 6,5.03245826 L6,13.5 C6,14.6045695 5.1045695,15.5 4,15.5 C2.8954305,15.5 2,14.6045695 2,13.5 C2,12.3954305 2.8954305,11.5 4,11.5 C4.364732,11.5 4.70666076,11.5976323 5.0010775,11.7681881 L5,4.08503671 C5,3.15891996 5.64322914,2.35706019 6.54729233,2.15615726 L11.5954279,1.03434935 C12.6607186,0.797618084 13.716216,1.46929822 13.9529472,2.53458892 Z"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 959 B |
3
Components/QProxyStyleTest/icons/category_network.svg
Normal file
@@ -0,0 +1,3 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
|
||||
<path fill-rule="evenodd" d="M7.99960993,0.9998 C11.8598496,0.9998 15,4.13995046 15,7.99940993 C15,11.8596496 11.8598496,14.9998 7.99960993,14.9998 C4.14015046,14.9998 1,11.8596496 1,7.99940993 C1,4.13995046 4.14015046,0.9998 7.99960993,0.9998 Z M8.86971986,11.9145 C8.56971986,12.747 8.22071986,13.122 7.99971986,13.122 C7.78521986,13.122 7.44971986,12.768 7.15571986,11.9845 C6.86571986,12.132 6.61521986,12.2485 6.36971986,12.354 C6.75321986,13.3495 7.29871986,14 7.99971986,14 C8.71921986,14 9.27521986,13.314 9.66021986,12.274 C9.41771986,12.1735 9.16171986,12.0585 8.86971986,11.9145 Z M12.0962199,3.61 C10.8027199,3.61 9.05121986,4.5085 7.94421986,5.19 C6.85371986,4.547 5.16021986,3.717 3.90321986,3.717 C3.19571986,3.717 2.85321986,4 2.69121986,4.238 C2.46021986,4.576 2.34571986,5.1655 2.90071986,6.1455 C2.82221986,6.286 2.77771986,6.448 2.77771986,6.6205 C2.77771986,7.154 3.20271986,7.5865 3.72621986,7.5865 C4.24971986,7.5865 4.67471986,7.154 4.67471986,6.6205 C4.67471986,6.087 4.25021986,5.6545 3.72621986,5.6545 L3.72621986,5.6545 L3.62121986,5.6605 C3.32971986,5.131 3.33321986,4.8355 3.39871986,4.7395 C3.46021986,4.6485 3.64921986,4.595 3.90321986,4.595 C4.30121986,4.595 4.82071986,4.7155 5.41071986,4.9325 C5.98671986,5.145 6.57721986,5.43 7.11871986,5.728 C5.99421986,6.502 5.13171986,7.25 4.36621986,8.027 C4.02471986,8.379 3.68871986,8.7615 3.39771986,9.1515 C2.30221986,10.6215 2.40671986,11.433 2.68771986,11.8555 C3.25671986,12.71 4.68721986,12.3665 5.64571986,12.014 C7.99371986,11.151 11.0597199,8.9165 12.6017199,6.848 C13.6972199,5.3785 13.5927199,4.567 13.3117199,4.1445 C13.1492199,3.9005 12.8067199,3.61 12.0962199,3.61 Z M12.2647199,8.445 C11.7407199,8.445 11.3162199,8.8775 11.3162199,9.411 C11.3162199,9.9445 11.7407199,10.377 12.2647199,10.377 L12.3937199,10.368 C12.6702199,10.88 12.6657199,11.167 12.6012199,11.2615 C12.5392199,11.352 12.3507199,11.4055 12.0967199,11.4055 C11.2957199,11.4055 10.1802199,10.933 9.46171986,10.5765 C9.22171986,10.7475 8.92321986,10.9505 8.63221986,11.136 C9.59521986,11.6545 11.0112199,12.2835 12.0967199,12.2835 C12.8042199,12.2835 13.1467199,12.0005 13.3087199,11.7625 C13.5392199,11.4255 13.6537199,10.8375 13.1032199,9.8625 C13.1737199,9.7275 13.2132199,9.574 13.2132199,9.411 C13.2132199,8.8775 12.7887199,8.445 12.2647199,8.445 Z M12.0962199,4.4875 C12.3517199,4.4875 12.5347199,4.542 12.5977199,4.6365 C12.6907199,4.776 12.6677199,5.3075 11.9147199,6.317 C10.9462199,7.6165 9.40121986,8.8925 8.04671986,9.7805 C6.94321986,10.504 5.07821986,11.5125 3.90321986,11.5125 C3.64771986,11.5125 3.46471986,11.458 3.40171986,11.3635 C3.21521986,11.083 3.61221986,10.04 5.02121986,8.601 C5.54371986,9.0665 6.10721986,9.5115 6.67921986,9.917 L6.67921986,9.917 C6.98671986,9.7555 7.25071986,9.597 7.51171986,9.4315 C6.82921986,8.9695 6.18871986,8.4705 5.65121986,7.995 C6.36621986,7.3465 7.16221986,6.738 7.95271986,6.2195 C8.64121986,6.6515 9.30521986,7.133 9.90271986,7.625 C10.1212199,7.429 10.3347199,7.226 10.5382199,7.0195 C9.99971986,6.5705 9.40971986,6.1295 8.77721986,5.711 C9.63321986,5.217 11.1197199,4.4875 12.0962199,4.4875 Z M7.99971986,2 C7.28021986,2 6.72421986,2.686 6.33921986,3.726 C6.58321986,3.827 6.83971986,3.9425 7.12971986,4.0855 C7.42971986,3.253 7.77871986,2.878 7.99971986,2.878 C8.21471986,2.878 8.54971986,3.232 8.84371986,4.0155 C9.13071986,3.8695 9.38371986,3.7515 9.62971986,3.646 C9.24671986,2.6505 8.70071986,2 7.99971986,2 Z"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 3.4 KiB |
@@ -0,0 +1,3 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
|
||||
<path fill="#FFF" fill-opacity=".6" fill-rule="evenodd" d="M7.99960993,0.9998 C11.8598496,0.9998 15,4.13995046 15,7.99940993 C15,11.8596496 11.8598496,14.9998 7.99960993,14.9998 C4.14015046,14.9998 1,11.8596496 1,7.99940993 C1,4.13995046 4.14015046,0.9998 7.99960993,0.9998 Z M8.86971986,11.9145 C8.56971986,12.747 8.22071986,13.122 7.99971986,13.122 C7.78521986,13.122 7.44971986,12.768 7.15571986,11.9845 C6.86571986,12.132 6.61521986,12.2485 6.36971986,12.354 C6.75321986,13.3495 7.29871986,14 7.99971986,14 C8.71921986,14 9.27521986,13.314 9.66021986,12.274 C9.41771986,12.1735 9.16171986,12.0585 8.86971986,11.9145 Z M12.0962199,3.61 C10.8027199,3.61 9.05121986,4.5085 7.94421986,5.19 C6.85371986,4.547 5.16021986,3.717 3.90321986,3.717 C3.19571986,3.717 2.85321986,4 2.69121986,4.238 C2.46021986,4.576 2.34571986,5.1655 2.90071986,6.1455 C2.82221986,6.286 2.77771986,6.448 2.77771986,6.6205 C2.77771986,7.154 3.20271986,7.5865 3.72621986,7.5865 C4.24971986,7.5865 4.67471986,7.154 4.67471986,6.6205 C4.67471986,6.087 4.25021986,5.6545 3.72621986,5.6545 L3.72621986,5.6545 L3.62121986,5.6605 C3.32971986,5.131 3.33321986,4.8355 3.39871986,4.7395 C3.46021986,4.6485 3.64921986,4.595 3.90321986,4.595 C4.30121986,4.595 4.82071986,4.7155 5.41071986,4.9325 C5.98671986,5.145 6.57721986,5.43 7.11871986,5.728 C5.99421986,6.502 5.13171986,7.25 4.36621986,8.027 C4.02471986,8.379 3.68871986,8.7615 3.39771986,9.1515 C2.30221986,10.6215 2.40671986,11.433 2.68771986,11.8555 C3.25671986,12.71 4.68721986,12.3665 5.64571986,12.014 C7.99371986,11.151 11.0597199,8.9165 12.6017199,6.848 C13.6972199,5.3785 13.5927199,4.567 13.3117199,4.1445 C13.1492199,3.9005 12.8067199,3.61 12.0962199,3.61 Z M12.2647199,8.445 C11.7407199,8.445 11.3162199,8.8775 11.3162199,9.411 C11.3162199,9.9445 11.7407199,10.377 12.2647199,10.377 L12.3937199,10.368 C12.6702199,10.88 12.6657199,11.167 12.6012199,11.2615 C12.5392199,11.352 12.3507199,11.4055 12.0967199,11.4055 C11.2957199,11.4055 10.1802199,10.933 9.46171986,10.5765 C9.22171986,10.7475 8.92321986,10.9505 8.63221986,11.136 C9.59521986,11.6545 11.0112199,12.2835 12.0967199,12.2835 C12.8042199,12.2835 13.1467199,12.0005 13.3087199,11.7625 C13.5392199,11.4255 13.6537199,10.8375 13.1032199,9.8625 C13.1737199,9.7275 13.2132199,9.574 13.2132199,9.411 C13.2132199,8.8775 12.7887199,8.445 12.2647199,8.445 Z M12.0962199,4.4875 C12.3517199,4.4875 12.5347199,4.542 12.5977199,4.6365 C12.6907199,4.776 12.6677199,5.3075 11.9147199,6.317 C10.9462199,7.6165 9.40121986,8.8925 8.04671986,9.7805 C6.94321986,10.504 5.07821986,11.5125 3.90321986,11.5125 C3.64771986,11.5125 3.46471986,11.458 3.40171986,11.3635 C3.21521986,11.083 3.61221986,10.04 5.02121986,8.601 C5.54371986,9.0665 6.10721986,9.5115 6.67921986,9.917 L6.67921986,9.917 C6.98671986,9.7555 7.25071986,9.597 7.51171986,9.4315 C6.82921986,8.9695 6.18871986,8.4705 5.65121986,7.995 C6.36621986,7.3465 7.16221986,6.738 7.95271986,6.2195 C8.64121986,6.6515 9.30521986,7.133 9.90271986,7.625 C10.1212199,7.429 10.3347199,7.226 10.5382199,7.0195 C9.99971986,6.5705 9.40971986,6.1295 8.77721986,5.711 C9.63321986,5.217 11.1197199,4.4875 12.0962199,4.4875 Z M7.99971986,2 C7.28021986,2 6.72421986,2.686 6.33921986,3.726 C6.58321986,3.827 6.83971986,3.9425 7.12971986,4.0855 C7.42971986,3.253 7.77871986,2.878 7.99971986,2.878 C8.21471986,2.878 8.54971986,3.232 8.84371986,4.0155 C9.13071986,3.8695 9.38371986,3.7515 9.62971986,3.646 C9.24671986,2.6505 8.70071986,2 7.99971986,2 Z"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 3.5 KiB |
3
Components/QProxyStyleTest/icons/category_office.svg
Normal file
@@ -0,0 +1,3 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
|
||||
<path fill-rule="evenodd" d="M14.6796875,1 C15.1667188,1 15.5,1.316 15.5,1.66666667 L15.5,2.33333333 C15.5,2.684 15.1667188,3 14.6796875,3 L14,3 L14,9.0952381 C14,10.147209 13.1045695,11 12,11 L10.223,11 L12.2674534,13.0443466 C12.4627155,13.2396088 12.4627155,13.5561912 12.2674534,13.7514534 C12.0721912,13.9467155 11.7556088,13.9467155 11.5603466,13.7514534 L8.9995,11.1905 L9,14.5 C9,14.7761424 8.77614237,15 8.5,15 C8.24358208,15 8.03224642,14.8069799 8.00336387,14.5583106 L8,14.5 L7.9995,11.191 L5.43965339,13.7514534 C5.25941141,13.9316954 4.97579588,13.9455601 4.77965028,13.7930477 L4.73254661,13.7514534 C4.55230463,13.5712114 4.53843986,13.2875959 4.69095231,13.0914503 L4.73254661,13.0443466 L6.776,11 L4,11 C2.8954305,11 2,10.147209 2,9.0952381 L2,3 L1.3203125,3 C0.83328125,3 0.5,2.684 0.5,2.33333333 L0.5,1.66666667 C0.5,1.316 0.83328125,1 1.3203125,1 L14.6796875,1 Z M13,3 L3,3 L3,9.05882353 C3,9.57862094 3.44771525,10 4,10 L12,10 C12.5522847,10 13,9.57862094 13,9.05882353 L13,3 Z M8,4.5 L8,6.5 L10,6.5 C10,7.6045695 9.1045695,8.5 8,8.5 C6.8954305,8.5 6,7.6045695 6,6.5 C6,5.3954305 6.8954305,4.5 8,4.5 Z M9,3.5 C10.1045695,3.5 11,4.3954305 11,5.5 L9,5.5 L9,3.5 Z"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.2 KiB |
@@ -0,0 +1,3 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
|
||||
<path fill="#FFF" fill-opacity=".6" fill-rule="evenodd" d="M14.6796875,1 C15.1667188,1 15.5,1.316 15.5,1.66666667 L15.5,2.33333333 C15.5,2.684 15.1667188,3 14.6796875,3 L14,3 L14,9.0952381 C14,10.147209 13.1045695,11 12,11 L10.223,11 L12.2674534,13.0443466 C12.4627155,13.2396088 12.4627155,13.5561912 12.2674534,13.7514534 C12.0721912,13.9467155 11.7556088,13.9467155 11.5603466,13.7514534 L8.9995,11.1905 L9,14.5 C9,14.7761424 8.77614237,15 8.5,15 C8.24358208,15 8.03224642,14.8069799 8.00336387,14.5583106 L8,14.5 L7.9995,11.191 L5.43965339,13.7514534 C5.25941141,13.9316954 4.97579588,13.9455601 4.77965028,13.7930477 L4.73254661,13.7514534 C4.55230463,13.5712114 4.53843986,13.2875959 4.69095231,13.0914503 L4.73254661,13.0443466 L6.776,11 L4,11 C2.8954305,11 2,10.147209 2,9.0952381 L2,3 L1.3203125,3 C0.83328125,3 0.5,2.684 0.5,2.33333333 L0.5,1.66666667 C0.5,1.316 0.83328125,1 1.3203125,1 L14.6796875,1 Z M13,3 L3,3 L3,9.05882353 C3,9.57862094 3.44771525,10 4,10 L12,10 C12.5522847,10 13,9.57862094 13,9.05882353 L13,3 Z M8,4.5 L8,6.5 L10,6.5 C10,7.6045695 9.1045695,8.5 8,8.5 C6.8954305,8.5 6,7.6045695 6,6.5 C6,5.3954305 6.8954305,4.5 8,4.5 Z M9,3.5 C10.1045695,3.5 11,4.3954305 11,5.5 L9,5.5 L9,3.5 Z"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.3 KiB |
3
Components/QProxyStyleTest/icons/category_others.svg
Normal file
@@ -0,0 +1,3 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
|
||||
<path fill-rule="evenodd" d="M8.00031808,0.99950155 C11.8603458,0.99950155 14.9999738,4.1390565 14.9999738,7.99950155 C14.9999738,11.8599466 11.8603458,14.9995015 8.00031808,14.9995015 C4.13971544,14.9995015 0.999973754,11.8600603 0.999973754,7.99950155 C0.999973754,4.13894278 4.13971544,0.99950155 8.00031808,0.99950155 Z M11.4999738,8.99950155 C12.0526404,8.99950155 12.4999738,8.55150155 12.4999738,7.99950155 C12.4999738,7.44683488 12.0526404,6.99950155 11.4999738,6.99950155 C10.9473071,6.99950155 10.4999738,7.44683488 10.4999738,7.99950155 C10.4999738,8.55150155 10.9473071,8.99950155 11.4999738,8.99950155 Z M7.99997375,8.99950155 C8.55264042,8.99950155 8.99997375,8.55150155 8.99997375,7.99950155 C8.99997375,7.44683488 8.55264042,6.99950155 7.99997375,6.99950155 C7.44797375,6.99950155 6.99997375,7.44683488 6.99997375,7.99950155 C6.99997375,8.55150155 7.44797375,8.99950155 7.99997375,8.99950155 Z M4.49997375,8.99950155 C5.05264042,8.99950155 5.49997375,8.55150155 5.49997375,7.99950155 C5.49997375,7.44683488 5.05264042,6.99950155 4.49997375,6.99950155 C3.94797375,6.99950155 3.49997375,7.44683488 3.49997375,7.99950155 C3.49997375,8.55150155 3.94797375,8.99950155 4.49997375,8.99950155 Z"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.3 KiB |
@@ -0,0 +1,3 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
|
||||
<path fill="#FFF" fill-opacity=".6" fill-rule="evenodd" d="M8.00031808,0.99950155 C11.8603458,0.99950155 14.9999738,4.1390565 14.9999738,7.99950155 C14.9999738,11.8599466 11.8603458,14.9995015 8.00031808,14.9995015 C4.13971544,14.9995015 0.999973754,11.8600603 0.999973754,7.99950155 C0.999973754,4.13894278 4.13971544,0.99950155 8.00031808,0.99950155 Z M11.4999738,8.99950155 C12.0526404,8.99950155 12.4999738,8.55150155 12.4999738,7.99950155 C12.4999738,7.44683488 12.0526404,6.99950155 11.4999738,6.99950155 C10.9473071,6.99950155 10.4999738,7.44683488 10.4999738,7.99950155 C10.4999738,8.55150155 10.9473071,8.99950155 11.4999738,8.99950155 Z M7.99997375,8.99950155 C8.55264042,8.99950155 8.99997375,8.55150155 8.99997375,7.99950155 C8.99997375,7.44683488 8.55264042,6.99950155 7.99997375,6.99950155 C7.44797375,6.99950155 6.99997375,7.44683488 6.99997375,7.99950155 C6.99997375,8.55150155 7.44797375,8.99950155 7.99997375,8.99950155 Z M4.49997375,8.99950155 C5.05264042,8.99950155 5.49997375,8.55150155 5.49997375,7.99950155 C5.49997375,7.44683488 5.05264042,6.99950155 4.49997375,6.99950155 C3.94797375,6.99950155 3.49997375,7.44683488 3.49997375,7.99950155 C3.49997375,8.55150155 3.94797375,8.99950155 4.49997375,8.99950155 Z"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.3 KiB |
6
Components/QProxyStyleTest/icons/category_reading.svg
Normal file
@@ -0,0 +1,6 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
|
||||
<g fill="none" fill-rule="evenodd">
|
||||
<path fill="#000" d="M1.85789238,2.64258737 C4.86313703,2.21112969 6.5771729,2.75883866 7,4.28571429 L7,13.7857143 C6.27058294,12.8374721 4.43450345,12.3388115 1.49176152,12.2897326 C1.2188519,12.2852804 1,12.062748 1,11.7898021 L1,3.63241367 C1.00002467,3.13504017 1.36556687,2.71326968 1.85789238,2.64258737 Z"/>
|
||||
<path fill="#000" d="M9.85789238,2.64258737 C12.863137,2.21112969 14.5771729,2.75883866 15,4.28571429 L15,13.7857143 C14.2705829,12.8374721 12.4345034,12.3388115 9.49176152,12.2897326 C9.2188519,12.2852804 9,12.062748 9,11.7898021 L9,3.63241367 C9.00002467,3.13504017 9.36556687,2.71326968 9.85789238,2.64258737 Z" transform="matrix(-1 0 0 1 24 0)"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 810 B |
@@ -0,0 +1,6 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
|
||||
<g fill="none" fill-opacity=".6" fill-rule="evenodd">
|
||||
<path fill="#FFF" d="M1.85789238,2.64258737 C4.86313703,2.21112969 6.5771729,2.75883866 7,4.28571429 L7,13.7857143 C6.27058294,12.8374721 4.43450345,12.3388115 1.49176152,12.2897326 C1.2188519,12.2852804 1,12.062748 1,11.7898021 L1,3.63241367 C1.00002467,3.13504017 1.36556687,2.71326968 1.85789238,2.64258737 Z"/>
|
||||
<path fill="#FFF" d="M9.85789238,2.64258737 C12.863137,2.21112969 14.5771729,2.75883866 15,4.28571429 L15,13.7857143 C14.2705829,12.8374721 12.4345034,12.3388115 9.49176152,12.2897326 C9.2188519,12.2852804 9,12.062748 9,11.7898021 L9,3.63241367 C9.00002467,3.13504017 9.36556687,2.71326968 9.85789238,2.64258737 Z" transform="matrix(-1 0 0 1 24 0)"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 828 B |
3
Components/QProxyStyleTest/icons/category_system.svg
Normal file
@@ -0,0 +1,3 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
|
||||
<path fill-rule="evenodd" d="M3,14 C1.8954305,14 1,13.1045695 1,12 L1,4 C1,2.8954305 1.8954305,2 3,2 L13,2 C14.1045695,2 15,2.8954305 15,4 L15,12 C15,13.0543618 14.1841222,13.9181651 13.1492623,13.9945143 L13,14 L13,14 L3,14 Z M14,5 L2,5 L2,12 C2,12.5522847 2.44771525,13 3,13 L8.01233301,13.0001639 C8.01943442,12.9772458 8.02824971,12.9546419 8.0388094,12.9325301 L8.30383017,12.3775926 C8.34459502,12.2912196 8.34695846,12.1917404 8.30983658,12.1028011 C8.27399122,12.0159757 8.20318605,11.9486684 8.11444707,11.9170901 L7.53244707,11.7100901 C7.33313205,11.6391997 7.19999981,11.4505463 7.19999981,11.2389998 L7.19999981,10.1609998 C7.19999981,9.9491733 7.33347927,9.7603339 7.53316619,9.6896543 L8.11249002,9.4846101 C8.20258302,9.4521442 8.27390085,9.3842428 8.31058669,9.2953916 C8.34695846,9.2082592 8.34459502,9.10878 8.3048094,9.0244696 L8.0388094,8.46746956 C7.94749917,8.2762673 7.98662009,8.04827275 8.13644642,7.89844642 L8.89844642,7.13644642 C9.04827275,6.98662009 9.2762673,6.94749917 9.46746956,7.0388094 L10.022407,7.30383017 C10.10878,7.34459502 10.2082592,7.34695846 10.2971985,7.30983658 C10.3842159,7.27391194 10.4518724,7.202745 10.4837447,7.11391109 L10.6897447,6.53291109 C10.7604992,6.33335606 10.9492726,6.19999981 11.1609998,6.19999981 L12.2389998,6.19999981 C12.450727,6.19999981 12.6395004,6.33335606 12.7102549,6.53291109 L12.9156316,7.11216331 C12.9481272,7.202745 13.0157837,7.27391194 13.104608,7.31058669 C13.1917404,7.34695846 13.2912196,7.34459502 13.3755301,7.3048094 L13.9325301,7.0388094 L14,7.013 L14,5 Z M11.6999998,9.1999998 C10.8729998,9.1999998 10.1999998,9.8729998 10.1999998,10.6999998 C10.1999998,11.5269998 10.8729998,12.1999998 11.6999998,12.1999998 C12.5269998,12.1999998 13.1999998,11.5269998 13.1999998,10.6999998 C13.1999998,9.8729998 12.5269998,9.1999998 11.6999998,9.1999998 Z M13,3 L12,3 L12,4 L13,4 L13,3 Z M9,3 L8,3 L8,4 L9,4 L9,3 Z M11,3 L10,3 L10,4 L11,4 L11,3 Z"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 2.0 KiB |
@@ -0,0 +1,3 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
|
||||
<path fill="#FFF" fill-opacity=".6" fill-rule="evenodd" d="M3,14 C1.8954305,14 1,13.1045695 1,12 L1,4 C1,2.8954305 1.8954305,2 3,2 L13,2 C14.1045695,2 15,2.8954305 15,4 L15,12 C15,13.0543618 14.1841222,13.9181651 13.1492623,13.9945143 L13,14 L13,14 L3,14 Z M14,5 L2,5 L2,12 C2,12.5522847 2.44771525,13 3,13 L8.01233301,13.0001639 C8.01943442,12.9772458 8.02824971,12.9546419 8.0388094,12.9325301 L8.30383017,12.3775926 C8.34459502,12.2912196 8.34695846,12.1917404 8.30983658,12.1028011 C8.27399122,12.0159757 8.20318605,11.9486684 8.11444707,11.9170901 L7.53244707,11.7100901 C7.33313205,11.6391997 7.19999981,11.4505463 7.19999981,11.2389998 L7.19999981,10.1609998 C7.19999981,9.9491733 7.33347927,9.7603339 7.53316619,9.6896543 L8.11249002,9.4846101 C8.20258302,9.4521442 8.27390085,9.3842428 8.31058669,9.2953916 C8.34695846,9.2082592 8.34459502,9.10878 8.3048094,9.0244696 L8.0388094,8.46746956 C7.94749917,8.2762673 7.98662009,8.04827275 8.13644642,7.89844642 L8.89844642,7.13644642 C9.04827275,6.98662009 9.2762673,6.94749917 9.46746956,7.0388094 L10.022407,7.30383017 C10.10878,7.34459502 10.2082592,7.34695846 10.2971985,7.30983658 C10.3842159,7.27391194 10.4518724,7.202745 10.4837447,7.11391109 L10.6897447,6.53291109 C10.7604992,6.33335606 10.9492726,6.19999981 11.1609998,6.19999981 L12.2389998,6.19999981 C12.450727,6.19999981 12.6395004,6.33335606 12.7102549,6.53291109 L12.9156316,7.11216331 C12.9481272,7.202745 13.0157837,7.27391194 13.104608,7.31058669 C13.1917404,7.34695846 13.2912196,7.34459502 13.3755301,7.3048094 L13.9325301,7.0388094 L14,7.013 L14,5 Z M11.6999998,9.1999998 C10.8729998,9.1999998 10.1999998,9.8729998 10.1999998,10.6999998 C10.1999998,11.5269998 10.8729998,12.1999998 11.6999998,12.1999998 C12.5269998,12.1999998 13.1999998,11.5269998 13.1999998,10.6999998 C13.1999998,9.8729998 12.5269998,9.1999998 11.6999998,9.1999998 Z M13,3 L12,3 L12,4 L13,4 L13,3 Z M9,3 L8,3 L8,4 L9,4 L9,3 Z M11,3 L10,3 L10,4 L11,4 L11,3 Z"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 2.0 KiB |
3
Components/QProxyStyleTest/icons/category_video.svg
Normal file
@@ -0,0 +1,3 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
|
||||
<path fill-rule="evenodd" d="M12,2 C13.1045695,2 14,2.8954305 14,4 L14,13 C14,14.1045695 13.1045695,15 12,15 L4,15 C2.8954305,15 2,14.1045695 2,13 L2,4 C2,2.8954305 2.8954305,2 4,2 L12,2 Z M4.5,12 L3.5,12 C3.22385763,12 3,12.2238576 3,12.5 L3,12.5 L3,13 C3,13.5522847 3.44771525,14 4,14 L4,14 L4.5,14 C4.77614237,14 5,13.7761424 5,13.5 L5,13.5 L5,12.5 C5,12.2238576 4.77614237,12 4.5,12 L4.5,12 Z M12.5,12 L11.5,12 C11.2238576,12 11,12.2238576 11,12.5 L11,12.5 L11,13.5 C11,13.7761424 11.2238576,14 11.5,14 L11.5,14 L12,14 C12.5522847,14 13,13.5522847 13,13 L13,13 L13,12.5 C13,12.2238576 12.7761424,12 12.5,12 L12.5,12 Z M4.5,9 L3.5,9 C3.22385763,9 3,9.22385763 3,9.5 L3,9.5 L3,10.5 C3,10.7761424 3.22385763,11 3.5,11 L3.5,11 L4.5,11 C4.77614237,11 5,10.7761424 5,10.5 L5,10.5 L5,9.5 C5,9.22385763 4.77614237,9 4.5,9 L4.5,9 Z M12.5,9 L11.5,9 C11.2238576,9 11,9.22385763 11,9.5 L11,9.5 L11,10.5 C11,10.7761424 11.2238576,11 11.5,11 L11.5,11 L12.5,11 C12.7761424,11 13,10.7761424 13,10.5 L13,10.5 L13,9.5 C13,9.22385763 12.7761424,9 12.5,9 L12.5,9 Z M4.5,6 L3.5,6 C3.22385763,6 3,6.22385763 3,6.5 L3,6.5 L3,7.5 C3,7.77614237 3.22385763,8 3.5,8 L3.5,8 L4.5,8 C4.77614237,8 5,7.77614237 5,7.5 L5,7.5 L5,6.5 C5,6.22385763 4.77614237,6 4.5,6 L4.5,6 Z M12.5,6 L11.5,6 C11.2238576,6 11,6.22385763 11,6.5 L11,6.5 L11,7.5 C11,7.77614237 11.2238576,8 11.5,8 L11.5,8 L12.5,8 C12.7761424,8 13,7.77614237 13,7.5 L13,7.5 L13,6.5 C13,6.22385763 12.7761424,6 12.5,6 L12.5,6 Z M4.5,3 L4,3 C3.44771525,3 3,3.44771525 3,4 L3,4 L3,4.5 C3,4.77614237 3.22385763,5 3.5,5 L3.5,5 L4.5,5 C4.77614237,5 5,4.77614237 5,4.5 L5,4.5 L5,3.5 C5,3.22385763 4.77614237,3 4.5,3 L4.5,3 Z M12,3 L11.5,3 C11.2238576,3 11,3.22385763 11,3.5 L11,3.5 L11,4.5 C11,4.77614237 11.2238576,5 11.5,5 L11.5,5 L12.5,5 C12.7761424,5 13,4.77614237 13,4.5 L13,4.5 L13,4 C13,3.44771525 12.5522847,3 12,3 L12,3 Z"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.9 KiB |
3
Components/QProxyStyleTest/icons/category_video_dark.svg
Normal file
@@ -0,0 +1,3 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
|
||||
<path fill="#FFF" fill-opacity=".6" fill-rule="evenodd" d="M12,2 C13.1045695,2 14,2.8954305 14,4 L14,13 C14,14.1045695 13.1045695,15 12,15 L4,15 C2.8954305,15 2,14.1045695 2,13 L2,4 C2,2.8954305 2.8954305,2 4,2 L12,2 Z M4.5,12 L3.5,12 C3.22385763,12 3,12.2238576 3,12.5 L3,12.5 L3,13 C3,13.5522847 3.44771525,14 4,14 L4,14 L4.5,14 C4.77614237,14 5,13.7761424 5,13.5 L5,13.5 L5,12.5 C5,12.2238576 4.77614237,12 4.5,12 L4.5,12 Z M12.5,12 L11.5,12 C11.2238576,12 11,12.2238576 11,12.5 L11,12.5 L11,13.5 C11,13.7761424 11.2238576,14 11.5,14 L11.5,14 L12,14 C12.5522847,14 13,13.5522847 13,13 L13,13 L13,12.5 C13,12.2238576 12.7761424,12 12.5,12 L12.5,12 Z M4.5,9 L3.5,9 C3.22385763,9 3,9.22385763 3,9.5 L3,9.5 L3,10.5 C3,10.7761424 3.22385763,11 3.5,11 L3.5,11 L4.5,11 C4.77614237,11 5,10.7761424 5,10.5 L5,10.5 L5,9.5 C5,9.22385763 4.77614237,9 4.5,9 L4.5,9 Z M12.5,9 L11.5,9 C11.2238576,9 11,9.22385763 11,9.5 L11,9.5 L11,10.5 C11,10.7761424 11.2238576,11 11.5,11 L11.5,11 L12.5,11 C12.7761424,11 13,10.7761424 13,10.5 L13,10.5 L13,9.5 C13,9.22385763 12.7761424,9 12.5,9 L12.5,9 Z M4.5,6 L3.5,6 C3.22385763,6 3,6.22385763 3,6.5 L3,6.5 L3,7.5 C3,7.77614237 3.22385763,8 3.5,8 L3.5,8 L4.5,8 C4.77614237,8 5,7.77614237 5,7.5 L5,7.5 L5,6.5 C5,6.22385763 4.77614237,6 4.5,6 L4.5,6 Z M12.5,6 L11.5,6 C11.2238576,6 11,6.22385763 11,6.5 L11,6.5 L11,7.5 C11,7.77614237 11.2238576,8 11.5,8 L11.5,8 L12.5,8 C12.7761424,8 13,7.77614237 13,7.5 L13,7.5 L13,6.5 C13,6.22385763 12.7761424,6 12.5,6 L12.5,6 Z M4.5,3 L4,3 C3.44771525,3 3,3.44771525 3,4 L3,4 L3,4.5 C3,4.77614237 3.22385763,5 3.5,5 L3.5,5 L4.5,5 C4.77614237,5 5,4.77614237 5,4.5 L5,4.5 L5,3.5 C5,3.22385763 4.77614237,3 4.5,3 L4.5,3 Z M12,3 L11.5,3 C11.2238576,3 11,3.22385763 11,3.5 L11,3.5 L11,4.5 C11,4.77614237 11.2238576,5 11.5,5 L11.5,5 L12.5,5 C12.7761424,5 13,4.77614237 13,4.5 L13,4.5 L13,4 C13,3.44771525 12.5522847,3 12,3 L12,3 Z"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.9 KiB |
3
Components/QProxyStyleTest/icons/downloads-symbolic.svg
Normal file
@@ -0,0 +1,3 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
|
||||
<path fill-rule="evenodd" d="M8,1 C11.8659932,1 15,4.13400675 15,8 C15,11.8659932 11.8659932,15 8,15 C4.13400675,15 1,11.8659932 1,8 C1,4.13400675 4.13400675,1 8,1 Z M9.5,8 L6.5,8 C6.22385763,8 6,8.22385763 6,8.5 C6,8.77614237 5.77614237,9 5.5,9 L5.5,9 L5,9 C4.89014373,9 4.78478689,9.04364023 4.70710678,9.12132034 C4.54534632,9.2830808 4.54534632,9.54534632 4.70710678,9.70710678 L4.70710678,9.70710678 L7.64644661,12.6464466 C7.84170876,12.8417088 8.15829124,12.8417088 8.35355339,12.6464466 L8.35355339,12.6464466 L11.2928932,9.70710678 C11.3705733,9.62942667 11.4142136,9.52406983 11.4142136,9.41421356 C11.4142136,9.18544973 11.2287638,9 11,9 L11,9 L10.5,9 C10.2238576,9 10,8.77614237 10,8.5 C10,8.22385763 9.77614237,8 9.5,8 L9.5,8 Z M9.5,6 L6.5,6 C6.22385763,6 6,6.22385763 6,6.5 C6,6.77614237 6.22385763,7 6.5,7 L6.5,7 L9.5,7 C9.77614237,7 10,6.77614237 10,6.5 C10,6.22385763 9.77614237,6 9.5,6 L9.5,6 Z M9.5,4 L6.5,4 C6.22385763,4 6,4.22385763 6,4.5 C6,4.77614237 6.22385763,5 6.5,5 L6.5,5 L9.5,5 C9.77614237,5 10,4.77614237 10,4.5 C10,4.22385763 9.77614237,4 9.5,4 L9.5,4 Z"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.2 KiB |
57
Components/QProxyStyleTest/icons/downloads-symbolic_dark.svg
Normal file
@@ -0,0 +1,57 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
width="16"
|
||||
height="16"
|
||||
viewBox="0 0 16 16"
|
||||
version="1.1"
|
||||
id="svg4"
|
||||
sodipodi:docname="downloads-symbolic_dark.svg"
|
||||
inkscape:version="0.92.4 (5da689c313, 2019-01-14)">
|
||||
<metadata
|
||||
id="metadata10">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<defs
|
||||
id="defs8" />
|
||||
<sodipodi:namedview
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1"
|
||||
objecttolerance="10"
|
||||
gridtolerance="10"
|
||||
guidetolerance="10"
|
||||
inkscape:pageopacity="0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:window-width="1920"
|
||||
inkscape:window-height="982"
|
||||
id="namedview6"
|
||||
showgrid="false"
|
||||
inkscape:zoom="14.75"
|
||||
inkscape:cx="8"
|
||||
inkscape:cy="8"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="0"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="svg4" />
|
||||
<path
|
||||
fill="#FFF"
|
||||
fill-opacity=".8"
|
||||
fill-rule="evenodd"
|
||||
d="M8,1 C11.8659932,1 15,4.13400675 15,8 C15,11.8659932 11.8659932,15 8,15 C4.13400675,15 1,11.8659932 1,8 C1,4.13400675 4.13400675,1 8,1 Z M9.5,8 L6.5,8 C6.22385763,8 6,8.22385763 6,8.5 C6,8.77614237 5.77614237,9 5.5,9 L5.5,9 L5,9 C4.89014373,9 4.78478689,9.04364023 4.70710678,9.12132034 C4.54534632,9.2830808 4.54534632,9.54534632 4.70710678,9.70710678 L4.70710678,9.70710678 L7.64644661,12.6464466 C7.84170876,12.8417088 8.15829124,12.8417088 8.35355339,12.6464466 L8.35355339,12.6464466 L11.2928932,9.70710678 C11.3705733,9.62942667 11.4142136,9.52406983 11.4142136,9.41421356 C11.4142136,9.18544973 11.2287638,9 11,9 L11,9 L10.5,9 C10.2238576,9 10,8.77614237 10,8.5 C10,8.22385763 9.77614237,8 9.5,8 L9.5,8 Z M9.5,6 L6.5,6 C6.22385763,6 6,6.22385763 6,6.5 C6,6.77614237 6.22385763,7 6.5,7 L6.5,7 L9.5,7 C9.77614237,7 10,6.77614237 10,6.5 C10,6.22385763 9.77614237,6 9.5,6 L9.5,6 Z M9.5,4 L6.5,4 C6.22385763,4 6,4.22385763 6,4.5 C6,4.77614237 6.22385763,5 6.5,5 L6.5,5 L9.5,5 C9.77614237,5 10,4.77614237 10,4.5 C10,4.22385763 9.77614237,4 9.5,4 L9.5,4 Z"
|
||||
id="path2"
|
||||
style="fill:#ffffff;fill-opacity:0.60000002" />
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 2.6 KiB |
68
Components/QProxyStyleTest/icons/homepage.svg
Normal file
@@ -0,0 +1,68 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
width="16px"
|
||||
height="16px"
|
||||
viewBox="0 0 16 16"
|
||||
version="1.1"
|
||||
id="svg8"
|
||||
sodipodi:docname="homepage.svg"
|
||||
inkscape:version="0.92.4 (5da689c313, 2019-01-14)">
|
||||
<metadata
|
||||
id="metadata14">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<defs
|
||||
id="defs12" />
|
||||
<sodipodi:namedview
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1"
|
||||
objecttolerance="10"
|
||||
gridtolerance="10"
|
||||
guidetolerance="10"
|
||||
inkscape:pageopacity="0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:window-width="1920"
|
||||
inkscape:window-height="982"
|
||||
id="namedview10"
|
||||
showgrid="false"
|
||||
inkscape:zoom="14.75"
|
||||
inkscape:cx="8"
|
||||
inkscape:cy="8"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="0"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="svg8" />
|
||||
<!-- Generator: Sketch 56.3 (81716) - https://sketch.com -->
|
||||
<title
|
||||
id="title2">category_recommend</title>
|
||||
<desc
|
||||
id="desc4">Created with Sketch.</desc>
|
||||
<g
|
||||
id="category_recommend"
|
||||
stroke="none"
|
||||
stroke-width="1"
|
||||
fill="none"
|
||||
fill-rule="evenodd"
|
||||
style="fill:#000000;fill-opacity:0.86666667">
|
||||
<path
|
||||
d="M8,12.6085145 L4.54924088,14.5160472 C4.06572729,14.783327 3.74708518,14.5504931 3.83503048,14.0113448 L4.5,9.93475242 L1.69148737,7.05624503 C1.30958944,6.6648293 1.44637232,6.27932454 1.97881505,6.19797453 L5.83688104,5.60851449 L7.5726373,1.91049416 C7.8086632,1.40764212 8.19196238,1.40897492 8.4273627,1.91049416 L10.163119,5.60851449 L14.0211849,6.19797453 C14.5617696,6.28056851 14.6893983,6.66586674 14.3085126,7.05624503 L11.5,9.93475242 L12.1649695,14.0113448 C12.2540356,14.557364 11.9269904,14.7793014 11.4507591,14.5160472 L8,12.6085145 Z"
|
||||
id="Star"
|
||||
fill="#536076"
|
||||
style="fill:#000000;fill-opacity:0.86666667" />
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 2.4 KiB |
68
Components/QProxyStyleTest/icons/homepage_dark.svg
Normal file
@@ -0,0 +1,68 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
width="16px"
|
||||
height="16px"
|
||||
viewBox="0 0 16 16"
|
||||
version="1.1"
|
||||
id="svg8"
|
||||
sodipodi:docname="homepage_dark.svg"
|
||||
inkscape:version="0.92.4 (5da689c313, 2019-01-14)">
|
||||
<metadata
|
||||
id="metadata14">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<defs
|
||||
id="defs12" />
|
||||
<sodipodi:namedview
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1"
|
||||
objecttolerance="10"
|
||||
gridtolerance="10"
|
||||
guidetolerance="10"
|
||||
inkscape:pageopacity="0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:window-width="1920"
|
||||
inkscape:window-height="982"
|
||||
id="namedview10"
|
||||
showgrid="false"
|
||||
inkscape:zoom="14.75"
|
||||
inkscape:cx="-15.932203"
|
||||
inkscape:cy="2.5762712"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="0"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="svg8" />
|
||||
<!-- Generator: Sketch 56.3 (81716) - https://sketch.com -->
|
||||
<title
|
||||
id="title2">category_recommend</title>
|
||||
<desc
|
||||
id="desc4">Created with Sketch.</desc>
|
||||
<g
|
||||
id="category_recommend"
|
||||
stroke="none"
|
||||
stroke-width="1"
|
||||
fill="none"
|
||||
fill-rule="evenodd"
|
||||
style="fill:#ffffff;fill-opacity:0.60000002">
|
||||
<path
|
||||
d="M8,12.6085145 L4.54924088,14.5160472 C4.06572729,14.783327 3.74708518,14.5504931 3.83503048,14.0113448 L4.5,9.93475242 L1.69148737,7.05624503 C1.30958944,6.6648293 1.44637232,6.27932454 1.97881505,6.19797453 L5.83688104,5.60851449 L7.5726373,1.91049416 C7.8086632,1.40764212 8.19196238,1.40897492 8.4273627,1.91049416 L10.163119,5.60851449 L14.0211849,6.19797453 C14.5617696,6.28056851 14.6893983,6.66586674 14.3085126,7.05624503 L11.5,9.93475242 L12.1649695,14.0113448 C12.2540356,14.557364 11.9269904,14.7793014 11.4507591,14.5160472 L8,12.6085145 Z"
|
||||
id="Star"
|
||||
fill="#C5CFE0"
|
||||
style="fill:#ffffff;fill-opacity:0.60000002" />
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 2.4 KiB |
54
Components/QProxyStyleTest/icons/refresh-page-dark.svg
Normal file
@@ -0,0 +1,54 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
inkscape:version="1.0 (4035a4fb49, 2020-05-01)"
|
||||
height="16"
|
||||
width="16"
|
||||
sodipodi:docname="refresh-page-dark.svg"
|
||||
xml:space="preserve"
|
||||
viewBox="0 0 16 16"
|
||||
y="0px"
|
||||
x="0px"
|
||||
id="Layer_1"
|
||||
version="1.1"><metadata
|
||||
id="metadata9"><rdf:RDF><cc:Work
|
||||
rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" /><dc:title></dc:title></cc:Work></rdf:RDF></metadata><defs
|
||||
id="defs7" /><sodipodi:namedview
|
||||
inkscape:current-layer="Layer_1"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:window-y="0"
|
||||
inkscape:window-x="0"
|
||||
inkscape:cy="8.8351119"
|
||||
inkscape:cx="12.452215"
|
||||
inkscape:zoom="34.711876"
|
||||
showgrid="true"
|
||||
id="namedview5"
|
||||
inkscape:window-height="958"
|
||||
inkscape:window-width="1920"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:pageopacity="0"
|
||||
guidetolerance="10"
|
||||
gridtolerance="10"
|
||||
objecttolerance="10"
|
||||
borderopacity="1"
|
||||
bordercolor="#666666"
|
||||
pagecolor="#ffffff"><inkscape:grid
|
||||
id="grid834"
|
||||
type="xygrid" /></sodipodi:namedview>
|
||||
<g
|
||||
style="fill:#ffffff;fill-opacity:0.60000002"
|
||||
transform="scale(0.03125,0.0312082)"
|
||||
id="XMLID_2_">
|
||||
<path
|
||||
style="fill:#ffffff;fill-opacity:0.60000002"
|
||||
d="M 436.6,75.4 C 390.1,28.9 326.7,0 256,0 114.5,0 0,114.5 0,256 0,397.5 114.5,512 256,512 375.2,512 474.8,430.1 503.6,320.2 h -67 C 410.5,394.7 339.8,447.7 256,447.7 149.9,447.7 64.2,362.1 64.2,255.9 64.2,149.7 149.9,64.2 256,64.2 c 53.1,0 100.5,22.3 135,56.8 L 287.7,224.3 H 512 V 0 Z"
|
||||
id="XMLID_4_" />
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.9 KiB |
52
Components/QProxyStyleTest/icons/refresh-page.svg
Normal file
@@ -0,0 +1,52 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
inkscape:version="1.0 (4035a4fb49, 2020-05-01)"
|
||||
height="16"
|
||||
width="16"
|
||||
sodipodi:docname="refresh-page.svg"
|
||||
xml:space="preserve"
|
||||
viewBox="0 0 16 16"
|
||||
y="0px"
|
||||
x="0px"
|
||||
id="Layer_1"
|
||||
version="1.1"><metadata
|
||||
id="metadata9"><rdf:RDF><cc:Work
|
||||
rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" /><dc:title></dc:title></cc:Work></rdf:RDF></metadata><defs
|
||||
id="defs7" /><sodipodi:namedview
|
||||
inkscape:current-layer="Layer_1"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:window-y="0"
|
||||
inkscape:window-x="0"
|
||||
inkscape:cy="8.8351119"
|
||||
inkscape:cx="12.452215"
|
||||
inkscape:zoom="34.711876"
|
||||
showgrid="true"
|
||||
id="namedview5"
|
||||
inkscape:window-height="958"
|
||||
inkscape:window-width="1920"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:pageopacity="0"
|
||||
guidetolerance="10"
|
||||
gridtolerance="10"
|
||||
objecttolerance="10"
|
||||
borderopacity="1"
|
||||
bordercolor="#666666"
|
||||
pagecolor="#ffffff"><inkscape:grid
|
||||
id="grid834"
|
||||
type="xygrid" /></sodipodi:namedview>
|
||||
<g
|
||||
transform="scale(0.03125,0.0312082)"
|
||||
id="XMLID_2_">
|
||||
<path
|
||||
d="M 436.6,75.4 C 390.1,28.9 326.7,0 256,0 114.5,0 0,114.5 0,256 0,397.5 114.5,512 256,512 375.2,512 474.8,430.1 503.6,320.2 h -67 C 410.5,394.7 339.8,447.7 256,447.7 149.9,447.7 64.2,362.1 64.2,255.9 64.2,149.7 149.9,64.2 256,64.2 c 53.1,0 100.5,22.3 135,56.8 L 287.7,224.3 H 512 V 0 Z"
|
||||
id="XMLID_4_" />
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.8 KiB |
3
Components/QProxyStyleTest/icons/theme-symbolic.svg
Normal file
@@ -0,0 +1,3 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
|
||||
<path fill-rule="evenodd" d="M3.5,14 C3.22385763,14 3,13.7761424 3,13.5 C3,13.2238576 3.22385763,13 3.5,13 L7,13 L7,12 L2,12 C1.44771525,12 1,11.5522847 1,11 L15,11 C15,11.5522847 14.5522847,12 14,12 L9,12 L9,13 L12.5,13 C12.7761424,13 13,13.2238576 13,13.5 C13,13.7761424 12.7761424,14 12.5,14 L3.5,14 Z M13,2 C14.1045695,2 15,2.8954305 15,4 L15,10 L1,10 L1,4 C1,2.8954305 1.8954305,2 3,2 L13,2 Z"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 494 B |
57
Components/QProxyStyleTest/icons/theme-symbolic_dark.svg
Normal file
@@ -0,0 +1,57 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
width="16"
|
||||
height="16"
|
||||
viewBox="0 0 16 16"
|
||||
version="1.1"
|
||||
id="svg4"
|
||||
sodipodi:docname="theme-symbolic_dark.svg"
|
||||
inkscape:version="0.92.4 (5da689c313, 2019-01-14)">
|
||||
<metadata
|
||||
id="metadata10">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<defs
|
||||
id="defs8" />
|
||||
<sodipodi:namedview
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1"
|
||||
objecttolerance="10"
|
||||
gridtolerance="10"
|
||||
guidetolerance="10"
|
||||
inkscape:pageopacity="0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:window-width="1920"
|
||||
inkscape:window-height="982"
|
||||
id="namedview6"
|
||||
showgrid="false"
|
||||
inkscape:zoom="14.75"
|
||||
inkscape:cx="8"
|
||||
inkscape:cy="8"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="0"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="svg4" />
|
||||
<path
|
||||
fill="#FFF"
|
||||
fill-opacity=".8"
|
||||
fill-rule="evenodd"
|
||||
d="M3.5,14 C3.22385763,14 3,13.7761424 3,13.5 C3,13.2238576 3.22385763,13 3.5,13 L7,13 L7,12 L2,12 C1.44771525,12 1,11.5522847 1,11 L15,11 C15,11.5522847 14.5522847,12 14,12 L9,12 L9,13 L12.5,13 C12.7761424,13 13,13.2238576 13,13.5 C13,13.7761424 12.7761424,14 12.5,14 L3.5,14 Z M13,2 C14.1045695,2 15,2.8954305 15,4 L15,10 L1,10 L1,4 C1,2.8954305 1.8954305,2 3,2 L13,2 Z"
|
||||
id="path2"
|
||||
style="opacity:1;fill:#ffffff;fill-opacity:0.60000002" />
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.9 KiB |
12
Components/QProxyStyleTest/main.cpp
Normal file
@@ -0,0 +1,12 @@
|
||||
#include "widget.h"
|
||||
#include "menubtnstyle.h"
|
||||
#include <QApplication>
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
QApplication a(argc, argv);
|
||||
a.setStyle(new MenuBtnStyle);
|
||||
Widget w;
|
||||
w.show();
|
||||
return a.exec();
|
||||
}
|
||||
125
Components/QProxyStyleTest/menubtnstyle.cpp
Normal file
@@ -0,0 +1,125 @@
|
||||
#include "menubtnstyle.h"
|
||||
#include <QStyleOptionButton>
|
||||
#include <QPainter>
|
||||
#include<QDebug>
|
||||
|
||||
/**
|
||||
* 根据Python版改的,还是Python写起来比较快比较方便
|
||||
*/
|
||||
void MenuBtnStyle::drawControl(QStyle::ControlElement element, const QStyleOption *option,
|
||||
QPainter *painter, const QWidget *widget) const
|
||||
{
|
||||
if (element == QStyle::CE_PushButtonLabel) {
|
||||
const QStyleOptionButton *btnOption = qstyleoption_cast<const QStyleOptionButton *>(option);
|
||||
QStyleOptionButton new_option = *btnOption;
|
||||
QIcon icon = btnOption->icon;
|
||||
new_option.icon = QIcon();
|
||||
QProxyStyle::drawControl(element, &new_option, painter, widget);
|
||||
|
||||
if (icon.isNull()) return;
|
||||
QIcon::Mode mode = btnOption->state & State_Enabled ? QIcon::Normal : QIcon::Disabled;
|
||||
if (mode == QIcon::Normal && btnOption->state & State_HasFocus)
|
||||
mode = QIcon::Active;
|
||||
QIcon::State state = QIcon::Off;
|
||||
if (btnOption->state & State_On)
|
||||
state = QIcon::On;
|
||||
QWindow *window = widget == nullptr ? nullptr : widget->window()->windowHandle();
|
||||
QPixmap pixmap = icon.pixmap(window, btnOption->iconSize, mode, state);
|
||||
int pixmapWidth = pixmap.width() / pixmap.devicePixelRatio();
|
||||
int pixmapHeight = pixmap.height() / pixmap.devicePixelRatio();
|
||||
|
||||
QRect iconRect = QRect(QPoint(), QSize(pixmapWidth, pixmapHeight));
|
||||
int iconSpacing = 4;
|
||||
iconRect.moveCenter(btnOption->rect.center());
|
||||
iconRect.moveLeft(btnOption->rect.left() + iconSpacing);
|
||||
iconRect = visualRect(btnOption->direction, btnOption->rect, iconRect);
|
||||
iconRect.translate(proxy()->pixelMetric(PM_ButtonShiftHorizontal, btnOption, widget),
|
||||
proxy()->pixelMetric(PM_ButtonShiftVertical, btnOption, widget));
|
||||
painter->drawPixmap(iconRect, pixmap);
|
||||
} else {
|
||||
// 其他的control,使用默认渲染机制
|
||||
QProxyStyle::drawControl(element, option, painter, widget);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 这个是直接贴stackoverflow上的回答的,但是好复杂,没太看的懂。
|
||||
*/
|
||||
void MenuBtnStyle::drawControl2(QStyle::ControlElement element, const QStyleOption *option,
|
||||
QPainter *painter, const QWidget *widget) const
|
||||
{
|
||||
if(element==CE_PushButtonLabel)
|
||||
{
|
||||
if (const QStyleOptionButton *button = qstyleoption_cast<const QStyleOptionButton *>(option))
|
||||
{
|
||||
QRect textRect = button->rect;
|
||||
uint tf = Qt::AlignVCenter | Qt::TextShowMnemonic;
|
||||
if (!proxy()->styleHint(SH_UnderlineShortcut, button, widget))
|
||||
tf |= Qt::TextHideMnemonic;
|
||||
|
||||
if (!button->icon.isNull()) {
|
||||
QRect iconRect;
|
||||
QIcon::Mode mode = button->state & State_Enabled ? QIcon::Normal : QIcon::Disabled;
|
||||
if (mode == QIcon::Normal && button->state & State_HasFocus)
|
||||
mode = QIcon::Active;
|
||||
QIcon::State state = QIcon::Off;
|
||||
if (button->state & State_On)
|
||||
state = QIcon::On;
|
||||
|
||||
QWindow *window = widget == nullptr ? nullptr : widget->window()->windowHandle();
|
||||
QPixmap pixmap = button->icon.pixmap(window, button->iconSize, mode, state);
|
||||
|
||||
int pixmapWidth = pixmap.width() / pixmap.devicePixelRatio();
|
||||
int pixmapHeight = pixmap.height() / pixmap.devicePixelRatio();
|
||||
int labelWidth = pixmapWidth;
|
||||
int labelHeight = pixmapHeight;
|
||||
int iconSpacing = 4;//### 4 is currently hardcoded in QPushButton::sizeHint()
|
||||
int textWidth = button->fontMetrics.boundingRect(option->rect, tf, button->text).width();
|
||||
if (!button->text.isEmpty())
|
||||
labelWidth += (textWidth + iconSpacing);
|
||||
|
||||
/*************************************************************/
|
||||
// Make the icon rectangle always be 10px in from the left edge
|
||||
/*************************************************************/
|
||||
iconRect = QRect(10,
|
||||
textRect.y() + (textRect.height() - labelHeight) / 2,
|
||||
pixmapWidth, pixmapHeight);
|
||||
|
||||
iconRect = visualRect(button->direction, textRect, iconRect);
|
||||
|
||||
/***********************************/
|
||||
// Always horizontal align the text
|
||||
/***********************************/
|
||||
tf |= Qt::AlignHCenter;
|
||||
|
||||
|
||||
if (button->state & (State_On | State_Sunken))
|
||||
iconRect.translate(proxy()->pixelMetric(PM_ButtonShiftHorizontal, option, widget),
|
||||
proxy()->pixelMetric(PM_ButtonShiftVertical, option, widget));
|
||||
painter->drawPixmap(iconRect, pixmap);
|
||||
} else {
|
||||
tf |= Qt::AlignHCenter;
|
||||
}
|
||||
if (button->state & (State_On | State_Sunken))
|
||||
textRect.translate(proxy()->pixelMetric(PM_ButtonShiftHorizontal, option, widget),
|
||||
proxy()->pixelMetric(PM_ButtonShiftVertical, option, widget));
|
||||
|
||||
if (button->features & QStyleOptionButton::HasMenu) {
|
||||
int indicatorSize = proxy()->pixelMetric(PM_MenuButtonIndicator, button, widget);
|
||||
if (button->direction == Qt::LeftToRight)
|
||||
textRect = textRect.adjusted(0, 0, -indicatorSize, 0);
|
||||
else
|
||||
textRect = textRect.adjusted(indicatorSize, 0, 0, 0);
|
||||
}
|
||||
proxy()->drawItemText(painter, textRect, tf, button->palette, (button->state & State_Enabled),
|
||||
button->text, QPalette::ButtonText);
|
||||
}
|
||||
|
||||
qDebug() << "调用了吗???";
|
||||
return;
|
||||
}
|
||||
|
||||
// For all other controls, draw the default
|
||||
QProxyStyle::drawControl(element, option, painter, widget);
|
||||
}
|
||||
16
Components/QProxyStyleTest/menubtnstyle.h
Normal file
@@ -0,0 +1,16 @@
|
||||
#ifndef MENUBTNSTYLE_H
|
||||
#define MENUBTNSTYLE_H
|
||||
|
||||
#include <QProxyStyle>
|
||||
#include <QIcon>
|
||||
|
||||
class MenuBtnStyle : public QProxyStyle
|
||||
{
|
||||
public:
|
||||
void drawControl(ControlElement element, const QStyleOption *option,
|
||||
QPainter *painter, const QWidget *widget = nullptr) const override;
|
||||
void drawControl2(ControlElement element, const QStyleOption *option,
|
||||
QPainter *painter, const QWidget *widget = nullptr) const;
|
||||
};
|
||||
|
||||
#endif // MENUBTNSTYLE_H
|
||||
BIN
Components/QProxyStyleTest/screenshot.png
Normal file
|
After Width: | Height: | Size: 30 KiB |
34
Components/QProxyStyleTest/widget.cpp
Normal file
@@ -0,0 +1,34 @@
|
||||
#include "widget.h"
|
||||
#include "ui_widget.h"
|
||||
|
||||
Widget::Widget(QWidget *parent)
|
||||
: QWidget(parent)
|
||||
, ui(new Ui::Widget)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
initUI();
|
||||
}
|
||||
|
||||
void Widget::initUI()
|
||||
{
|
||||
ui->pushButton->setIcon(QIcon(":/icons/icons/homepage.svg"));
|
||||
ui->pushButton_2->setIcon(QIcon(":/icons/icons/category_network.svg"));
|
||||
ui->pushButton_3->setIcon(QIcon(":/icons/icons/category_chat.svg"));
|
||||
ui->pushButton_4->setIcon(QIcon(":/icons/icons/category_music.svg"));
|
||||
ui->pushButton_5->setIcon(QIcon(":/icons/icons/category_video.svg"));
|
||||
ui->pushButton_6->setIcon(QIcon(":/icons/icons/category_graphic.svg"));
|
||||
ui->pushButton_7->setIcon(QIcon(":/icons/icons/category_game.svg"));
|
||||
ui->pushButton_8->setIcon(QIcon(":/icons/icons/category_office.svg"));
|
||||
ui->pushButton_9->setIcon(QIcon(":/icons/icons/category_reading.svg"));
|
||||
ui->pushButton_10->setIcon(QIcon(":/icons/icons/category_develop.svg"));
|
||||
ui->pushButton_11->setIcon(QIcon(":/icons/icons/category_system.svg"));
|
||||
ui->pushButton_12->setIcon(QIcon(":/icons/icons/theme-symbolic.svg"));
|
||||
ui->pushButton_13->setIcon(QIcon(":/icons/icons/category_others.svg"));
|
||||
ui->pushButton_14->setIcon(QIcon(":/icons/icons/downloads-symbolic.svg"));
|
||||
}
|
||||
|
||||
Widget::~Widget()
|
||||
{
|
||||
delete ui;
|
||||
}
|
||||
|
||||
24
Components/QProxyStyleTest/widget.h
Normal file
@@ -0,0 +1,24 @@
|
||||
#ifndef WIDGET_H
|
||||
#define WIDGET_H
|
||||
|
||||
#include <QWidget>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
namespace Ui { class Widget; }
|
||||
QT_END_NAMESPACE
|
||||
|
||||
class Widget : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
Widget(QWidget *parent = nullptr);
|
||||
~Widget();
|
||||
|
||||
private:
|
||||
void initUI();
|
||||
|
||||
private:
|
||||
Ui::Widget *ui;
|
||||
};
|
||||
#endif // WIDGET_H
|
||||
119
Components/QProxyStyleTest/widget.ui
Normal file
@@ -0,0 +1,119 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>Widget</class>
|
||||
<widget class="QWidget" name="Widget">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>267</width>
|
||||
<height>547</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Widget</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<widget class="QPushButton" name="pushButton">
|
||||
<property name="text">
|
||||
<string>Home</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="pushButton_2">
|
||||
<property name="text">
|
||||
<string>Network</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="pushButton_3">
|
||||
<property name="text">
|
||||
<string>Communication</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="pushButton_4">
|
||||
<property name="text">
|
||||
<string>Music</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="pushButton_5">
|
||||
<property name="text">
|
||||
<string>Videos</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="pushButton_6">
|
||||
<property name="text">
|
||||
<string>Graphics</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="pushButton_7">
|
||||
<property name="text">
|
||||
<string>Games</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="pushButton_8">
|
||||
<property name="text">
|
||||
<string>Office</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="pushButton_9">
|
||||
<property name="text">
|
||||
<string>Translate</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="pushButton_10">
|
||||
<property name="text">
|
||||
<string>Development</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="pushButton_11">
|
||||
<property name="text">
|
||||
<string>Tools</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="pushButton_12">
|
||||
<property name="text">
|
||||
<string>Beautify</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="pushButton_13">
|
||||
<property name="text">
|
||||
<string>Others</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="pushButton_14">
|
||||
<property name="text">
|
||||
<string>Download List</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
||||
73
Components/ThreadPool/.gitignore
vendored
Normal file
@@ -0,0 +1,73 @@
|
||||
# This file is used to ignore files which are generated
|
||||
# ----------------------------------------------------------------------------
|
||||
|
||||
*~
|
||||
*.autosave
|
||||
*.a
|
||||
*.core
|
||||
*.moc
|
||||
*.o
|
||||
*.obj
|
||||
*.orig
|
||||
*.rej
|
||||
*.so
|
||||
*.so.*
|
||||
*_pch.h.cpp
|
||||
*_resource.rc
|
||||
*.qm
|
||||
.#*
|
||||
*.*#
|
||||
core
|
||||
!core/
|
||||
tags
|
||||
.DS_Store
|
||||
.directory
|
||||
*.debug
|
||||
Makefile*
|
||||
*.prl
|
||||
*.app
|
||||
moc_*.cpp
|
||||
ui_*.h
|
||||
qrc_*.cpp
|
||||
Thumbs.db
|
||||
*.res
|
||||
*.rc
|
||||
/.qmake.cache
|
||||
/.qmake.stash
|
||||
|
||||
# qtcreator generated files
|
||||
*.pro.user*
|
||||
|
||||
# xemacs temporary files
|
||||
*.flc
|
||||
|
||||
# Vim temporary files
|
||||
.*.swp
|
||||
|
||||
# Visual Studio generated files
|
||||
*.ib_pdb_index
|
||||
*.idb
|
||||
*.ilk
|
||||
*.pdb
|
||||
*.sln
|
||||
*.suo
|
||||
*.vcproj
|
||||
*vcproj.*.*.user
|
||||
*.ncb
|
||||
*.sdf
|
||||
*.opensdf
|
||||
*.vcxproj
|
||||
*vcxproj.*
|
||||
|
||||
# MinGW generated files
|
||||
*.Debug
|
||||
*.Release
|
||||
|
||||
# Python byte code
|
||||
*.pyc
|
||||
|
||||
# Binaries
|
||||
# --------
|
||||
*.dll
|
||||
*.exe
|
||||
|
||||
32
Components/ThreadPool/CustomThreadPool.pro
Normal file
@@ -0,0 +1,32 @@
|
||||
QT -= gui
|
||||
QT += network
|
||||
|
||||
CONFIG += c++11 console
|
||||
CONFIG -= app_bundle
|
||||
|
||||
# The following define makes your compiler emit warnings if you use
|
||||
# any Qt feature that has been marked deprecated (the exact warnings
|
||||
# depend on your compiler). Please consult the documentation of the
|
||||
# deprecated API in order to know how to port your code away from it.
|
||||
DEFINES += QT_DEPRECATED_WARNINGS
|
||||
|
||||
# You can also make your code fail to compile if it uses deprecated APIs.
|
||||
# In order to do so, uncomment the following line.
|
||||
# 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 += \
|
||||
ThreadPool.cpp \
|
||||
Thread.cpp \
|
||||
main.cpp
|
||||
|
||||
# Default rules for deployment.
|
||||
qnx: target.path = /tmp/$${TARGET}/bin
|
||||
else: unix:!android: target.path = /opt/$${TARGET}/bin
|
||||
!isEmpty(target.path): INSTALLS += target
|
||||
|
||||
HEADERS += \
|
||||
PriorityQueue.h \
|
||||
Task.h \
|
||||
Thread.h \
|
||||
ThreadPool.h
|
||||
79
Components/ThreadPool/HeapQueue.hpp
Normal file
@@ -0,0 +1,79 @@
|
||||
#pragma once
|
||||
#include <vector>
|
||||
#include <functional>
|
||||
|
||||
template<
|
||||
typename T,
|
||||
typename Array=std::vector<T>,
|
||||
typename compare_T=std::less<T>
|
||||
>
|
||||
class HeapQueue
|
||||
{
|
||||
public:
|
||||
HeapQueue() { elements.clear(); }
|
||||
|
||||
bool empty() { return elements.size() == 0; }
|
||||
|
||||
T front() { return elements[0]; }
|
||||
|
||||
/**
|
||||
* 入列,并向上调整
|
||||
*/
|
||||
void push(const T &val)
|
||||
{
|
||||
elements.push_back(val);
|
||||
up_update();
|
||||
}
|
||||
|
||||
/**
|
||||
* 出列,弹出栈顶元素
|
||||
*/
|
||||
void pop() {
|
||||
if (empty())
|
||||
return ;
|
||||
int n = elements.size();
|
||||
std::swap(elements[n-1], elements[0]);
|
||||
elements.pop_back();
|
||||
down_update();
|
||||
return ;
|
||||
}
|
||||
|
||||
private:
|
||||
/**
|
||||
* 向上调整
|
||||
*/
|
||||
void up_update()
|
||||
{
|
||||
int ind = elements.size();
|
||||
while (ind > 1 && compare(elements[ind / 2 - 1], elements[ind - 1]))
|
||||
{
|
||||
std::swap(elements[ind / 2 - 1], elements[ind - 1]);
|
||||
ind /= 2;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 向下调整
|
||||
*/
|
||||
void down_update()
|
||||
{
|
||||
int ind = 0, n = elements.size();
|
||||
while (ind * 2 + 1 < n)
|
||||
{
|
||||
int tind = ind;
|
||||
if (compare(elements[tind], elements[ind * 2 + 1]))
|
||||
tind = ind * 2 + 1;
|
||||
|
||||
if (ind * 2 + 2 < n && compare(elements[tind], elements[ind * 2 + 2]))
|
||||
tind = ind * 2 + 2;
|
||||
|
||||
if (ind == tind)
|
||||
break;
|
||||
std::swap(elements[ind], elements[tind]);
|
||||
ind = tind;
|
||||
}
|
||||
}
|
||||
|
||||
Array elements;
|
||||
compare_T compare;
|
||||
};
|
||||
99
Components/ThreadPool/PriorityQueue.h
Normal file
@@ -0,0 +1,99 @@
|
||||
#pragma once
|
||||
|
||||
#include <QVector>
|
||||
#include <algorithm>
|
||||
|
||||
template <
|
||||
typename T,
|
||||
typename Array = QVector<T>,
|
||||
typename compare_T=std::less<T>
|
||||
>
|
||||
class PriorityQueue
|
||||
{
|
||||
public:
|
||||
PriorityQueue();
|
||||
bool empty();
|
||||
T front();
|
||||
void push(const T& val);
|
||||
void pop();
|
||||
int size();
|
||||
|
||||
private:
|
||||
void up_adjust(); // 向上调整
|
||||
void down_adjust(); // 向下调整
|
||||
|
||||
Array elements;
|
||||
compare_T compare;
|
||||
};
|
||||
|
||||
template<typename T, typename Array, typename compare_T>
|
||||
PriorityQueue<T, Array, compare_T>::PriorityQueue()
|
||||
{
|
||||
elements.clear();
|
||||
}
|
||||
|
||||
template<typename T, typename Array, typename compare_T>
|
||||
bool PriorityQueue<T, Array, compare_T>::empty()
|
||||
{
|
||||
return elements.size() == 0;
|
||||
}
|
||||
|
||||
template<typename T, typename Array, typename compare_T>
|
||||
T PriorityQueue<T, Array, compare_T>::front()
|
||||
{
|
||||
return elements[0];
|
||||
}
|
||||
|
||||
template<typename T, typename Array, typename compare_T>
|
||||
void PriorityQueue<T, Array, compare_T>::push(const T &val)
|
||||
{
|
||||
elements.push_back(val);
|
||||
up_adjust();
|
||||
}
|
||||
|
||||
template<typename T, typename Array, typename compare_T>
|
||||
void PriorityQueue<T, Array, compare_T>::pop()
|
||||
{
|
||||
if (empty()) return;
|
||||
int count = elements.size();
|
||||
qSwap(elements[count - 1], elements[0]);
|
||||
elements.pop_back();
|
||||
down_adjust();
|
||||
}
|
||||
|
||||
template<typename T, typename Array, typename compare_T>
|
||||
int PriorityQueue<T, Array, compare_T>::size()
|
||||
{
|
||||
return elements.size();
|
||||
}
|
||||
|
||||
template<typename T, typename Array, typename compare_T>
|
||||
void PriorityQueue<T, Array, compare_T>::up_adjust()
|
||||
{
|
||||
int ind = elements.size();
|
||||
while (ind > 1 && compare(elements[ind/2-1], elements[ind-1])) {
|
||||
qSwap(elements[ind/2-1], elements[ind-1]);
|
||||
ind /= 2;
|
||||
}
|
||||
}
|
||||
|
||||
template<typename T, typename Array, typename compare_T>
|
||||
void PriorityQueue<T, Array, compare_T>::down_adjust()
|
||||
{
|
||||
int ind = 0;
|
||||
int count = elements.size();
|
||||
while (ind * 2 + 1 < count) {
|
||||
int tind = ind;
|
||||
if (compare(elements[tind], elements[ind*2+1]))
|
||||
tind = ind * 2 + 1;
|
||||
|
||||
if (ind*2+2<count && compare(elements[tind], elements[ind*2+1]))
|
||||
tind = ind * 2 + 2;
|
||||
|
||||
if (ind == tind)
|
||||
break;
|
||||
|
||||
qSwap(elements[ind], elements[tind]);
|
||||
ind = tind;
|
||||
}
|
||||
}
|
||||
36
Components/ThreadPool/Task.h
Normal file
@@ -0,0 +1,36 @@
|
||||
#pragma once
|
||||
|
||||
#include <functional>
|
||||
|
||||
class Task
|
||||
{
|
||||
public:
|
||||
Task(){};
|
||||
|
||||
template<typename Func, typename ...Args>
|
||||
Task(Func f, Args&& ...args)
|
||||
{
|
||||
func = std::bind(f, std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
virtual void run()
|
||||
{
|
||||
func();
|
||||
}
|
||||
|
||||
void setPriority(int priority)
|
||||
{
|
||||
m_priority = priority;
|
||||
}
|
||||
|
||||
friend bool operator<(const Task& t1, const Task& t2);
|
||||
|
||||
private:
|
||||
std::function<void()> func;
|
||||
int m_priority = 100;
|
||||
};
|
||||
|
||||
inline bool operator<(const Task& t1, const Task& t2)
|
||||
{
|
||||
return t1.m_priority < t2.m_priority;
|
||||
}
|
||||
75
Components/ThreadPool/Thread.cpp
Normal file
@@ -0,0 +1,75 @@
|
||||
#include "Thread.h"
|
||||
#include "ThreadPool.h"
|
||||
#include <QDebug>
|
||||
|
||||
Thread::Thread(int id, ThreadPool *pool, QObject *parent) :
|
||||
QObject(parent),
|
||||
m_threadPool(pool),
|
||||
m_id(id)
|
||||
{
|
||||
|
||||
moveToThread(&m_thread);
|
||||
connect(&m_thread, &QThread::started, [this](){
|
||||
emit threadStarted();
|
||||
run();
|
||||
});
|
||||
connect(&m_thread, &QThread::finished, [this](){
|
||||
emit threadStoped();
|
||||
});
|
||||
}
|
||||
|
||||
Thread::~Thread()
|
||||
{
|
||||
if (isStarted())
|
||||
stop();
|
||||
}
|
||||
|
||||
int Thread::id() const
|
||||
{
|
||||
return m_id;
|
||||
}
|
||||
|
||||
bool Thread::start()
|
||||
{
|
||||
bool ok = false;
|
||||
if (!isStarted()) {
|
||||
m_thread.start();
|
||||
ok = true;
|
||||
}
|
||||
return ok;
|
||||
}
|
||||
|
||||
bool Thread::stop()
|
||||
{
|
||||
bool ok = false;
|
||||
if (isStarted()) {
|
||||
m_thread.quit();
|
||||
m_thread.wait();
|
||||
emit threadStoped();
|
||||
ok = true;
|
||||
}
|
||||
return ok;
|
||||
}
|
||||
|
||||
bool Thread::isStarted() const
|
||||
{
|
||||
return m_thread.isRunning();
|
||||
}
|
||||
|
||||
void Thread::run()
|
||||
{
|
||||
// 就是抢任务这一块出问题了,任务输入的太快
|
||||
while (true) {
|
||||
QMutexLocker lock(&(m_threadPool->m_mutex));
|
||||
// qDebug() << QString("线程%1 进入等待!").arg(m_id);
|
||||
m_threadPool->m_cond.wait(lock.mutex());
|
||||
// qDebug() << QString("线程%1 被唤醒!").arg(m_id);
|
||||
if (!m_threadPool->is_running && m_threadPool->m_tasks.empty()) {
|
||||
return;
|
||||
}
|
||||
m_task = m_threadPool->m_tasks.front();
|
||||
m_threadPool->m_tasks.pop();
|
||||
m_task.run();
|
||||
}
|
||||
}
|
||||
|
||||
32
Components/ThreadPool/Thread.h
Normal file
@@ -0,0 +1,32 @@
|
||||
#pragma once
|
||||
|
||||
#include <QObject>
|
||||
#include <QThread>
|
||||
#include <thread>
|
||||
#include "Task.h"
|
||||
|
||||
class ThreadPool;
|
||||
|
||||
class Thread : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit Thread(int id = 0, ThreadPool *pool = nullptr, QObject *parent= nullptr);
|
||||
virtual ~Thread();
|
||||
virtual int id() const;
|
||||
virtual bool start();
|
||||
virtual bool stop();
|
||||
virtual bool isStarted() const;
|
||||
virtual void run();
|
||||
|
||||
signals:
|
||||
void threadStarted();
|
||||
void threadStoped();
|
||||
|
||||
private:
|
||||
QThread m_thread;
|
||||
Task m_task;
|
||||
ThreadPool *m_threadPool;
|
||||
int m_id;
|
||||
};
|
||||
|
||||
49
Components/ThreadPool/ThreadPool.cpp
Normal file
@@ -0,0 +1,49 @@
|
||||
#include "ThreadPool.h"
|
||||
#include "Thread.h"
|
||||
#include <QDebug>
|
||||
#include <algorithm>
|
||||
|
||||
ThreadPool::ThreadPool(size_t threads_num, QObject *parent)
|
||||
: QObject(parent)
|
||||
{
|
||||
for (size_t i = 0; i < threads_num; i++) {
|
||||
m_threads.push_back(QSharedPointer<Thread>(new Thread(i, this)));
|
||||
}
|
||||
}
|
||||
|
||||
ThreadPool::~ThreadPool()
|
||||
{
|
||||
{
|
||||
QMutexLocker lock(&m_mutex);
|
||||
is_running = false;
|
||||
}
|
||||
m_cond.wakeAll();
|
||||
// 等待线程退出
|
||||
for (auto thread : m_threads) {
|
||||
thread->stop();
|
||||
}
|
||||
m_threads.clear(); // 智能指针自动释放内存
|
||||
}
|
||||
|
||||
void ThreadPool::enqueue(Task &t)
|
||||
{
|
||||
QMutexLocker lock(&m_mutex);
|
||||
if (!is_running) {
|
||||
return;
|
||||
}
|
||||
m_tasks.push(std::move(t));
|
||||
m_cond.wakeOne();
|
||||
}
|
||||
|
||||
void ThreadPool::start()
|
||||
{
|
||||
is_running = true;
|
||||
for (auto thread : m_threads) {
|
||||
thread->start();
|
||||
}
|
||||
}
|
||||
|
||||
int ThreadPool::tasksCount()
|
||||
{
|
||||
return m_tasks.size();
|
||||
}
|
||||
35
Components/ThreadPool/ThreadPool.h
Normal file
@@ -0,0 +1,35 @@
|
||||
#pragma once
|
||||
|
||||
#include "PriorityQueue.h"
|
||||
#include "Task.h"
|
||||
|
||||
#include <QThread>
|
||||
#include <QVector>
|
||||
#include <QMutex>
|
||||
#include <QMutexLocker>
|
||||
#include <QWaitCondition>
|
||||
#include <QSharedPointer>
|
||||
#include <QTimer>
|
||||
|
||||
class Thread;
|
||||
|
||||
|
||||
using QueueType = PriorityQueue<Task>;
|
||||
class ThreadPool : public QObject
|
||||
{
|
||||
public:
|
||||
ThreadPool(size_t threads_num = QThread::idealThreadCount(), QObject *parent = nullptr);
|
||||
~ThreadPool();
|
||||
void enqueue(Task& t);
|
||||
void start();
|
||||
int tasksCount();
|
||||
|
||||
private:
|
||||
QVector<QSharedPointer<Thread>> m_threads;
|
||||
bool is_running = false;
|
||||
QueueType m_tasks;
|
||||
QMutex m_mutex;
|
||||
QWaitCondition m_cond;
|
||||
|
||||
friend class Thread;
|
||||
};
|
||||
115
Components/ThreadPool/ThreadPool.hpp
Normal file
@@ -0,0 +1,115 @@
|
||||
#pragma once
|
||||
#include <cstdlib>
|
||||
#include <thread>
|
||||
#include <vector>
|
||||
#include <queue>
|
||||
#include <mutex>
|
||||
#include <condition_variable>
|
||||
#include <iostream>
|
||||
#include <functional>
|
||||
|
||||
class Task
|
||||
{
|
||||
public:
|
||||
template<typename Func, typename ...Args>
|
||||
Task(Func&& f, Args&& ...args)
|
||||
{
|
||||
func = std::bind(std::forward<Func>(f), std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
void run()
|
||||
{
|
||||
std::cout << "开始运行任务函数!" << std::endl;
|
||||
func();
|
||||
return;
|
||||
}
|
||||
|
||||
private:
|
||||
std::function<void()> func;
|
||||
};
|
||||
|
||||
/**
|
||||
* 将线程池改成模板类,让任务队列可配置
|
||||
*/
|
||||
template<typename QueueType = std::queue<Task*>>
|
||||
class ThreadPool
|
||||
{
|
||||
public:
|
||||
ThreadPool(size_t n)
|
||||
{
|
||||
|
||||
for (int i = 0; i < n; i++) {
|
||||
threads.push_back(new std::thread(
|
||||
&ThreadPool::thread_worker, this
|
||||
));
|
||||
}
|
||||
}
|
||||
~ThreadPool()
|
||||
{
|
||||
{
|
||||
std::unique_lock<std::mutex> lock(m_mutex);
|
||||
is_running = false; // 线程池即将要销毁停止工作了
|
||||
}
|
||||
m_cond.notify_all();
|
||||
for(auto &worker : threads) {
|
||||
worker->join();
|
||||
delete worker;
|
||||
worker = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 工作线程入口函数,在取任务和执行任务之间做循环,
|
||||
* 直到整个线程池停止工作、被销毁为止
|
||||
*/
|
||||
void thread_worker()
|
||||
{
|
||||
while (is_running) {
|
||||
Task *t = getOneTask();
|
||||
if (t == nullptr) {
|
||||
std::cout << "获取任务失败 调用了个寂寞" << std::endl;
|
||||
return;
|
||||
} else {
|
||||
std::cout << "拿到了任务,耶耶耶" << std::endl;
|
||||
}
|
||||
t->run();
|
||||
}
|
||||
}
|
||||
|
||||
Task *getOneTask()
|
||||
{
|
||||
{
|
||||
// 进入线程临界区时加锁
|
||||
std::unique_lock<std::mutex> lock(m_mutex);
|
||||
// 等待任务
|
||||
m_cond.wait(lock, [this](){
|
||||
return is_running && tasks.empty();
|
||||
});
|
||||
Task *t = nullptr;
|
||||
if (is_running) {
|
||||
t = tasks.front();
|
||||
tasks.pop();
|
||||
}
|
||||
return t;
|
||||
}
|
||||
}
|
||||
|
||||
void addOneTask(Task *t)
|
||||
{
|
||||
std::unique_lock<std::mutex> lock(m_mutex);
|
||||
// 线程池停止,不允许再添加新的任务
|
||||
if (!is_running) {
|
||||
return;
|
||||
}
|
||||
tasks.push(t);
|
||||
std::cout << "添加任务成功!";
|
||||
m_cond.notify_one();
|
||||
}
|
||||
|
||||
private:
|
||||
std::vector<std::thread *> threads;
|
||||
bool is_running = true;
|
||||
QueueType tasks;
|
||||
std::mutex m_mutex;
|
||||
std::condition_variable m_cond;
|
||||
};
|
||||
206
Components/ThreadPool/main.cpp
Normal file
@@ -0,0 +1,206 @@
|
||||
#include "ThreadPool.h"
|
||||
|
||||
#include <QCoreApplication>
|
||||
#include <QMutex>
|
||||
#include <QMutexLocker>
|
||||
#include <QDebug>
|
||||
#include <QFile>
|
||||
#include <QFileInfo>
|
||||
#include <QtNetwork/QNetworkRequest>
|
||||
#include <QtNetwork/QNetworkReply>
|
||||
#include <QtNetwork/QNetworkAccessManager>
|
||||
#include <QTimer>
|
||||
|
||||
qint64 getFileSize(const QString& url);
|
||||
void multiDownload(const QString &url, qint64 fileSize, const QString &filename);
|
||||
|
||||
ThreadPool pool;
|
||||
|
||||
QMutex mutex;
|
||||
int count = 0;
|
||||
|
||||
void sum(int a, int b)
|
||||
{
|
||||
QMutexLocker lock(&mutex);
|
||||
count++;
|
||||
qDebug() << QString("%1+%2=%3").arg(a).arg(b).arg(a+b);
|
||||
qDebug() << QString("第%1次计算").arg(count);
|
||||
}
|
||||
|
||||
void event()
|
||||
{
|
||||
{
|
||||
QMutexLocker lock(&mutex);
|
||||
qDebug() << "当前线程ID为:" << QThread::currentThreadId() << ",开始执行任务";
|
||||
}
|
||||
QTimer timer;
|
||||
QObject::connect(&timer, &QTimer::timeout, [](){
|
||||
QMutexLocker lock(&mutex);
|
||||
qDebug() << "当前线程ID为:" << QThread::currentThreadId() << ",定时器触发成功";
|
||||
});
|
||||
timer.setInterval(1000);
|
||||
timer.start();
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
QCoreApplication a(argc, argv);
|
||||
|
||||
// 测试计算任务
|
||||
if (false) {
|
||||
ThreadPool pool;
|
||||
pool.start();
|
||||
qDebug() << "线程池启动完毕,当前任务队列有任务" << pool.tasksCount();
|
||||
for(size_t i = 0; i < 100; i++) {
|
||||
Task t(sum, i, i);
|
||||
pool.enqueue(t);
|
||||
}
|
||||
qDebug() << "任务添加完毕,当前任务队列有任务" << pool.tasksCount();
|
||||
QTimer timer;
|
||||
QObject::connect(&timer, &QTimer::timeout, [&pool](){
|
||||
qDebug() << "当前任务队列有任务" << pool.tasksCount();
|
||||
});
|
||||
timer.setInterval(1000);
|
||||
timer.start();
|
||||
}
|
||||
|
||||
// 测试定时器任务
|
||||
if (true) {
|
||||
pool.start();
|
||||
qDebug() << "线程池启动完毕,当前任务队列有任务" << pool.tasksCount();
|
||||
for(size_t i = 0; i < 100; i++) {
|
||||
Task t(event);
|
||||
pool.enqueue(t);
|
||||
}
|
||||
qDebug() << "任务添加完毕,当前任务队列有任务" << pool.tasksCount();
|
||||
}
|
||||
|
||||
// 测试下载任务
|
||||
if (false) {
|
||||
pool.start();
|
||||
QString url = "https://sample-videos.com/video123/mp4/720/big_buck_bunny_720p_10mb.mp4";
|
||||
qint64 fileSize = getFileSize(url);
|
||||
QString filename = QFileInfo(url).fileName();
|
||||
multiDownload(url, fileSize, filename);
|
||||
}
|
||||
return a.exec();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief 获取要下载的文件大小
|
||||
* @param url
|
||||
*/
|
||||
qint64 getFileSize(const QString& url)
|
||||
{
|
||||
|
||||
QNetworkAccessManager requestManager;
|
||||
QEventLoop event;
|
||||
QNetworkRequest request;
|
||||
request.setUrl(QUrl(url));
|
||||
request.setAttribute(QNetworkRequest::FollowRedirectsAttribute, true);
|
||||
QNetworkReply *reply = requestManager.head(request);
|
||||
QObject::connect(reply, &QNetworkReply::errorOccurred, [reply](QNetworkReply::NetworkError error){
|
||||
if (error != QNetworkReply::NoError) {
|
||||
qDebug() << reply->errorString();
|
||||
}
|
||||
});
|
||||
QObject::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();
|
||||
}
|
||||
reply->deleteLater();
|
||||
return fileSize;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief 多线程下载
|
||||
* @param url
|
||||
* @param fileSize
|
||||
* @param filename
|
||||
* @param threadCount
|
||||
*/
|
||||
void multiDownload(const QString &url, qint64 fileSize, const QString &filename)
|
||||
{
|
||||
int threadCount = QThread::idealThreadCount();
|
||||
|
||||
QFile file(filename);
|
||||
if (file.exists())
|
||||
file.remove();
|
||||
if (!file.open(QIODevice::WriteOnly)) {
|
||||
qDebug() << file.errorString();
|
||||
return;
|
||||
}
|
||||
file.resize(fileSize);
|
||||
|
||||
// 任务等分
|
||||
qint64 segmentSize = fileSize / threadCount;
|
||||
QVector<QPair<qint64, qint64>> vec(threadCount);
|
||||
for (int i = 0; i < threadCount; i++) {
|
||||
vec[i].first = i * segmentSize;
|
||||
vec[i].second = i * segmentSize + segmentSize - 1;
|
||||
}
|
||||
vec[threadCount-1].second = fileSize; // 余数部分加入最后一个
|
||||
|
||||
qint64 bytesReceived = 0; // 下载接收的总字节数
|
||||
|
||||
QMutex mutex;
|
||||
|
||||
auto writeFile = [&](qint64 pos, QByteArray data){
|
||||
QMutexLocker lock(&mutex);
|
||||
qDebug() << QString("跳转文件位置%1,写入数据%2").arg(pos).arg(data.size());
|
||||
file.seek(pos);
|
||||
file.write(data);
|
||||
bytesReceived += data.size();
|
||||
if (fileSize == bytesReceived) {
|
||||
file.close();
|
||||
qDebug() << "下载完毕";
|
||||
}
|
||||
};
|
||||
|
||||
// 任务队列
|
||||
auto downloadFunc = [writeFile, url](const QPair<qint64, qint64>& pair) {
|
||||
qDebug() << QString("当前线程ID") << QThread::currentThreadId();
|
||||
QNetworkAccessManager *mgr = new QNetworkAccessManager;
|
||||
QNetworkRequest request;
|
||||
request.setUrl(url);
|
||||
request.setAttribute(QNetworkRequest::FollowRedirectsAttribute, true);
|
||||
request.setRawHeader("Range", QString("bytes=%1-%2").arg(pair.first).arg(pair.second).toLocal8Bit());
|
||||
QNetworkReply *reply = mgr->get(request);
|
||||
qint64 writePos = pair.first;
|
||||
qint64 currentReceived = 0;
|
||||
qDebug() << "开始下载数据:" << QString(" %1~%2 ").arg(pair.first).arg(pair.second);
|
||||
QObject::connect(reply, &QNetworkReply::readyRead, [reply, writePos, writeFile, ¤tReceived](){
|
||||
qDebug() << "测试,呜啦啦啦啦";
|
||||
qDebug() << "当前 currentReceived 的值为:" << currentReceived;
|
||||
qDebug() << QString("没有任何响应吗? writePos = %1, currentReceived=%2").arg(writePos).arg(currentReceived);
|
||||
QByteArray data = reply->readAll();
|
||||
writeFile(writePos + currentReceived, data);
|
||||
currentReceived += data.size();
|
||||
});
|
||||
QObject::connect(reply, &QNetworkReply::finished, [](){
|
||||
qDebug() << "线程" << QThread::currentThreadId() << "下载完毕";
|
||||
});
|
||||
QObject::connect(reply, &QNetworkReply::errorOccurred, [reply](QNetworkReply::NetworkError error){
|
||||
qDebug() << "发生了错误,呜啦啦啦" << reply->errorString();
|
||||
});
|
||||
QObject::connect(reply, &QNetworkReply::finished, mgr, &QNetworkAccessManager::deleteLater);
|
||||
// 测试事件循环
|
||||
QTimer timer;
|
||||
timer.setInterval(1000);
|
||||
timer.start();
|
||||
QObject::connect(&timer, &QTimer::timeout, [](){
|
||||
qDebug() << "的确有触发事件循环,可喜可贺!";
|
||||
});
|
||||
};
|
||||
qDebug() << QString("主线程ID") << QThread::currentThreadId();
|
||||
for (auto &pair : vec) {
|
||||
qDebug() << "输入任务数据,耶耶耶!";
|
||||
Task t(downloadFunc, pair);
|
||||
pool.enqueue(t);
|
||||
}
|
||||
}
|
||||