123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254 |
- #include "downloader.h"
- #include <QEventLoop>
- #include <QApplication>
- #include <QDebug>
- #include <QTime>
- Downloader::Downloader(QObject *parent) : QObject(parent), busy_(false), m_WebCtrl(this)
- {
- qRegisterMetaType<Downloader::Status>();
- connect(&m_WebCtrl, SIGNAL(finished(QNetworkReply*)), this, SLOT(onDownloadFinished(QNetworkReply*)));
- }
- Downloader::~Downloader() {
- }
- QUrl Downloader::getUrl() const
- {
- return url_;
- }
- void Downloader::setUrl(const QUrl &_url)
- {
- url_ = _url;
- }
- void Downloader::waitForDownloaded() const
- {
- if (!busy_)
- return;
- QEventLoop loop;
- connect(this, &Downloader::downloadFinished, &loop, &QEventLoop::quit);
- loop.exec();
- }
- bool Downloader::isStarted() const
- {
- return busy_;
- }
- double Downloader::getPercent() const
- {
- return bytes_total_ > 0.01 ? double(bytes_downloaded_) * 100.0 / double(bytes_total_) : 0;
- }
- quint64 Downloader::getBytesTotal() const
- {
- return bytes_total_;
- }
- quint64 Downloader::getBytesDownloaded() const
- {
- return bytes_downloaded_;
- }
- quint64 Downloader::getElapsedTime() const
- {
- 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() const
- {
- return download_speed_;
- }
- quint64 Downloader::getAverageSpeed() const
- {
- return average_speed_;
- }
- Downloader::Status Downloader::getDownloadStatus() const
- {
- return {isStarted(), getPercent(), getBytesTotal(), getBytesDownloaded(), getCurrentSpeed(), getAverageSpeed(), getElapsedTime()};
- }
- QString Downloader::getSpeedFormatted(quint64 speed_bytes_per_sec)
- {
- float speed = speed_bytes_per_sec;
- QString unit;
- if (speed < 1024) {
- unit = "bytes/sec";
- } else if (speed < 1024*1024) {
- speed /= 1024;
- unit = "kB/s";
- } else {
- speed /= 1024*1024;
- unit = "MB/s";
- }
- return QString::number(speed, 'f', 1) + " " + unit;
- }
- QString Downloader::getSizeFormatted(quint64 bytes)
- {
- float size = bytes;
- QString unit;
- if (size < 1024) {
- unit = "байт";
- } else if (size < 1024 * 1024) {
- size /= 1024;
- unit = "кб";
- } else if (size < 1024 * 1024 * 1024){
- size /= 1024*1024;
- 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;
- qint64 mins = 0;
- qint64 hours = 0;
- qint64 days = 0;
- if (secs > 60) {
- mins = secs / 60;
- secs %= 60;
- }
- if (mins > 60) {
- hours = mins / 60;
- mins %= 60;
- }
- if (hours > 24) {
- days = hours / 24;
- hours %= 24;
- }
- if (days > 0)
- return " очень много (низкая скорость)";
- QString result = "";
- if (hours > 0) {
- result += QString::number(hours);
- if (hours % 10 == 1 && hours / 10 != 1)
- result += " час ";
- else if (hours % 10 > 1 && hours % 10 < 5 && hours / 10 != 1)
- result += " часа ";
- else
- result += " часов ";
- }
- if (mins > 0) {
- result += QString::number(mins);
- if (mins % 10 == 1 && mins / 10 != 1)
- result += " минута ";
- else if (mins % 10 > 1 && mins % 10 < 5 && mins / 10 != 1)
- result += " минуты ";
- else
- result += " минут ";
- }
- if (secs > 0 && hours == 0) {
- result += QString::number(secs);
- if (secs % 10 == 1 && secs / 10 != 1)
- result += " секунда ";
- else if (secs % 10 > 1 && secs % 10 < 5 && secs / 10 != 1)
- result += " секунды ";
- else
- result += " секунд ";
- }
- if (result == "")
- result = "совсем чуть-чуть";
- return result;
- }
- void Downloader::start()
- {
- if (busy_) {
- qDebug() << "Cannot download " << url_ << ", downloader is busy!";
- return;
- }
- qDebug() << "Starting download " << url_;
- last_tick_time_.restart();
- bytes_downloaded_ = 0;
- bytes_total_ = 0;
- download_speed_ = 0;
- bytes_downloaded_before_tick_ = 0;
- 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);
- connect(m_CurrentReply, &QNetworkReply::downloadProgress, this, &Downloader::onDownloadProgressChanged);
- }
- void Downloader::updateDownloadSpeedLimit(int bytes_per_sec)
- {
- download_speed_limit = bytes_per_sec;
- if (m_CurrentReply)
- m_CurrentReply->setReadBufferSize(bytes_per_sec);
- }
- void Downloader::onDownloadProgressChanged(qint64 bytesReceived, qint64 bytesTotal)
- {
- bytes_downloaded_ = bytesReceived;
- bytes_total_ = bytesTotal;
- if (last_tick_time_.elapsed() >= 100) {
- download_speed_ = (bytes_downloaded_ - bytes_downloaded_before_tick_) * 1000.0 / (last_tick_time_.elapsed());
- average_speed_ = (average_speed_ * update_ticks_counter_ + download_speed_) / (update_ticks_counter_ + 1);
- ++update_ticks_counter_;
- last_tick_time_.restart();
- bytes_downloaded_before_tick_ = bytes_downloaded_;
- emit progressChanged(this, getDownloadStatus());
- }
- }
- void Downloader::stop()
- {
- if (m_CurrentReply) {
- m_CurrentReply->abort();
- }
- busy_ = false;
- }
- void Downloader::onDownloadFinished(QNetworkReply*) {
- if (m_CurrentReply)
- m_CurrentReply->deleteLater();
- download_speed_ = 0;
- busy_ = false;
- emit downloadFinished(this);
- }
- void Downloader::onReadyRead()
- {
- QByteArray readdata = m_CurrentReply->readAll();
- if (targetFile && targetFile->isWritable())
- targetFile->write(readdata);
- if (targetBytearray)
- targetBytearray->append(readdata);
- }
|