From bf35b0ca5bd4ba33e28d015c36f91d3cd511bda4 Mon Sep 17 00:00:00 2001
From: Ming Rui Zhang <mingrui.zhang@savoirfairelinux.com>
Date: Wed, 25 Sep 2019 17:50:58 -0400
Subject: [PATCH] downloadmanager: add cancel ability

- change download speed display to download progress
- add cancel ability to make user enable to abort update or
  download

Change-Id: Ibb725897a1cf0c636186275541f25322819d5517
---
 downloadmanager.cpp      |  41 ++++++------
 downloadmanager.h        |   7 +-
 stylesheet.css           |  21 +++++-
 updatedownloaddialog.cpp |  35 ++++++++--
 updatedownloaddialog.h   |  16 +++--
 updatedownloaddialog.ui  | 136 +++++++++++++++++++++++++++------------
 utils.cpp                |   2 +-
 7 files changed, 176 insertions(+), 82 deletions(-)

diff --git a/downloadmanager.cpp b/downloadmanager.cpp
index 2d197b2..313b4e2 100644
--- a/downloadmanager.cpp
+++ b/downloadmanager.cpp
@@ -53,8 +53,6 @@ void DownloadManager::downloadFile(const QUrl& fileUrl,
         return;
     }
 
-    downloadTime_.start();
-
     QNetworkRequest request(fileUrl);
     currentDownload_ = manager_.get(request);
 
@@ -67,6 +65,10 @@ void DownloadManager::downloadFile(const QUrl& fileUrl,
 #if QT_CONFIG(ssl)
     connect(currentDownload_, SIGNAL(sslErrors(const QList<QSslError>&)), this, SLOT(slotSslErrors(QList<QSslError>)));
 #endif
+    connect(&progressBar_, &UpdateDownloadDialog::isCanceled,
+        [this] {
+            cancelDownload();
+        });
 
     if (withUI_) {
         progressBar_.exec();
@@ -77,6 +79,11 @@ void DownloadManager::slotDownloadFinished()
 {
     statusCode_ = currentDownload_->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
 
+    if (httpRequestAborted_) {
+        // request aborted
+        statusCode_ = 0;
+    }
+
     currentDownload_->deleteLater();
     currentDownload_ = nullptr;
 
@@ -88,7 +95,7 @@ void DownloadManager::slotDownloadFinished()
         progressBar_.setMaximum(0);
         progressBar_.setValue(0);
         progressBar_.update("0");
-        progressBar_.close();
+        progressBar_.done(0);
     }
 
     if (doneCb_)
@@ -109,26 +116,7 @@ void DownloadManager::slotDownloadProgress(qint64 bytesReceived, qint64 bytesTot
     progressBar_.setMaximum(bytesTotal);
     progressBar_.setValue(bytesReceived);
 
-    int presentTime = downloadTime_.elapsed();
-    // calculate the download speed
-    double speed = (bytesReceived - previousDownloadBytes_) * 1000.0 / (presentTime - previousTime_);
-    if (speed < 0)
-        speed = 0;
-    previousTime_ = presentTime;
-    previousDownloadBytes_ = bytesReceived;
-
-    QString unit;
-    if (speed < 1024) {
-        unit = "B/s";
-    } else if (speed < 1024 * 1024) {
-        speed /= 1024;
-        unit = "kB/s";
-    } else {
-        speed /= 1024 * 1024;
-        unit = "MB/s";
-    }
-
-    progressBar_.update(QString::number(speed) + " " + unit);
+    progressBar_.update(Utils::humanFileSize(bytesReceived) + " / " + Utils::humanFileSize(bytesTotal));
 }
 
 void DownloadManager::slotHttpReadyRead()
@@ -156,3 +144,10 @@ int DownloadManager::getDownloadStatus()
 {
     return statusCode_;
 }
+
+void DownloadManager::cancelDownload()
+{
+    httpRequestAborted_ = true;
+    if(currentDownload_)
+        currentDownload_->abort();
+}
diff --git a/downloadmanager.h b/downloadmanager.h
index 081fbde..4fcde34 100644
--- a/downloadmanager.h
+++ b/downloadmanager.h
@@ -40,6 +40,7 @@ public:
                       bool withUI,
                       std::function<void(int)> doneCb = {});
     int getDownloadStatus();
+    void cancelDownload();
 
 public slots:
     void slotSslErrors(const QList<QSslError>& sslErrors);
@@ -52,13 +53,11 @@ private:
 
     QNetworkAccessManager manager_;
     QNetworkReply* currentDownload_;
-    updateDownloadDialog progressBar_;
+    UpdateDownloadDialog progressBar_;
     std::unique_ptr<QFile> file_;
-    QTime downloadTime_;
-    int previousTime_ = 0;
-    qint64 previousDownloadBytes_ = 0;
     int statusCode_;
     bool withUI_;
+    bool httpRequestAborted_ { false };
 
     std::function<void(int)> doneCb_;
 
diff --git a/stylesheet.css b/stylesheet.css
index 220b116..ccd830f 100644
--- a/stylesheet.css
+++ b/stylesheet.css
@@ -216,6 +216,25 @@ QPushButton#sipInputPanelButton:checked {
     border: solid 1px;
 }
 
