1 #include "downloaditem.h"
2 #include "networkaccess.h"
5 #include <QDesktopServices>
11 DownloadItem::DownloadItem(Video *video, QUrl url, QString filename, QObject *parent)
14 , m_startedSaving(false)
15 , m_finishedDownloading(false)
22 speedCheckTimer = new QTimer(this);
23 speedCheckTimer->setInterval(2000);
24 speedCheckTimer->setSingleShot(true);
25 connect(speedCheckTimer, SIGNAL(timeout()), SLOT(speedCheck()));
28 DownloadItem::~DownloadItem() {
29 if (m_reply) delete m_reply;
30 if (video) delete video;
33 void DownloadItem::start() {
34 m_reply = The::http()->simpleGet(m_url);
38 void DownloadItem::init() {
47 m_startedSaving = false;
48 m_finishedDownloading = false;
50 // attach to the m_reply
51 m_url = m_reply->url();
52 connect(m_reply, SIGNAL(readyRead()), this, SLOT(downloadReadyRead()));
53 connect(m_reply, SIGNAL(error(QNetworkReply::NetworkError)),
54 this, SLOT(error(QNetworkReply::NetworkError)));
55 connect(m_reply, SIGNAL(downloadProgress(qint64, qint64)),
56 this, SLOT(downloadProgress(qint64, qint64)));
57 connect(m_reply, SIGNAL(metaDataChanged()),
58 this, SLOT(metaDataChanged()));
59 connect(m_reply, SIGNAL(finished()),
60 this, SLOT(requestFinished()));
62 // start timer for the download estimation
63 m_downloadTime.start();
64 speedCheckTimer->start();
66 if (m_reply->error() != QNetworkReply::NoError) {
67 error(m_reply->error());
73 void DownloadItem::stop() {
80 void DownloadItem::open() {
81 QFileInfo info(m_file);
82 QUrl url = QUrl::fromLocalFile(info.absoluteFilePath());
83 QDesktopServices::openUrl(url);
86 void DownloadItem::openFolder() {
87 QFileInfo info(m_file);
88 QUrl url = QUrl::fromLocalFile(info.absolutePath());
89 QDesktopServices::openUrl(url);
92 void DownloadItem::tryAgain() {
99 m_reply = The::http()->simpleGet(m_url);
101 emit statusChanged();
104 void DownloadItem::downloadReadyRead() {
106 if (!m_file.isOpen()) {
107 if (!m_file.open(QIODevice::ReadWrite)) {
108 qDebug() << QString("Error opening output file: %1").arg(m_file.errorString());
110 emit statusChanged();
113 emit statusChanged();
116 if (-1 == m_file.write(m_reply->readAll())) {
118 downloadInfoLabel->setText(tr("Error saving: %1")
119 .arg(m_output.errorString()));
123 m_startedSaving = true;
124 if (m_status != Downloading) {
125 // m_status = Downloading;
126 // emit statusChanged();
127 } else if (m_finishedDownloading)
132 void DownloadItem::error(QNetworkReply::NetworkError) {
134 #ifdef DOWNLOADMANAGER_DEBUG
135 qDebug() << "DownloadItem::" << __FUNCTION__ << m_reply->errorString() << m_url;
138 qDebug() << m_reply->errorString();
140 m_errorMessage = m_reply->errorString();
147 QString DownloadItem::errorMessage() const {
148 return m_errorMessage;
151 void DownloadItem::metaDataChanged() {
152 QVariant locationHeader = m_reply->header(QNetworkRequest::LocationHeader);
153 if (locationHeader.isValid()) {
154 m_url = locationHeader.toUrl();
155 // qDebug() << "Redirecting to" << m_url;
156 m_reply->deleteLater();
157 m_reply = The::http()->simpleGet(m_url);
162 #ifdef DOWNLOADMANAGER_DEBUG
163 qDebug() << "DownloadItem::" << __FUNCTION__ << "not handled.";
167 int DownloadItem::initialBufferSize() {
168 // qDebug() << video->getDefinitionCode();
169 switch (video->getDefinitionCode()) {
180 void DownloadItem::downloadProgress(qint64 bytesReceived, qint64 bytesTotal) {
182 if (m_lastProgressTime.elapsed() < 150) return;
183 m_lastProgressTime.start();
185 m_bytesReceived = bytesReceived;
187 if (m_status != Downloading) {
189 int neededBytes = (int) (bytesTotal * .001);
190 // qDebug() << bytesReceived << bytesTotal << neededBytes << m_downloadTime.elapsed();
191 int bufferSize = initialBufferSize();
192 if (bytesReceived > bufferSize
193 && bytesReceived > neededBytes
194 && m_downloadTime.elapsed() > 1000 ) {
195 emit bufferProgress(100);
196 m_status = Downloading;
197 emit statusChanged();
199 int bufferPercent = bytesReceived * 100 / qMax(bufferSize, neededBytes);
200 emit bufferProgress(bufferPercent);
205 if (bytesTotal > 0) {
206 int percent = bytesReceived * 100 / bytesTotal;
207 if (percent != this->percent) {
208 this->percent = percent;
209 emit progress(percent);
216 void DownloadItem::speedCheck() {
217 if (!m_reply) return;
218 if (m_bytesReceived < initialBufferSize() / 3) {
219 m_reply->disconnect();
221 m_reply->deleteLater();
225 qDebug() << "Retrying...";
226 connect(video, SIGNAL(gotStreamUrl(QUrl)), SLOT(gotStreamUrl(QUrl)));
227 video->loadStreamUrl();
231 void DownloadItem::gotStreamUrl(QUrl streamUrl) {
233 Video *video = static_cast<Video *>(sender());
235 qDebug() << "Cannot get sender";
238 video->disconnect(this);
240 m_reply = The::http()->simpleGet(video->getStreamUrl());
244 qint64 DownloadItem::bytesTotal() const {
245 if (!m_reply) return 0;
246 return m_reply->header(QNetworkRequest::ContentLengthHeader).toULongLong();
249 qint64 DownloadItem::bytesReceived() const {
250 return m_bytesReceived;
253 double DownloadItem::remainingTime() const {
254 if (m_finishedDownloading)
257 double timeRemaining = ((double)(bytesTotal() - bytesReceived())) / currentSpeed();
259 // When downloading the eta should never be 0
260 if (timeRemaining == 0)
263 return timeRemaining;
266 double DownloadItem::currentSpeed() const {
267 if (m_finishedDownloading)
270 return m_bytesReceived * 1000.0 / m_downloadTime.elapsed();
273 void DownloadItem::requestFinished() {
275 m_finishedDownloading = true;
276 if (!m_startedSaving) {
277 qDebug() << "Request finished but never started saving";
282 emit statusChanged();
286 QString DownloadItem::formattedFilesize(qint64 size) {
288 if (size < 1024) return tr("%1 bytes").arg(size);
289 else if (size < 1024*1024) return tr("%1 KB").arg(size/1024);
290 else if (size < 1024*1024*1024) return tr("%1 MB").arg(size/1024/1024);
291 else return tr("%1 GB").arg(size/1024/1024/1024);
296 } else if (size < 1024*1024) {
303 return QString(QLatin1String("%1 %2")).arg(size).arg(unit);
306 QString DownloadItem::formattedSpeed(double speed) {
308 static const int K = 1024;
309 if (speed < K) return tr("%1 bytes/s").arg(speed);
310 else if (speed < K*K) return tr("%1 KB/s").arg(speed/K);
311 else if (speed < K*K*K) return tr("%1 MB/s").arg(speed/K/K);
312 else return tr("%1 GB/s").arg(speed/K/K/K);
314 int speedInt = (int) speed;
316 if (speedInt < 1024) {
317 unit = tr("bytes/sec");
318 } else if (speedInt < 1024*1024) {
322 speedInt /= 1024*1024;
325 return QString(QLatin1String("%1 %2")).arg(speedInt).arg(unit);
328 QString DownloadItem::formattedTime(double timeRemaining) {
329 QString timeRemainingString = tr("seconds");
330 if (timeRemaining > 60) {
331 timeRemaining = timeRemaining / 60;
332 timeRemainingString = tr("minutes");
334 timeRemaining = floor(timeRemaining);
335 return tr("%4 %5 remaining")
337 .arg(timeRemainingString);