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()->request(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
75 m_downloadTime.start();
76 speedCheckTimer->start();
78 if (m_reply->error() != QNetworkReply::NoError) {
79 error(m_reply->error());
85 void DownloadItem::stop() {
87 m_reply->disconnect();
89 m_reply->deleteLater();
96 void DownloadItem::open() {
97 QFileInfo info(m_file);
98 QUrl url = QUrl::fromLocalFile(info.absoluteFilePath());
99 QDesktopServices::openUrl(url);
102 void DownloadItem::openFolder() {
103 QFileInfo info(m_file);
105 mac::showInFinder(info.absoluteFilePath());
107 QUrl url = QUrl::fromLocalFile(info.absolutePath());
108 QDesktopServices::openUrl(url);
112 void DownloadItem::tryAgain() {
117 void DownloadItem::downloadReadyRead() {
118 if (!m_reply) return;
120 if (!m_file.isOpen()) {
121 if (!m_file.open(QIODevice::ReadWrite)) {
122 qWarning() << QString("Error opening output file: %1").arg(m_file.errorString());
124 emit statusChanged();
127 emit statusChanged();
130 if (-1 == m_file.write(m_reply->readAll())) {
131 qWarning() << "Error saving." << m_file.errorString();
134 m_startedSaving = true;
136 // if (m_finishedDownloading) requestFinished();
140 void DownloadItem::error(QNetworkReply::NetworkError) {
143 qWarning() << m_reply->errorString() << m_reply->url().toEncoded();
144 m_errorMessage = m_reply->errorString();
153 QString DownloadItem::errorMessage() const {
154 return m_errorMessage;
157 void DownloadItem::metaDataChanged() {
158 if (!m_reply) return;
159 QVariant locationHeader = m_reply->header(QNetworkRequest::LocationHeader);
160 if (locationHeader.isValid()) {
161 m_url = locationHeader.toUrl();
162 // qDebug() << "Redirecting to" << m_url;
167 #ifdef DOWNLOADMANAGER_DEBUG
168 qDebug() << "DownloadItem::" << __FUNCTION__ << "not handled.";
172 int DownloadItem::initialBufferSize() {
173 // qDebug() << video->getDefinitionCode();
174 switch (video->getDefinitionCode()) {
185 void DownloadItem::downloadProgress(qint64 bytesReceived, qint64 bytesTotal) {
187 // qDebug() << bytesReceived << bytesTotal << m_downloadTime.elapsed();
189 if (m_lastProgressTime.elapsed() < 150) return;
190 m_lastProgressTime.start();
192 m_bytesReceived = bytesReceived;
194 if (m_status != Downloading) {
196 int neededBytes = (int) (bytesTotal * .005);
197 int bufferSize = initialBufferSize();
198 if (bufferSize > bytesTotal) bufferSize = bytesTotal;
199 // qDebug() << bytesReceived << bytesTotal << neededBytes << bufferSize << m_downloadTime.elapsed();
200 if (bytesReceived > bufferSize
201 && bytesReceived > neededBytes
202 && m_downloadTime.elapsed() > 2000) {
203 emit bufferProgress(100);
204 m_status = Downloading;
205 emit statusChanged();
207 int bytes = qMax(bufferSize, neededBytes);
208 int bufferPercent = 0;
210 bufferPercent = bytesReceived * 100 / bytes;
211 emit bufferProgress(bufferPercent);
216 if (bytesTotal > 0) {
217 int percent = bytesReceived * 100 / bytesTotal;
218 if (percent != this->percent) {
219 this->percent = percent;
220 emit progress(percent);
227 void DownloadItem::speedCheck() {
228 if (!m_reply) return;
229 int bytesTotal = m_reply->size();
230 int bufferSize = initialBufferSize();
231 if (bufferSize > bytesTotal) bufferSize = 0;
232 if (m_bytesReceived < bufferSize / 3) {
236 qDebug() << "Retrying...";
237 connect(video, SIGNAL(gotStreamUrl(QUrl)), SLOT(gotStreamUrl(QUrl)), Qt::UniqueConnection);
238 video->loadStreamUrl();
242 void DownloadItem::gotStreamUrl(QUrl /*streamUrl*/) {
244 Video *video = static_cast<Video *>(sender());
246 qDebug() << "Cannot get sender";
249 video->disconnect(this);
251 m_url = video->getStreamUrl();
255 qint64 DownloadItem::bytesTotal() const {
256 if (!m_reply) return 0;
257 return m_reply->header(QNetworkRequest::ContentLengthHeader).toULongLong();
260 qint64 DownloadItem::bytesReceived() const {
261 return m_bytesReceived;
264 double DownloadItem::remainingTime() const {
265 if (m_finishedDownloading)
268 double speed = currentSpeed();
269 double timeRemaining = 0.0;
271 timeRemaining = ((double)(bytesTotal() - bytesReceived())) / speed;
273 // When downloading the eta should never be 0
274 if (timeRemaining == 0)
277 return timeRemaining;
280 double DownloadItem::currentSpeed() const {
281 if (m_finishedDownloading)
284 int elapsed = m_downloadTime.elapsed();
287 speed = m_bytesReceived * 1000.0 / elapsed;
291 void DownloadItem::requestFinished() {
292 if (!m_startedSaving) {
293 qDebug() << "Request finished but never started saving";
298 if (m_bytesReceived <= 0) {
299 qDebug() << "Request finished but saved 0 bytes";
304 m_finishedDownloading = true;
306 if (m_status == Starting) {
307 m_status = Downloading;
308 emit statusChanged();
312 m_totalTime = m_downloadTime.elapsed() / 1000.0;
313 emit statusChanged();
315 m_reply->deleteLater();
319 QString DownloadItem::formattedFilesize(qint64 size) {
323 } else if (size < 1024*1024) {
330 return QString(QLatin1String("%1 %2")).arg(size).arg(unit);
333 QString DownloadItem::formattedSpeed(double speed) {
334 int speedInt = (int) speed;
336 if (speedInt < 1024) {
337 unit = tr("bytes/sec");
338 } else if (speedInt < 1024*1024) {
342 speedInt /= 1024*1024;
345 return QString(QLatin1String("%1 %2")).arg(speedInt).arg(unit);
348 QString DownloadItem::formattedTime(double timeRemaining, bool remaining) {
349 QString timeRemainingString = tr("seconds");
350 if (timeRemaining > 60) {
351 timeRemaining = timeRemaining / 60;
352 timeRemainingString = tr("minutes");
354 timeRemaining = floor(timeRemaining);
355 QString msg = remaining ? tr("%4 %5 remaining") : "%4 %5";
358 .arg(timeRemainingString);