+QPushButton#updateCancelButton {
+    padding: 4px;
+    background: #369;
+    color: white;
+    font-size: 12px;
+    border: 0;
+    border-radius: 3px;
+    outline: 0px;
+    width: 50px;
+}
+
+QPushButton#updateCancelButton:hover {
+    background: #47a;
+}
+
+QPushButton#updateCancelButton:pressed {
+    background: #58b;
+}
+
 QMessageBox QPushButton {
     padding: 4px;
     background: #369;
@@ -272,7 +291,7 @@ QScrollBar::handle:vertical{
 }
 
 QWidget#messagingPage, QWidget#contactRequestPage,
-QDialog#DeleteAccountDialog, QDialog#updateDownloadDialog,
+QDialog#DeleteAccountDialog, QDialog#UpdateDownloadDialog,
 QDialog#UpdateConfirmDialog, QDialog#AccountMigrationDialog {
     background: rgb(255, 255, 255);
 }
diff --git a/updatedownloaddialog.cpp b/updatedownloaddialog.cpp
index a39869e..6e80708 100644
--- a/updatedownloaddialog.cpp
+++ b/updatedownloaddialog.cpp
@@ -19,34 +19,55 @@
 #include "updatedownloaddialog.h"
 #include "ui_updatedownloaddialog.h"
 
-updateDownloadDialog::updateDownloadDialog(QWidget* parent)
+#include <QCloseEvent>
+#include <QMessageBox>
+
+UpdateDownloadDialog::UpdateDownloadDialog(QWidget* parent)
     : QDialog(parent)
-    , ui(new Ui::updateDownloadDialog)
+    , ui(new Ui::UpdateDownloadDialog)
 {
     ui->setupUi(this);
     ui->progressBar->setValue(0);
     ui->progressBar->setVisible(true);
     setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint);
+
+    connect(ui->updateCancelButton, &QAbstractButton::clicked,
+        [this] {
+            emit isCanceled();
+        });
 }
 
-void updateDownloadDialog::setValue(double var)
+void UpdateDownloadDialog::setValue(double var)
 {
     value_ = var;
 }
 
-void updateDownloadDialog::setMaximum(double var)
+void UpdateDownloadDialog::setMaximum(double var)
 {
     maximum_ = var;
 }
 
-updateDownloadDialog::~updateDownloadDialog()
+UpdateDownloadDialog::~UpdateDownloadDialog()
 {
     delete ui;
 }
 
-void updateDownloadDialog::update(QString displayText)
+void UpdateDownloadDialog::update(QString displayText)
 {
     int percent = static_cast<int>((1 - ((maximum_ - value_) / maximum_)) * 100);
-    ui->Statusedit->setText("Speed: " + displayText);
+    ui->Statusedit->setText("Progress: " + displayText);
     ui->progressBar->setValue(percent);
 }
+
+void UpdateDownloadDialog::closeEvent(QCloseEvent *event)
+{
+    QMessageBox::StandardButton resBtn = QMessageBox::question(this, "Update",
+        tr("Quit Update?\n"),
+        QMessageBox::No | QMessageBox::Yes,
+        QMessageBox::Yes);
+    if (resBtn == QMessageBox::Yes) {
+        emit isCanceled();
+    } else {
+        event->ignore();
+    }
+}
diff --git a/updatedownloaddialog.h b/updatedownloaddialog.h
index d97226c..a5cc9f0 100644
--- a/updatedownloaddialog.h
+++ b/updatedownloaddialog.h
@@ -21,21 +21,27 @@
 #include <QDialog>
 
 namespace Ui {
-class updateDownloadDialog;
+class UpdateDownloadDialog;
 }
 
