DownloadWidget.cpp raw
  1#include "DownloadWidget.h"
  2#include <QHBoxLayout>
  3#include <QLabel>
  4#include <QProgressBar>
  5#include <QPushButton>
  6#include <QWebEngineDownloadRequest>
  7
  8DownloadWidget::DownloadWidget(QWebEngineDownloadRequest *downloadReq) : QFrame(nullptr), download(downloadReq) {
  9	setFrameStyle(QFrame::StyledPanel | QFrame::Plain);
 10	setFrameShape(QFrame::NoFrame);
 11
 12	auto *layout = new QHBoxLayout(this);
 13	layout->setContentsMargins(4, 2, 4, 2);
 14	layout->setSpacing(6);
 15
 16	QString filename = downloadReq->downloadFileName();
 17	if (filename.isEmpty()) {
 18		QString path = downloadReq->url().path();
 19		filename = path.mid(path.lastIndexOf('/') + 1);
 20		if (filename.isEmpty()) {
 21			filename = "download";
 22		}
 23	}
 24
 25	filenameLabel = new QLabel(filename, this);
 26	filenameLabel->setMaximumWidth(250);
 27
 28	progressBar = new QProgressBar(this);
 29	progressBar->setMinimum(0);
 30	progressBar->setMaximum(100);
 31	progressBar->setValue(0);
 32	progressBar->setTextVisible(false);
 33	progressBar->setFixedHeight(18);
 34
 35	statusLabel = new QLabel("0%", this);
 36	statusLabel->setFixedWidth(80);
 37	statusLabel->setAlignment(Qt::AlignRight | Qt::AlignVCenter);
 38
 39	button = new QPushButton(QStringLiteral("\u2715"), this);
 40	button->setFixedSize(22, 22);
 41	button->setFlat(true);
 42
 43	layout->addWidget(filenameLabel);
 44	layout->addWidget(progressBar, 1);
 45	layout->addWidget(statusLabel);
 46	layout->addWidget(button);
 47
 48	connect(button, &QPushButton::clicked, this, &DownloadWidget::onButtonClicked);
 49	connect(download, &QWebEngineDownloadRequest::receivedBytesChanged, this, [this]() { onDownloadProgress(download->receivedBytes(), download->totalBytes()); });
 50	connect(download, &QWebEngineDownloadRequest::totalBytesChanged, this, [this]() { onDownloadProgress(download->receivedBytes(), download->totalBytes()); });
 51	connect(download, &QWebEngineDownloadRequest::stateChanged, this, &DownloadWidget::onStateChanged);
 52	connect(download, &QWebEngineDownloadRequest::isFinishedChanged, this, &DownloadWidget::onStateChanged);
 53
 54	if (download->state() == QWebEngineDownloadRequest::DownloadInProgress || download->state() == QWebEngineDownloadRequest::DownloadCompleted) {
 55		onStateChanged();
 56	}
 57}
 58
 59bool DownloadWidget::isCompleted() const {
 60	auto state = download->state();
 61	return state == QWebEngineDownloadRequest::DownloadCompleted || state == QWebEngineDownloadRequest::DownloadCancelled || state == QWebEngineDownloadRequest::DownloadInterrupted;
 62}
 63
 64void DownloadWidget::onDownloadProgress(qint64 received, qint64 total) {
 65	if (total > 0) {
 66		int pct = qBound(0, static_cast<int>(received * 100 / total), 100);
 67		progressBar->setValue(pct);
 68		statusLabel->setText(QString("%1%").arg(pct));
 69	} else {
 70		progressBar->setValue(0);
 71		statusLabel->setText(formatSize(received) + " / ?");
 72	}
 73}
 74
 75void DownloadWidget::onStateChanged() {
 76	switch (download->state()) {
 77		case QWebEngineDownloadRequest::DownloadInProgress:
 78			statusLabel->setStyleSheet("color: inherit;");
 79			button->setText(QStringLiteral("\u2715"));
 80			break;
 81		case QWebEngineDownloadRequest::DownloadCompleted:
 82			progressBar->setValue(100);
 83			statusLabel->setText("Complete");
 84			statusLabel->setStyleSheet("color: green;");
 85			button->setText("Dismiss");
 86			break;
 87		case QWebEngineDownloadRequest::DownloadCancelled:
 88			statusLabel->setText("Cancelled");
 89			statusLabel->setStyleSheet("color: orange;");
 90			button->setText("Dismiss");
 91			break;
 92		case QWebEngineDownloadRequest::DownloadInterrupted:
 93			statusLabel->setText("Failed");
 94			statusLabel->setStyleSheet("color: red;");
 95			button->setText("Dismiss");
 96			break;
 97		default:
 98			break;
 99	}
100}
101
102void DownloadWidget::onButtonClicked() {
103	if (download->state() == QWebEngineDownloadRequest::DownloadInProgress || download->state() == QWebEngineDownloadRequest::DownloadRequested) {
104		download->cancel();
105	} else {
106		emit removeRequested(this);
107	}
108}
109
110QString DownloadWidget::formatSize(qint64 bytes) {
111	if (bytes < 1024) {
112		return QString("%1 B").arg(bytes);
113	}
114	if (bytes < 1024 * 1024) {
115		return QString("%1 KB").arg(bytes / 1024);
116	}
117	if (bytes < 1024 * 1024 * 1024) {
118		return QString("%1 MB").arg(bytes / (1024 * 1024));
119	}
120	return QString("%1 GB").arg(bytes / (1024 * 1024 * 1024));
121}