downloader.cpp 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254
  1. #include "downloader.h"
  2. #include <QEventLoop>
  3. #include <QApplication>
  4. #include <QDebug>
  5. #include <QTime>
  6. Downloader::Downloader(QObject *parent) : QObject(parent), busy_(false), m_WebCtrl(this)
  7. {
  8. qRegisterMetaType<Downloader::Status>();
  9. connect(&m_WebCtrl, SIGNAL(finished(QNetworkReply*)), this, SLOT(onDownloadFinished(QNetworkReply*)));
  10. }
  11. Downloader::~Downloader() {
  12. }
  13. QUrl Downloader::getUrl() const
  14. {
  15. return url_;
  16. }
  17. void Downloader::setUrl(const QUrl &_url)
  18. {
  19. url_ = _url;
  20. }
  21. void Downloader::waitForDownloaded() const
  22. {
  23. if (!busy_)
  24. return;
  25. QEventLoop loop;
  26. connect(this, &Downloader::downloadFinished, &loop, &QEventLoop::quit);
  27. loop.exec();
  28. }
  29. bool Downloader::isStarted() const
  30. {
  31. return busy_;
  32. }
  33. double Downloader::getPercent() const
  34. {
  35. return double(bytes_downloaded_) * 100.0 / double(bytes_total_);
  36. }
  37. quint64 Downloader::getBytesTotal() const
  38. {
  39. return bytes_total_;
  40. }
  41. quint64 Downloader::getBytesDownloaded() const
  42. {
  43. return bytes_downloaded_;
  44. }
  45. quint64 Downloader::getElapsedTime() const
  46. {
  47. quint64 delta_size = getBytesTotal() - getBytesDownloaded();
  48. quint64 avg_speed = qMax(quint64(1), getAverageSpeed());
  49. while (delta_size > 1024 && avg_speed > 1024) { // Making precision smaller to get smoother dynamics
  50. delta_size /= 1024;
  51. avg_speed /= 1024;
  52. }
  53. return delta_size / avg_speed;
  54. }
  55. quint64 Downloader::getCurrentSpeed() const
  56. {
  57. return download_speed_;
  58. }
  59. quint64 Downloader::getAverageSpeed() const
  60. {
  61. return average_speed_;
  62. }
  63. Downloader::Status Downloader::getDownloadStatus() const
  64. {
  65. return {isStarted(), getPercent(), getBytesTotal(), getBytesDownloaded(), getCurrentSpeed(), getAverageSpeed(), getElapsedTime()};
  66. }
  67. QString Downloader::getSpeedFormatted(quint64 speed_bytes_per_sec)
  68. {
  69. float speed = speed_bytes_per_sec;
  70. QString unit;
  71. if (speed < 1024) {
  72. unit = "bytes/sec";
  73. } else if (speed < 1024*1024) {
  74. speed /= 1024;
  75. unit = "kB/s";
  76. } else {
  77. speed /= 1024*1024;
  78. unit = "MB/s";
  79. }
  80. return QString::number(speed, 'f', 1) + " " + unit;
  81. }
  82. QString Downloader::getSizeFormatted(quint64 bytes)
  83. {
  84. float size = bytes;
  85. QString unit;
  86. if (size < 1024) {
  87. unit = "байт";
  88. } else if (size < 1024 * 1024) {
  89. size /= 1024;
  90. unit = "кб";
  91. } else if (size < 1024 * 1024 * 1024){
  92. size /= 1024*1024;
  93. unit = "мб";
  94. } else {
  95. size /= 1024 * 1024 * 1024;
  96. unit = "гб";
  97. }
  98. return QString::number(size, 'f', 1) + " " + unit;
  99. }
  100. QString Downloader::getElapsedTimeFormatted(quint64 elapsed_time_secs)
  101. {
  102. qint64 secs = elapsed_time_secs;
  103. qint64 mins = 0;
  104. qint64 hours = 0;
  105. qint64 days = 0;
  106. if (secs > 60) {
  107. mins = secs / 60;
  108. secs %= 60;
  109. }
  110. if (mins > 60) {
  111. hours = mins / 60;
  112. mins %= 60;
  113. }
  114. if (hours > 24) {
  115. days = hours / 24;
  116. hours %= 24;
  117. }
  118. if (days > 0)
  119. return " очень много (низкая скорость)";
  120. QString result = "";
  121. if (hours > 0) {
  122. result += QString::number(hours);
  123. if (hours % 10 == 1 && hours / 10 != 1)
  124. result += " час ";
  125. else if (hours % 10 > 1 && hours % 10 < 5 && hours / 10 != 1)
  126. result += " часа ";
  127. else
  128. result += " часов ";
  129. }
  130. if (mins > 0) {
  131. result += QString::number(mins);
  132. if (mins % 10 == 1 && mins / 10 != 1)
  133. result += " минута ";
  134. else if (mins % 10 > 1 && mins % 10 < 5 && mins / 10 != 1)
  135. result += " минуты ";
  136. else
  137. result += " минут ";
  138. }
  139. if (secs > 0 && hours == 0) {
  140. result += QString::number(secs);
  141. if (secs % 10 == 1 && secs / 10 != 1)
  142. result += " секунда ";
  143. else if (secs % 10 > 1 && secs % 10 < 5 && secs / 10 != 1)
  144. result += " секунды ";
  145. else
  146. result += " секунд ";
  147. }
  148. if (result == "")
  149. result = "совсем чуть-чуть";
  150. return result;
  151. }
  152. void Downloader::start()
  153. {
  154. if (busy_) {
  155. qDebug() << "Cannot download " << url_ << ", downloader is busy!";
  156. return;
  157. }
  158. qDebug() << "Starting download " << url_;
  159. last_tick_time_.restart();
  160. bytes_downloaded_ = 0;
  161. bytes_total_ = 0;
  162. download_speed_ = 0;
  163. bytes_downloaded_before_tick_ = 0;
  164. busy_ = true;
  165. QNetworkRequest request(url_);
  166. m_CurrentReply = m_WebCtrl.get(request);
  167. m_CurrentReply->setReadBufferSize(download_speed_limit);
  168. connect(m_CurrentReply, &QNetworkReply::readyRead, this, &Downloader::onReadyRead);
  169. connect(m_CurrentReply, &QNetworkReply::downloadProgress, this, &Downloader::onDownloadProgressChanged);
  170. }
  171. void Downloader::updateDownloadSpeedLimit(int bytes_per_sec)
  172. {
  173. download_speed_limit = bytes_per_sec;
  174. if (m_CurrentReply)
  175. m_CurrentReply->setReadBufferSize(bytes_per_sec);
  176. }
  177. void Downloader::onDownloadProgressChanged(qint64 bytesReceived, qint64 bytesTotal)
  178. {
  179. bytes_downloaded_ = bytesReceived;
  180. bytes_total_ = bytesTotal;
  181. if (last_tick_time_.elapsed() >= 300) {
  182. download_speed_ = (bytes_downloaded_ - bytes_downloaded_before_tick_) * 1000.0 / (last_tick_time_.elapsed());
  183. average_speed_ = (average_speed_ * update_ticks_counter_ + download_speed_) / (update_ticks_counter_ + 1);
  184. ++update_ticks_counter_;
  185. last_tick_time_.restart();
  186. bytes_downloaded_before_tick_ = bytes_downloaded_;
  187. emit progressChanged(this, getDownloadStatus());
  188. }
  189. }
  190. void Downloader::stop()
  191. {
  192. if (m_CurrentReply) {
  193. m_CurrentReply->abort();
  194. }
  195. busy_ = false;
  196. }
  197. void Downloader::onDownloadFinished(QNetworkReply*) {
  198. if (m_CurrentReply)
  199. m_CurrentReply->deleteLater();
  200. download_speed_ = 0;
  201. busy_ = false;
  202. emit downloadFinished(this);
  203. }
  204. void Downloader::onReadyRead()
  205. {
  206. QByteArray readdata = m_CurrentReply->readAll();
  207. if (targetFile && targetFile->isWritable())
  208. targetFile->write(readdata);
  209. if (targetBytearray)
  210. targetBytearray->append(readdata);
  211. }