-class updateDownloadDialog : public QDialog {
+class UpdateDownloadDialog : public QDialog {
     Q_OBJECT
 
 public:
-    updateDownloadDialog(QWidget* parent = nullptr);
-    ~updateDownloadDialog();
+    UpdateDownloadDialog(QWidget* parent = nullptr);
+    ~UpdateDownloadDialog();
     void setValue(double var);
     void setMaximum(double var);
     void update(QString displayText);
 
+signals:
+    void isCanceled();
+
 private:
-    Ui::updateDownloadDialog* ui;
+    Ui::UpdateDownloadDialog* ui;
     double value_ = 0;
     double maximum_ = -1;
+
+protected:
+    void closeEvent(QCloseEvent *event);
 };
diff --git a/updatedownloaddialog.ui b/updatedownloaddialog.ui
index 4a6ebba..bd2d99a 100644
--- a/updatedownloaddialog.ui
+++ b/updatedownloaddialog.ui
@@ -1,55 +1,54 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <ui version="4.0">
- <class>updateDownloadDialog</class>
- <widget class="QDialog" name="updateDownloadDialog">
+ <class>UpdateDownloadDialog</class>
+ <widget class="QDialog" name="UpdateDownloadDialog">
   <property name="geometry">
    <rect>
     <x>0</x>
     <y>0</y>
-    <width>309</width>
-    <height>121</height>
+    <width>300</width>
+    <height>113</height>
    </rect>
   </property>
+  <property name="sizePolicy">
+   <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
+    <horstretch>0</horstretch>
+    <verstretch>0</verstretch>
+   </sizepolicy>
+  </property>
+  <property name="minimumSize">
+   <size>
+    <width>0</width>
+    <height>0</height>
+   </size>
+  </property>
+  <property name="maximumSize">
+   <size>
+    <width>16777215</width>
+    <height>16777215</height>
+   </size>
+  </property>
   <property name="windowTitle">
-   <string>Update Download</string>
+   <string>Update</string>
   </property>
-  <layout class="QHBoxLayout" name="horizontalLayout">
+  <layout class="QVBoxLayout" name="verticalLayout_3">
+   <property name="spacing">
+    <number>7</number>
+   </property>
+   <property name="leftMargin">
+    <number>11</number>
+   </property>
+   <property name="topMargin">
+    <number>11</number>
+   </property>
+   <property name="rightMargin">
+    <number>11</number>
+   </property>
+   <property name="bottomMargin">
+    <number>11</number>
+   </property>
    <item>
     <layout class="QVBoxLayout" name="verticalLayout_2">
-     <item>
-      <widget class="QLabel" name="label">
-       <property name="sizePolicy">
-        <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
-         <horstretch>0</horstretch>
-         <verstretch>0</verstretch>
-        </sizepolicy>
-       </property>
-       <property name="font">
-        <font>
-         <pointsize>9</pointsize>
-        </font>
-       </property>
-       <property name="text">
-        <string>Update Download Status</string>
-       </property>
-      </widget>
-     </item>
-     <item>
-      <spacer name="verticalSpacer">
-       <property name="orientation">
-        <enum>Qt::Vertical</enum>
-       </property>
-       <property name="sizeType">
-        <enum>QSizePolicy::Preferred</enum>
-       </property>
-       <property name="sizeHint" stdset="0">
-        <size>
-         <width>20</width>
-         <height>20</height>
-        </size>
-       </property>
-      </spacer>
-     </item>
      <item>
       <layout class="QVBoxLayout" name="verticalLayout">
        <item>
@@ -66,7 +65,7 @@
           </font>
          </property>
          <property name="text">
-          <string>Speed: </string>
+          <string>Download Progress: </string>
          </property>
         </widget>
        </item>
@@ -85,6 +84,61 @@
        </item>
       </layout>
      </item>
+     <item>
+      <spacer name="verticalSpacer_2">
+       <property name="orientation">
+        <enum>Qt::Vertical</enum>
+       </property>
+       <property name="sizeType">
+        <enum>QSizePolicy::MinimumExpanding</enum>
+       </property>
+       <property name="sizeHint" stdset="0">
+        <size>
+         <width>20</width>
+         <height>10</height>
+        </size>
+       </property>
+      </spacer>
+     </item>
+     <item>
+      <layout class="QHBoxLayout" name="horizontalLayout">
+       <property name="spacing">
+        <number>7</number>
+       </property>
+       <item>
+        <spacer name="horizontalSpacer">
+         <property name="orientation">
+          <enum>Qt::Horizontal</enum>
+         </property>
+         <property name="sizeHint" stdset="0">
+          <size>
+           <width>40</width>
+           <height>20</height>
+          </size>
+         </property>
+        </spacer>
+       </item>
+       <item>
+        <widget class="QPushButton" name="updateCancelButton">
+         <property name="minimumSize">
+          <size>
+           <width>90</width>
+           <height>30</height>
+          </size>
+         </property>
+         <property name="maximumSize">
+          <size>
+           <width>15</width>
+           <height>30</height>
+          </size>
+         </property>
+         <property name="text">
+          <string>Cancel</string>
+         </property>
+        </widget>
+       </item>
+      </layout>
+     </item>
     </layout>
    </item>
   </layout>
diff --git a/utils.cpp b/utils.cpp
index 16a241b..bbe705c 100644
--- a/utils.cpp
+++ b/utils.cpp
@@ -326,7 +326,7 @@ Utils::checkForUpdates(bool withUI, QWidget* parent)
     Utils::cleanUpdateFiles();
     QString downloadpath = WinGetEnv("TEMP");
     DownloadManager::instance().downloadFile(
-        QUrl::fromEncoded("https://dl.jami.net/windows/version"),
+        QUrl::fromEncoded("https://dl.jami.net/windows/jami-x64.msi"),
         downloadpath,
         withUI,
         [parent, withUI, downloadpath](int status) {
-- 
GitLab