]> git.sur5r.net Git - minitube/blob - src/downloaditem.cpp
1219fb489944ca9800af9aae1075e03cc648d544
[minitube] / src / downloaditem.cpp
1 #include "downloaditem.h"
2 #include "networkaccess.h"
3 #include "video.h"
4
5 #include <QDesktopServices>
6
7 namespace The {
8     NetworkAccess* http();
9 }
10
11 DownloadItem::DownloadItem(Video *video, QUrl url, QString filename, QObject *parent)
12     : QObject(parent)
13     , m_bytesReceived(0)
14     , m_startedSaving(false)
15     , m_finishedDownloading(false)
16     , m_url(url)
17     , m_file(filename)
18     , m_reply(0)
19     , video(video)
20     , m_status(Idle)
21 { }
22
23 void DownloadItem::start() {
24     m_reply = The::http()->simpleGet(m_url);
25     init();
26 }
27
28 void DownloadItem::init() {
29     if (!m_reply)
30         return;
31
32     m_status = Starting;
33
34     m_startedSaving = false;
35     m_finishedDownloading = false;
36
37     // attach to the m_reply
38     m_url = m_reply->url();
39     connect(m_reply, SIGNAL(readyRead()), this, SLOT(downloadReadyRead()));
40     connect(m_reply, SIGNAL(error(QNetworkReply::NetworkError)),
41             this, SLOT(error(QNetworkReply::NetworkError)));
42     connect(m_reply, SIGNAL(downloadProgress(qint64, qint64)),
43             this, SLOT(downloadProgress(qint64, qint64)));
44     connect(m_reply, SIGNAL(metaDataChanged()),
45             this, SLOT(metaDataChanged()));
46     connect(m_reply, SIGNAL(finished()),
47             this, SLOT(requestFinished()));
48
49     // start timer for the download estimation
50     m_downloadTime.start();
51
52     if (m_reply->error() != QNetworkReply::NoError) {
53         error(m_reply->error());
54         requestFinished();
55     }
56 }
57
58
59 void DownloadItem::stop() {
60     if (m_reply)
61         m_reply->abort();
62     m_status = Idle;
63     emit statusChanged();
64 }
65
66 void DownloadItem::open() {
67     QFileInfo info(m_file);
68     QUrl url = QUrl::fromLocalFile(info.absoluteFilePath());
69     QDesktopServices::openUrl(url);
70 }
71
72 void DownloadItem::openFolder() {
73     QFileInfo info(m_file);
74     QUrl url = QUrl::fromLocalFile(info.absolutePath());
75     QDesktopServices::openUrl(url);
76 }
77
78 void DownloadItem::tryAgain() {
79     if (m_reply)
80         m_reply->abort();
81
82     if (m_file.exists())
83         m_file.remove();
84
85     m_reply = The::http()->simpleGet(m_url);
86     init();
87     emit statusChanged();
88 }
89
90 void DownloadItem::downloadReadyRead() {
91
92     if (!m_file.isOpen()) {
93         if (!m_file.open(QIODevice::WriteOnly)) {
94             qDebug() << QString("Error opening output file: %1").arg(m_file.errorString());
95             stop();
96             emit statusChanged();
97             return;
98         }
99         emit statusChanged();
100     }
101
102     if (-1 == m_file.write(m_reply->readAll())) {
103         /*
104         downloadInfoLabel->setText(tr("Error saving: %1")
105                                    .arg(m_output.errorString()));
106         stopButton->click();
107         */
108     } else {
109         m_startedSaving = true;
110         if (m_status != Downloading) {
111             // m_status = Downloading;
112             // emit statusChanged();
113         } else if (m_finishedDownloading)
114             requestFinished();
115     }
116 }
117
118 void DownloadItem::error(QNetworkReply::NetworkError) {
119
120 #ifdef DOWNLOADMANAGER_DEBUG
121     qDebug() << "DownloadItem::" << __FUNCTION__ << m_reply->errorString() << m_url;
122 #endif
123
124     m_errorMessage = m_reply->errorString();
125     m_reply = 0;
126     m_status = Failed;
127
128     emit finished();
129 }
130
131 QString DownloadItem::errorMessage() const {
132     return m_errorMessage;
133 }
134
135 void DownloadItem::metaDataChanged() {
136     QVariant locationHeader = m_reply->header(QNetworkRequest::LocationHeader);
137     if (locationHeader.isValid()) {
138         m_url = locationHeader.toUrl();
139         m_reply->deleteLater();
140         m_reply = The::http()->simpleGet(m_url);
141         init();
142         return;
143     }
144
145 #ifdef DOWNLOADMANAGER_DEBUG
146     qDebug() << "DownloadItem::" << __FUNCTION__ << "not handled.";
147 #endif
148 }
149
150 void DownloadItem::downloadProgress(qint64 bytesReceived, qint64 bytesTotal) {
151     QTime now = QTime::currentTime();
152     if (m_lastProgressTime.msecsTo(now) < 200)
153         return;
154
155     m_lastProgressTime = now;
156
157     m_bytesReceived = bytesReceived;
158     if (bytesTotal > 0) {
159         percent = bytesReceived * 100 / bytesTotal;
160     }
161
162     // qDebug() << bytesReceived << bytesTotal;
163     if (m_status != Downloading
164         && bytesReceived > 1024 * 512
165         && bytesReceived > bytesTotal * .01) {
166         m_status = Downloading;
167         emit statusChanged();
168     }
169
170     emit progress(percent);
171     // emit statusChanged();
172 }
173
174 qint64 DownloadItem::bytesTotal() const {
175     if (!m_reply) return 0;
176     return m_reply->header(QNetworkRequest::ContentLengthHeader).toULongLong();
177 }
178
179 qint64 DownloadItem::bytesReceived() const {
180     return m_bytesReceived;
181 }
182
183 double DownloadItem::remainingTime() const {
184     if (m_finishedDownloading)
185         return -1.0;
186
187     double timeRemaining = ((double)(bytesTotal() - bytesReceived())) / currentSpeed();
188
189     // When downloading the eta should never be 0
190     if (timeRemaining == 0)
191         timeRemaining = 1;
192
193     return timeRemaining;
194 }
195
196 double DownloadItem::currentSpeed() const {
197     if (m_finishedDownloading)
198         return -1.0;
199
200     return m_bytesReceived * 1000.0 / m_downloadTime.elapsed();
201 }
202
203 void DownloadItem::requestFinished() {
204     m_reply = 0;
205     m_finishedDownloading = true;
206     if (!m_startedSaving) {
207         return;
208     }
209     m_file.close();
210     m_status = Finished;
211     emit statusChanged();
212     emit finished();
213 }
214
215 QString DownloadItem::formattedFilesize(qint64 size) {
216     /*
217     if (size < 1024) return tr("%1 bytes").arg(size);
218     else if (size < 1024*1024) return tr("%1 KB").arg(size/1024);
219     else if (size < 1024*1024*1024) return tr("%1 MB").arg(size/1024/1024);
220     else return tr("%1 GB").arg(size/1024/1024/1024);
221     */
222     QString unit;
223     if (size < 1024) {
224         unit = tr("bytes");
225     } else if (size < 1024*1024) {
226         size /= 1024;
227         unit = tr("KB");
228     } else {
229         size /= 1024*1024;
230         unit = tr("MB");
231     }
232     return QString(QLatin1String("%1 %2")).arg(size).arg(unit);
233 }
234
235 QString DownloadItem::formattedSpeed(double speed) {
236     /*
237     static const int K = 1024;
238     if (speed < K) return tr("%1 bytes/s").arg(speed);
239     else if (speed < K*K) return tr("%1 KB/s").arg(speed/K);
240     else if (speed < K*K*K) return tr("%1 MB/s").arg(speed/K/K);
241     else return tr("%1 GB/s").arg(speed/K/K/K);
242     */
243     int speedInt = (int) speed;
244     QString unit;
245     if (speedInt < 1024) {
246         unit = tr("bytes/sec");
247     } else if (speedInt < 1024*1024) {
248         speedInt /= 1024;
249         unit = tr("KB/sec");
250     } else {
251         speedInt /= 1024*1024;
252         unit = tr("MB/sec");
253     }
254     return QString(QLatin1String("%1 %2")).arg(speedInt).arg(unit);
255 }
256
257 QString DownloadItem::formattedTime(double timeRemaining) {
258     QString timeRemainingString = tr("seconds");
259     if (timeRemaining > 60) {
260         timeRemaining = timeRemaining / 60;
261         timeRemainingString = tr("minutes");
262     }
263     timeRemaining = floor(timeRemaining);
264     return tr("%4 %5 remaining")
265             .arg(timeRemaining)
266             .arg(timeRemainingString);
267 }