Bläddra i källkod

Downloader status accuracy improvements and bug fixes

Ivan Arkhipov 5 år sedan
förälder
incheckning
51dabdbdcc
2 ändrade filer med 76 tillägg och 56 borttagningar
  1. 49 44
      src/Legacy/models/downloader.cpp
  2. 27 12
      src/Legacy/models/downloader.h

+ 49 - 44
src/Legacy/models/downloader.cpp

@@ -4,14 +4,10 @@
 #include <QDebug>
 #include <QTime>
 
-Downloader::Downloader(QObject *parent) :QObject(parent), busy(false)
+Downloader::Downloader(QObject *parent) :QObject(parent), busy_(false)
 {
+    qRegisterMetaType<Downloader::Status>();
     connect(&m_WebCtrl, SIGNAL(finished(QNetworkReply*)), this, SLOT(onDownloadFinished(QNetworkReply*)));
-    bytes_downloaded = 0;
-    bytes_total = 0;
-    download_speed = 0;
-    bytesReceivedBeforeSecond = 0;
-    timeElapsedBeforeSecond = 0;
 }
 
 Downloader::~Downloader() {
@@ -19,17 +15,17 @@ Downloader::~Downloader() {
 
 QUrl Downloader::getUrl()
 {
-    return url;
+    return url_;
 }
 
 void Downloader::setUrl(const QUrl &_url)
 {
-    url = _url;
+    url_ = _url;
 }
 
 void Downloader::waitForDownloaded()
 {
-    if (!busy)
+    if (!busy_)
         return;
 
     QEventLoop loop;
@@ -39,37 +35,45 @@ void Downloader::waitForDownloaded()
 
 bool Downloader::isStarted()
 {
-    return busy;
+    return busy_;
 }
 
 double Downloader::getPercent()
 {
-    return double(std::ceil(((double)bytes_downloaded/ bytes_total) * 100 * 10)) / 10.0;
+    return double(bytes_downloaded_) * 100.0 / double(bytes_total_);
 }
 
 quint64 Downloader::getBytesTotal()
 {
-    return bytes_total;
+    return bytes_total_;
 }
 
 quint64 Downloader::getBytesDownloaded()
 {
-    return bytes_downloaded;
+    return bytes_downloaded_;
 }
 
 quint64 Downloader::getElapsedTime()
 {
-    return (getBytesTotal() - getBytesDownloaded()) / qMax(quint64(1), getAverageSpeed());
+    quint64 delta_size = getBytesTotal() - getBytesDownloaded();
+    quint64 avg_speed = qMax(quint64(1), getAverageSpeed());
+
+    while (delta_size > 1024 && avg_speed > 1024) { // Making precision smaller to get smoother dynamics
+        delta_size /= 1024;
+        avg_speed /= 1024;
+    }
+
+    return delta_size / avg_speed;
 }
 
 quint64 Downloader::getCurrentSpeed()
 {
-    return download_speed;
+    return download_speed_;
 }
 
 quint64 Downloader::getAverageSpeed()
 {
-    return average_speed;
+    return average_speed_;
 }
 
 Downloader::Status Downloader::getDownloadStatus()
@@ -100,17 +104,19 @@ QString Downloader::getSizeFormatted(quint64 bytes)
     QString unit;
     if (size < 1024) {
         unit = "байт";
-    } else if (size < 1024*1024) {
+    } else if (size < 1024 * 1024) {
         size /= 1024;
-        unit = "kB";
-    } else {
+        unit = "кб";
+    } else if (size < 1024 * 1024 * 1024){
         size /= 1024*1024;
-        unit = "MB";
+        unit = "мб";
+    } else {
+        size /= 1024 * 1024 * 1024;
+        unit = "гб";
     }
     return QString::number(size, 'f', 1) + " " + unit;
 }
 
-
 QString Downloader::getElapsedTimeFormatted(quint64 elapsed_time_secs)
 {
     qint64 secs = elapsed_time_secs;
@@ -170,26 +176,26 @@ QString Downloader::getElapsedTimeFormatted(quint64 elapsed_time_secs)
 
     if (result == "")
         result = "совсем чуть-чуть";
+
     return result;
 }
 
 void Downloader::start()
 {
-    if (busy) {
-        qDebug() << "Cannot download " << url << ", downloader is busy!";
+    if (busy_) {
+        qDebug() << "Cannot download " << url_ << ", downloader is busy!";
         return;
     }
-    qDebug() << "Starting download " << url;
+    qDebug() << "Starting download " << url_;
 
-    downloadTime.restart();
-    bytes_downloaded = 0;
-    bytes_total = 0;
-    download_speed = 0;
-    bytesReceivedBeforeSecond = 0;
-    timeElapsedBeforeSecond = 0;
+    last_tick_time_.restart();
+    bytes_downloaded_ = 0;
+    bytes_total_ = 0;
+    download_speed_ = 0;
+    bytes_downloaded_before_tick_ = 0;
 
-    busy = true;
-    QNetworkRequest request(url);
+    busy_ = true;
+    QNetworkRequest request(url_);
     m_CurrentReply = m_WebCtrl.get(request);
     m_CurrentReply->setReadBufferSize(download_speed_limit);
     connect(m_CurrentReply, &QNetworkReply::readyRead, this, &Downloader::onReadyRead);
@@ -205,18 +211,17 @@ void Downloader::updateDownloadSpeedLimit(int bytes_per_sec)
 
 void Downloader::onDownloadProgressChanged(qint64 bytesReceived, qint64 bytesTotal)
 {
+    bytes_downloaded_ = bytesReceived;
+    bytes_total_ = bytesTotal;
 
-    bytes_downloaded = bytesReceived;
-    bytes_total = bytesTotal;
-
-    if (downloadTime.elapsed() - timeElapsedBeforeSecond >= 300) {
-        download_speed = (bytes_downloaded - bytesReceivedBeforeSecond) * 1000.0 / (downloadTime.elapsed() - timeElapsedBeforeSecond);
+    if (last_tick_time_.elapsed() >= 300) {
+        download_speed_ = (bytes_downloaded_ - bytes_downloaded_before_tick_) * 1000.0 / (last_tick_time_.elapsed());
 
-        average_speed = (average_speed * speed_update_ticks + download_speed) / (speed_update_ticks + 1);
-        ++speed_update_ticks;
+        average_speed_ = (average_speed_ * update_ticks_counter_ + download_speed_) / (update_ticks_counter_ + 1);
+        ++update_ticks_counter_;
 
-        timeElapsedBeforeSecond = downloadTime.elapsed();
-        bytesReceivedBeforeSecond = bytes_downloaded;
+        last_tick_time_.restart();
+        bytes_downloaded_before_tick_ = bytes_downloaded_;
         emit progressChanged(this, getDownloadStatus());
     }
 }
@@ -226,15 +231,15 @@ void Downloader::stop()
     if (m_CurrentReply) {
         m_CurrentReply->abort();
     }
-    busy = false;
+    busy_ = false;
 }
 
 void Downloader::onDownloadFinished(QNetworkReply*) {
     if (m_CurrentReply)
         m_CurrentReply->deleteLater();
 
-    download_speed = 0;
-    busy = false;
+    download_speed_ = 0;
+    busy_ = false;
 
     emit downloadFinished(this);
 }

+ 27 - 12
src/Legacy/models/downloader.h

@@ -28,11 +28,24 @@ public:
     friend Status operator+(const Status& a, const Status &b) {
         Status result;
         result.running = a.running || b.running;
-        result.percent = (a.percent + b.percent) / 2.0;
         result.total_bytes = a.total_bytes + b.total_bytes;
         result.downloaded_bytes = a.downloaded_bytes + b.downloaded_bytes;
+        result.percent = double(result.downloaded_bytes) * 100.0 / double(result.total_bytes);
         result.average_speed = a.average_speed + b.average_speed;
-        result.elapsed_time = qMax(a.elapsed_time, b.elapsed_time);
+        result.current_speed = a.current_speed + b.current_speed;
+
+
+        // Counting elapsed time
+        quint64 delta_size = result.total_bytes - result.downloaded_bytes;
+        quint64 avg_speed = qMax(quint64(1), result.average_speed);
+
+        while (delta_size > 1024 && avg_speed > 1024) { // Making precision smaller to get smoother dynamics
+            delta_size /= 1024;
+            avg_speed /= 1024;
+        }
+        result.elapsed_time = delta_size / avg_speed;
+
+
         return result;
     }
 
@@ -80,23 +93,25 @@ public:
     QByteArray* targetBytearray {nullptr};
 
 private:
-    QTime downloadTime;
-    quint64 download_speed; // bytes per second
-    quint64 average_speed;
-    quint64 speed_update_ticks;
+    QTime last_tick_time_;
+    quint64 download_speed_ = 0; // bytes per second
+    quint64 average_speed_ = 0;
+    quint64 update_ticks_counter_ = 0;
 
-    quint64 bytes_total;
-    quint64 bytes_downloaded;
+    quint64 bytes_total_ = 0;
+    quint64 bytes_downloaded_ = 0;
 
-    quint64 bytesReceivedBeforeSecond; // Нужны для подсчёта текущей скорости скачивания, а не
-    quint64 timeElapsedBeforeSecond;   // средней за всё время.
+    quint64 bytes_downloaded_before_tick_ = 0; // Нужны для подсчёта текущей скорости скачивания, а не
 
-    bool busy;
-    QUrl url;
+    bool busy_;
+    QUrl url_;
     QNetworkReply* m_CurrentReply {nullptr};
     QNetworkAccessManager m_WebCtrl;
 
     unsigned download_speed_limit {0};
 };
 
+
+Q_DECLARE_METATYPE(Downloader::Status)
+
 #endif // INCLUDEILEDOWNLOADER_H