From c412743642b59b1c83d55889db6bc9a3ce088c9f Mon Sep 17 00:00:00 2001
From: zty199 <1282441920@qq.com>
Date: Tue, 1 Dec 2020 15:15:47 +0800
Subject: [PATCH] Fix Bugs & Improve Features

Restrict downloading one file at a time;
Fix a bug if downloading second file, the progress bar won't show;
Support pause / resume / cancel download operation.
---
 spark-webapp-runtime/mainwindow.cpp           | 149 +++++++++++++-----
 spark-webapp-runtime/mainwindow.h             |  14 ++
 .../spark-webapp-runtime_zh_CN.qm             | Bin 2827 -> 3156 bytes
 .../spark-webapp-runtime_zh_CN.ts             |  51 ++++--
 4 files changed, 163 insertions(+), 51 deletions(-)

diff --git a/spark-webapp-runtime/mainwindow.cpp b/spark-webapp-runtime/mainwindow.cpp
index 0bb2716..c231fcd 100644
--- a/spark-webapp-runtime/mainwindow.cpp
+++ b/spark-webapp-runtime/mainwindow.cpp
@@ -1,12 +1,10 @@
-#include "mainwindow.h"
+#include "mainwindow.h"
 
 #include <DMainWindow>
 #include <DWidgetUtil>
 #include <DTitlebar>
 #include <DMessageManager>
-#include <DPushButton>
 
-#include <QLayout>
 #include <QFileInfo>
 #include <QFileDialog>
 #include <QDir>
