1 #include "downloaditem.h"
2 #include "networkaccess.h"
5 #include <QDesktopServices>
13 NetworkAccess* http();
16 DownloadItem::DownloadItem(Video *video, QUrl url, QString filename, QObject *parent)
19 , m_startedSaving(false)
20 , m_finishedDownloading(false)
27 speedCheckTimer = new QTimer(this);
28 speedCheckTimer->setInterval(2000);
29 speedCheckTimer->setSingleShot(true);
30 connect(speedCheckTimer, SIGNAL(timeout()), SLOT(speedCheck()));
33 DownloadItem::~DownloadItem() {
44 void DownloadItem::start() {
45 m_reply = The::http()->simpleGet(m_url);
49 void DownloadItem::init() {
58 m_startedSaving = false;
59 m_finishedDownloading = false;
61 // attach to the m_reply
62 m_url = m_reply->url();
63 connect(m_reply, SIGNAL(readyRead()), this, SLOT(downloadReadyRead()));
64 connect(m_reply, SIGNAL(error(QNetworkReply::NetworkError)),
65 this, SLOT(error(QNetworkReply::NetworkError)));
66 connect(m_reply, SIGNAL(downloadProgress(qint64, qint64)),
67 this, SLOT(downloadProgress(qint64, qint64)));
68 connect(m_reply, SIGNAL(metaDataChanged()),
69 this, SLOT(metaDataChanged()));
70 connect(m_reply, SIGNAL(finished()),
71 this, SLOT(requestFinished()));
73 // start timer for the download estimation
74 m_downloadTime.start();
75 speedCheckTimer->start();
77 if (m_reply->error() != QNetworkReply::NoError) {
78 error(m_reply->error());
84 void DownloadItem::stop() {
91 void DownloadItem::open() {
92 QFileInfo info(m_file);
93 QUrl url = QUrl::fromLocalFile(info.absoluteFilePath());
94 QDesktopServices::openUrl(url);
97 void DownloadItem::openFolder() {
98 QFileInfo info(m_file);
100 mac::showInFinder(info.absoluteFilePath());
102 QUrl url = QUrl::fromLocalFile(info.absolutePath());
103 QDesktopServices::openUrl(url);
107 void DownloadItem::tryAgain() {
114 m_reply = The::http()->simpleGet(m_url);
116 emit statusChanged();
119 void DownloadItem::downloadReadyRead() {
120 if (!m_reply) return;
122 if (!m_file.isOpen()) {
123 if (!m_file.open(QIODevice::ReadWrite)) {
124 qDebug() << QString("Error opening output file: %1").arg(m_file.errorString());
126 emit statusChanged();
129 emit statusChanged();
132 if (-1 == m_file.write(m_reply->readAll())) {
134 downloadInfoLabel->setText(tr("Error saving: %1")
135 .arg(m_output.errorString()));
139 m_startedSaving = true;
140 if (m_status != Downloading) {
141 // m_status = Downloading;
142 // emit statusChanged();
143 } else if (m_finishedDownloading)
148 void DownloadItem::error(QNetworkReply::NetworkError) {
151 qWarning() << m_reply->errorString() << m_reply->url().toEncoded();
152 m_errorMessage = m_reply->errorString();
161 QString DownloadItem::errorMessage() const {
162 return m_errorMessage;
165 void DownloadItem::metaDataChanged() {
166 if (!m_reply) return;
167 QVariant locationHeader = m_reply->header(QNetworkRequest::LocationHeader);
168 if (locationHeader.isValid()) {
169 m_url = locationHeader.toUrl();
170 // qDebug() << "Redirecting to" << m_url;
171 m_reply->deleteLater();
172 m_reply = The::http()->simpleGet(m_url);
177 #ifdef DOWNLOADMANAGER_DEBUG
178 qDebug() << "DownloadItem::" << __FUNCTION__ << "not handled.";
182 int DownloadItem::initialBufferSize() {
183 // qDebug() << video->getDefinitionCode();
184 switch (video->getDefinitionCode()) {
195 void DownloadItem::downloadProgress(qint64 bytesReceived, qint64 bytesTotal) {
197 // qDebug() << bytesReceived << bytesTotal << m_downloadTime.elapsed();
199 if (m_lastProgressTime.elapsed() < 150) return;
200 m_lastProgressTime.start();
202 m_bytesReceived = bytesReceived;
204 if (m_status != Downloading) {
206 int neededBytes = (int) (bytesTotal * .001);
207 // qDebug() << bytesReceived << bytesTotal << neededBytes << m_downloadTime.elapsed();
208 int bufferSize = initialBufferSize();
209 if (bytesReceived > bufferSize
210 && bytesReceived > neededBytes
211 && (m_downloadTime.elapsed() > 1000)) {
212 emit bufferProgress(100);
213 m_status = Downloading;
214 emit statusChanged();
216 int bufferPercent = bytesReceived * 100 / qMax(bufferSize, neededBytes);
217 emit bufferProgress(bufferPercent);
222 if (bytesTotal > 0) {
223 int percent = bytesReceived * 100 / bytesTotal;
224 if (percent != this->percent) {
225 this->percent = percent;
226 emit progress(percent);
233 void DownloadItem::speedCheck() {
234 if (!m_reply) return;
235 if (m_bytesReceived < initialBufferSize() / 3) {
236 m_reply->disconnect();
238 m_reply->deleteLater();
242 qDebug() << "Retrying...";
243 connect(video, SIGNAL(gotStreamUrl(QUrl)), SLOT(gotStreamUrl(QUrl)));
244 video->loadStreamUrl();
248 void DownloadItem::gotStreamUrl(QUrl streamUrl) {
250 Video *video = static_cast<Video *>(sender());
252 qDebug() << "Cannot get sender";
255 video->disconnect(this);
257 m_reply = The::http()->simpleGet(video->getStreamUrl());
261 qint64 DownloadItem::bytesTotal() const {
262 if (!m_reply) return 0;
263 return m_reply->header(QNetworkRequest::ContentLengthHeader).toULongLong();
266 qint64 DownloadItem::bytesReceived() const {
267 return m_bytesReceived;
270 double DownloadItem::remainingTime() const {
271 if (m_finishedDownloading)
274 double timeRemaining = ((double)(bytesTotal() - bytesReceived())) / currentSpeed();
276 // When downloading the eta should never be 0
277 if (timeRemaining == 0)
280 return timeRemaining;
283 double DownloadItem::currentSpeed() const {
284 if (m_finishedDownloading)
287 return m_bytesReceived * 1000.0 / m_downloadTime.elapsed();
290 void DownloadItem::requestFinished() {
292 m_finishedDownloading = true;
293 if (!m_startedSaving) {
294 qDebug() << "Request finished but never started saving";
297 if (m_status == Starting) {
298 m_status = Downloading;
299 emit statusChanged();
303 emit statusChanged();
307 QString DownloadItem::formattedFilesize(qint64 size) {
309 if (size < 1024) return tr("%1 bytes").arg(size);
310 else if (size < 1024*1024) return tr("%1 KB").arg(size/1024);
311 else if (size < 1024*1024*1024) return tr("%1 MB").arg(size/1024/1024);
312 else return tr("%1 GB").arg(size/1024/1024/1024);
317 } else if (size < 1024*1024) {
324 return QString(QLatin1String("%1 %2")).arg(size).arg(unit);
327 QString DownloadItem::formattedSpeed(double speed) {
329 static const int K = 1024;
330 if (speed < K) return tr("%1 bytes/s").arg(speed);
331 else if (speed < K*K) return tr("%1 KB/s").arg(speed/K);
332 else if (speed < K*K*K) return tr("%1 MB/s").arg(speed/K/K);
333 else return tr("%1 GB/s").arg(speed/K/K/K);
335 int speedInt = (int) speed;
337 if (speedInt < 1024) {
338 unit = tr("bytes/sec");
339 } else if (speedInt < 1024*1024) {
343 speedInt /= 1024*1024;
346 return QString(QLatin1String("%1 %2")).arg(speedInt).arg(unit);
349 QString DownloadItem::formattedTime(double timeRemaining) {
350 QString timeRemainingString = tr("seconds");
351 if (timeRemaining > 60) {
352 timeRemaining = timeRemaining / 60;
353 timeRemainingString = tr("minutes");
355 timeRemaining = floor(timeRemaining);
356 return tr("%4 %5 remaining")
358 .arg(timeRemainingString);