@@ -40,9 +38,15 @@ MainWindow::MainWindow(QString szTitle,
     , t_show(new QAction(tr("Show MainWindow")))
     , t_about(new QAction(tr("About")))
     , t_exit(new QAction(tr("Exit")))
+    , downloadProgressBar(new QWidget)
     , bar(new DProgressBar)
+    , pause(new DPushButton(tr("Pause")))
+    , resume(new DPushButton(tr("Resume")))
+    , cancel(new DPushButton(tr("Cancel")))
+    , progress(new QHBoxLayout)
     , message(new DFloatingMessage(DFloatingMessage::ResidentType))
     , process(new QProcess)
+    , isCanceled(false)
     , mtray(tray)
     , mFixSize(nFixSize)
     , m_width(nWidth)
@@ -111,6 +115,17 @@ MainWindow::MainWindow(QString szTitle,
         m_tray->show(); // 启用托盘时显示
     }
 
+    /* 初始化 DownloadProgressBar */
+    bar->setFixedSize(250, 8);
+    progress->addWidget(bar);
+    progress->addSpacing(5);
+    progress->addWidget(pause);
+    progress->addWidget(resume);
+    progress->addWidget(cancel);
+    downloadProgressBar->setLayout(progress);
+    message->setIcon(QIcon::fromTheme("deepin-download").pixmap(64, 64));
+    message->setWidget(downloadProgressBar);
+
     connect(btnBack, &DToolButton::clicked, this, [&]()
     {
         m_widget->goBack();
@@ -292,58 +307,116 @@ void MainWindow::trayIconActivated(QSystemTrayIcon::ActivationReason reason)
 }
 
 void MainWindow::on_downloadStart(QWebEngineDownloadItem *item)
-
 {
-    QString fileName = QFileInfo(item->path()).fileName();
-    QString filePath = saveAs(fileName);
-    if(filePath.isEmpty())
+    /* 尝试加锁互斥量,禁止同时下载多个文件 */
+    if(mutex.tryLock())
     {
-        return;
+        QString fileName = QFileInfo(item->path()).fileName();
+        QString filePath = saveAs(fileName);
+        if(filePath.isEmpty())
+        {
+            return;
+        }
+        item->setPath(filePath);
+        filePath = QFileInfo(item->path()).absoluteFilePath();
+
+        connect(item, &QWebEngineDownloadItem::downloadProgress, this, &MainWindow::on_downloadProgress);
+        connect(item, &QWebEngineDownloadItem::finished, this, [=]()
+        {
+            on_downloadFinish(filePath);
+        });
+
+        connect(pause, &DPushButton::clicked, this, [=]()
+        {
+            on_downloadPause(item);
+        });
+        connect(resume, &DPushButton::clicked, this, [=]()
+        {
+            on_downloadResume(item);
+        });
+        connect(cancel, &DPushButton::clicked, this, [=]()
+        {
+            on_downloadCancel(item);
+        });
+
+        DFloatingMessage *message = new DFloatingMessage(DFloatingMessage::TransientType);
+        message->setIcon(QIcon::fromTheme("dialog-information").pixmap(64, 64));
+        message->setMessage(QString(tr("%1Start downloading %2")).arg("    ").arg(fileName));
+        DMessageManager::instance()->sendMessage(this, message);
+
+        item->accept();
+
+        /* 重置 DownloadProgressBar 状态 */
+        isCanceled = false;
+        resume->hide();
+        pause->show();
+        this->message->show();  // 上一次下载完成后隐藏了进度条,这里要重新显示
     }
-    item->setPath(filePath);
-    filePath = QFileInfo(item->path()).absoluteFilePath();
-
-    connect(item, &QWebEngineDownloadItem::downloadProgress, this, &MainWindow::on_downloadProgress);
-    connect(item, &QWebEngineDownloadItem::finished, this, [=]()
+    else
     {
-        on_downloadFinish(filePath);
-    });
-
-    DFloatingMessage *message = new DFloatingMessage(DFloatingMessage::TransientType);
-    message->setIcon(QIcon::fromTheme("dialog-information").pixmap(64, 64));
-    message->setMessage(QString(tr("%1Start downloading %2")).arg("    ").arg(fileName));
-    DMessageManager::instance()->sendMessage(this, message);
-
-    item->accept();
+        DMessageManager::instance()->sendMessage(this, QIcon::fromTheme("dialog-cancel").pixmap(64, 64), QString(tr("%1Wait for previous download to complete!")).arg("    "));
+    }
 }
 
 void MainWindow::on_downloadProgress(qint64 bytesReceived, qint64 bytesTotal)
 {
     int value = int(double(bytesReceived) / double(bytesTotal) * 100.0);
-
-    bar->setFixedSize(250, 8);
     bar->setValue(value);
-    message->setIcon(QIcon::fromTheme("deepin-download").pixmap(64, 64));
+
     message->setMessage("    " + QString::number(value) + "%");
-    message->setWidget(bar);
+
     DMessageManager::instance()->sendMessage(this, message);
 }
 
 void MainWindow::on_downloadFinish(QString filePath)
 {
+    mutex.unlock(); // 解锁互斥量,允许下载新文件
+
     message->hide();
 
-    DPushButton *button = new DPushButton(tr("Open"));
-
-    DFloatingMessage *message = new DFloatingMessage(DFloatingMessage::ResidentType);
-    message->setIcon(QIcon::fromTheme("dialog-ok").pixmap(64, 64));
-    message->setMessage(QString("    %1 %2 %3").arg(QFileInfo(filePath).fileName()).arg(tr("download finished.")).arg(tr("Show in file manager?")));
-    message->setWidget(button);
-    DMessageManager::instance()->sendMessage(this, message);
-
-    connect(button, &DPushButton::clicked, this, [=]()
+    if(!isCanceled) // 下载完成显示提示信息
     {
-        process->start("dde-file-manager --show-item " + filePath);
-        message->hide();
-    });
+        DPushButton *button = new DPushButton(tr("Open"));
+
+        DFloatingMessage *message = new DFloatingMessage(DFloatingMessage::ResidentType);
+        message->setIcon(QIcon::fromTheme("dialog-ok").pixmap(64, 64));
+        message->setMessage(QString("    %1 %2 %3").arg(QFileInfo(filePath).fileName()).arg(tr("download finished.")).arg(tr("Show in file manager?")));
+        message->setWidget(button);
+        DMessageManager::instance()->sendMessage(this, message);
+
+        connect(button, &DPushButton::clicked, this, [=]()
+        {
+            process->start("dde-file-manager --show-item " + filePath);
+            message->hide();
+        });
+    }
+}
+
+void MainWindow::on_downloadPause(QWebEngineDownloadItem *item)
+{
+    item->pause();
+
+    message->setIcon(QIcon::fromTheme("package-download-failed").pixmap(64, 64));
+    resume->show();
+    pause->hide();
+}
+
+void MainWindow::on_downloadResume(QWebEngineDownloadItem *item)
+{
+    item->resume();
+
+    message->setIcon(QIcon::fromTheme("deepin-download").pixmap(64, 64));
+    resume->hide();
+    pause->show();
+}
+
+void MainWindow::on_downloadCancel(QWebEngineDownloadItem *item)
+{
+    isCanceled = true;  // 取消下载
+    item->cancel();
+
+    mutex.unlock();
+
+    message->hide();
+    DMessageManager::instance()->sendMessage(this, QIcon::fromTheme("dialog-error").pixmap(64, 64), QString(tr("%1Download canceled!")).arg("    "));
 }
diff --git a/spark-webapp-runtime/mainwindow.h b/spark-webapp-runtime/mainwindow.h
index df74ee2..2f4c139 100644
--- a/spark-webapp-runtime/mainwindow.h
+++ b/spark-webapp-runtime/mainwindow.h
@@ -5,10 +5,13 @@
 #include <DAboutDialog>
 #include <DToolButton>
 #include <DProgressBar>
+#include <DPushButton>
 #include <DFloatingMessage>
 
 #include <QSystemTrayIcon>
+#include <QLayout>
 #include <QProcess>
+#include <QMutex>
 
 #include "widget.h"
 #include "globaldefine.h"
@@ -53,11 +56,19 @@ private:
     QAction *t_about;
     QAction *t_exit;
 
+    QWidget *downloadProgressBar;
     DProgressBar *bar;
+    DPushButton *pause;
+    DPushButton *resume;
+    DPushButton *cancel;
+    QHBoxLayout *progress;
     DFloatingMessage *message;
 
     QProcess *process;
 
+    QMutex mutex;       // 通过 Mutex 互斥量禁止同时下载多个文件(使用简单的 bool 变量应该也可以实现该功能?)
+    bool isCanceled;    // 判断是否为取消下载
+
     bool mtray, mFixSize;
     int m_width, m_height;
 
@@ -76,6 +87,9 @@ private slots:
     void on_downloadStart(QWebEngineDownloadItem *item);
     void on_downloadProgress(qint64 bytesReceived, qint64 bytesTotal);
     void on_downloadFinish(QString filePath);
+    void on_downloadPause(QWebEngineDownloadItem *item);
+    void on_downloadResume(QWebEngineDownloadItem *item);
+    void on_downloadCancel(QWebEngineDownloadItem *item);
 
 signals:
     void sigQuit();
diff --git a/spark-webapp-runtime/translations/spark-webapp-runtime_zh_CN.qm b/spark-webapp-runtime/translations/spark-webapp-runtime_zh_CN.qm
index dca0c2b7b8efbcc7dd7cfdaef9e27dda2587f5ce..7da2e3201232f647d564e82bf5a36f3201e5be55 100644
GIT binary patch
delta 560
zcmeAcyCN|`q~3sm<va@m1LIZ(*0g;L3`_+K96#<cFtBPc$ZqgsU|{>s;6CjLP(Fnr
ztY<1vemcX_rB{LcJB)dY^%xk~KQeAzlnPWA&%(I-9|HrY0gH=F9s>gl2TRP-jSN7*
zGQ)EZP<;=};nhHSj&N3Q)p7;~W)arJ-J%Q(^^97qJ!?#X2JdIxdB`7VaX0I(KA;2G
z7P6k}>jP>pX1(qi2bAY#{dngc0|S=|+Z6XlKyzz3IQky~4Z6&6GHD->p1~=00q8IW
zN6wy-%Ru!ncxEx)0;+$&t0F86<lFMexq}?+#;5o?5UB15pE1vWhI$5OA3nQ%AQzwE
zTfBW8P{CTh3m?w`eKMEtqu4v3i}&*DOYi|5_KQEDKN)CXYbFB&Hy1O|2tEc?217sY
z{@UPcxgGx*Ie<b8Y(OlcYUq+*o|luKn4*xJn3tTIlbWK)4wT^XP0Y*-&&*57FJ}Z9
zz{4<EgRwD44rEUE_iE4hRzEI320ty3nSQ^67Do3Z2_TuPscIOWm|3EbmS3b$P?TDh
znO|D005l6?Q%Sx;a(-?>PHIW2;^e7}<su+g!QI5>40g!m^NgaCd6*swv!pcz#K2`)
g0}@M%C!b>!6RCS%_ZBY97L;0Cnwz@$CX*2d08FBk8~^|S

delta 300
zcmca2(JeMXq@II;<va@m1H)4W*0g;L42%mHIDXt?U|?Zqklo<Nz`%Nq!F}2hp!{Bj
zrAw~@<#`zM7V9xEuw7u>x+oPWZ^y#8`yT@X2S1C8OdbOR({q-?tATuWGgfcaa-jOp
ztckltf%=<ScOLQwnw!PCs}E>CYXj@KzCH$qdgdV3>z;8yh1RSe@4RDR;ACc-;{FJz
z!G?pQ{~^%8O&lka_5tZ~PO%F>2LM&{lw1a?Kh86Y@fMJ`pI1d#7|74%lXC|-OqI`=
z=RZ)rHlN)-po5rK^DW-K4k+Hkcj4nXphIi;K8n2qI&coZz62kG00YZS{($~upg}2_
dK;q@(ZpQY>{fw-WYnkFEvoJs0Y{nwT0RS>DPVxW%

diff --git a/spark-webapp-runtime/translations/spark-webapp-runtime_zh_CN.ts b/spark-webapp-runtime/translations/spark-webapp-runtime_zh_CN.ts
index a485dc4..031f6ab 100644
--- a/spark-webapp-runtime/translations/spark-webapp-runtime_zh_CN.ts
+++ b/spark-webapp-runtime/translations/spark-webapp-runtime_zh_CN.ts
@@ -4,70 +4,95 @@
 <context>
     <name>MainWindow</name>
     <message>
-        <location filename="../mainwindow.cpp" line="36"/>
+        <location filename="../mainwindow.cpp" line="34"/>
         <source>Full Screen</source>
         <translation>全屏显示</translation>
     </message>
     <message>
-        <location filename="../mainwindow.cpp" line="37"/>
+        <location filename="../mainwindow.cpp" line="35"/>
         <source>Fix Size</source>
         <translation>固定大小</translation>
     </message>
     <message>
-        <location filename="../mainwindow.cpp" line="38"/>
+        <location filename="../mainwindow.cpp" line="36"/>
         <source>Hide Buttons</source>
         <translation>隐藏按钮</translation>
     </message>
     <message>
-        <location filename="../mainwindow.cpp" line="40"/>
+        <location filename="../mainwindow.cpp" line="38"/>
         <source>Show MainWindow</source>
         <translation>显示主界面</translation>
     </message>
     <message>
-        <location filename="../mainwindow.cpp" line="41"/>
+        <location filename="../mainwindow.cpp" line="39"/>
         <source>About</source>
         <translation>关于</translation>
     </message>
     <message>
-        <location filename="../mainwindow.cpp" line="42"/>
+        <location filename="../mainwindow.cpp" line="40"/>
         <source>Exit</source>
         <translation>退出</translation>
     </message>
     <message>
-        <location filename="../mainwindow.cpp" line="191"/>
+        <location filename="../mainwindow.cpp" line="43"/>
+        <source>Pause</source>
+        <translation>暂停</translation>
+    </message>
+    <message>
+        <location filename="../mainwindow.cpp" line="44"/>
+        <source>Resume</source>
+        <translation>继续</translation>
+    </message>
+    <message>
+        <location filename="../mainwindow.cpp" line="45"/>
+        <source>Cancel</source>
+        <translation>取消</translation>
+    </message>
+    <message>
+        <location filename="../mainwindow.cpp" line="206"/>
         <source>%1Fullscreen Mode</source>
         <translation>%1全屏模式</translation>
     </message>
     <message>
-        <location filename="../mainwindow.cpp" line="201"/>
+        <location filename="../mainwindow.cpp" line="216"/>
         <source>%1Windowed Mode</source>
         <translation>%1窗口模式</translation>
     </message>
     <message>
-        <location filename="../mainwindow.cpp" line="243"/>
+        <location filename="../mainwindow.cpp" line="258"/>
         <source>Save As</source>
         <translation>另存为</translation>
     </message>
     <message>
-        <location filename="../mainwindow.cpp" line="314"/>
+        <location filename="../mainwindow.cpp" line="344"/>
         <source>%1Start downloading %2</source>
         <translation>%1开始下载 %2</translation>
     </message>
     <message>
-        <location filename="../mainwindow.cpp" line="336"/>
+        <location filename="../mainwindow.cpp" line="357"/>
+        <source>%1Wait for previous download to complete!</source>
+        <translation>%1请等待上一个下载任务完成!</translation>
+    </message>
+    <message>
+        <location filename="../mainwindow.cpp" line="379"/>
         <source>Open</source>
         <translation>打开</translation>
     </message>
     <message>
-        <location filename="../mainwindow.cpp" line="340"/>
+        <location filename="../mainwindow.cpp" line="383"/>
         <source>download finished.</source>
         <translation>下载完成。</translation>
     </message>
     <message>
-        <location filename="../mainwindow.cpp" line="340"/>
+        <location filename="../mainwindow.cpp" line="383"/>
         <source>Show in file manager?</source>
         <translation>是否在文件管理器中显示?</translation>
     </message>
+    <message>
+        <location filename="../mainwindow.cpp" line="421"/>
+        <source>%1Download canceled!</source>
+        <translation>%1下载取消!</translation>
+    </message>
 </context>
 <context>
     <name>QObject</name>