45
|
1 /****************************************************************************
|
|
2 **
|
|
3 ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
|
|
4 ** Contact: Qt Software Information (qt-info@nokia.com)
|
|
5 **
|
|
6 ** This file is part of the demonstration applications of the Qt Toolkit.
|
|
7 **
|
|
8 ** $QT_BEGIN_LICENSE:LGPL$
|
|
9 ** Commercial Usage
|
|
10 ** Licensees holding valid Qt Commercial licenses may use this file in
|
|
11 ** accordance with the Qt Commercial License Agreement provided with the
|
|
12 ** Software or, alternatively, in accordance with the terms contained in
|
|
13 ** a written agreement between you and Nokia.
|
|
14 **
|
|
15 ** GNU Lesser General Public License Usage
|
|
16 ** Alternatively, this file may be used under the terms of the GNU Lesser
|
|
17 ** General Public License version 2.1 as published by the Free Software
|
|
18 ** Foundation and appearing in the file LICENSE.LGPL included in the
|
|
19 ** packaging of this file. Please review the following information to
|
|
20 ** ensure the GNU Lesser General Public License version 2.1 requirements
|
|
21 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
|
22 **
|
|
23 ** In addition, as a special exception, Nokia gives you certain
|
|
24 ** additional rights. These rights are described in the Nokia Qt LGPL
|
|
25 ** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
|
|
26 ** package.
|
|
27 **
|
|
28 ** GNU General Public License Usage
|
|
29 ** Alternatively, this file may be used under the terms of the GNU
|
|
30 ** General Public License version 3.0 as published by the Free Software
|
|
31 ** Foundation and appearing in the file LICENSE.GPL included in the
|
|
32 ** packaging of this file. Please review the following information to
|
|
33 ** ensure the GNU General Public License version 3.0 requirements will be
|
|
34 ** met: http://www.gnu.org/copyleft/gpl.html.
|
|
35 **
|
|
36 ** If you are unsure which license is appropriate for your use, please
|
|
37 ** contact the sales department at qt-sales@nokia.com.
|
|
38 ** $QT_END_LICENSE$
|
|
39 **
|
|
40 ****************************************************************************/
|
|
41 module downloadmanager;
|
|
42
|
|
43 import ui_downloads;
|
|
44 import ui_downloaditem;
|
|
45
|
|
46 import QtNetwork.QNetworkReply;
|
|
47
|
|
48 import QtCore.QFile;
|
|
49 import QtCore.QTime;
|
|
50
|
|
51
|
|
52 import autosaver;
|
|
53 import browserapplication;
|
|
54 import networkaccessmanager;
|
|
55
|
|
56 import math;
|
|
57
|
|
58 import QtCore.QMetaEnum;
|
|
59 import QtCore.QSettings;
|
|
60
|
|
61 import QtGui.QDesktopServices;
|
|
62 import QtGui.QFileDialog;
|
|
63 import QtGui.QHeaderView;
|
|
64 import QtGui.QFileIconProvider;
|
|
65
|
|
66 import QtCore.QDebug;
|
|
67
|
|
68 import QtWebKit.QWebSettings;
|
|
69
|
|
70
|
|
71
|
|
72 class DownloadItem : public QWidget, public Ui_DownloadItem
|
|
73 {
|
|
74
|
46
|
75 mixin Signal!("statusChanged");
|
45
|
76
|
|
77 public:
|
|
78
|
|
79 /*!
|
|
80 DownloadItem is a widget that is displayed in the download manager list.
|
|
81 It moves the data from the QNetworkReply into the QFile as well
|
|
82 as update the information/progressbar and report errors.
|
|
83 */
|
46
|
84 this(QNetworkReply reply = null, bool requestFileName = false, QWidget parent = null)
|
|
85 {
|
|
86 super(parent);
|
|
87 m_reply = reply;
|
|
88 m_requestFileName = requestFileName;
|
|
89 m_bytesReceived = 0;
|
|
90
|
|
91 setupUi(this);
|
|
92 QPalette p = downloadInfoLabel.palette();
|
|
93 p.setColor(QPalette.Text, Qt.darkGray);
|
|
94 downloadInfoLabel.setPalette(p);
|
|
95 progressBar.setMaximum(0);
|
|
96 tryAgainButton.hide();
|
|
97 stopButton.clicked.connect(&this.stop);
|
|
98 openButton.clicked.connect(&this.open);
|
|
99 tryAgainButton.clicked.connect(&this.tryAgain);
|
45
|
100
|
46
|
101 init();
|
|
102 }
|
45
|
103
|
|
104
|
|
105 bool downloading()
|
46
|
106 {
|
|
107 return (progressBar.isVisible());
|
|
108 }
|
45
|
109
|
|
110
|
|
111 bool downloadedSuccessfully()
|
46
|
112 {
|
|
113 return (stopButton.isHidden() && tryAgainButton.isHidden());
|
|
114 }
|
45
|
115
|
|
116
|
|
117 QUrl m_url;
|
|
118
|
|
119 QFile m_output;
|
|
120 QNetworkReply *m_reply;
|
|
121
|
46
|
122 private: // slots:
|
45
|
123 void stop()
|
46
|
124 {
|
|
125 setUpdatesEnabled(false);
|
|
126 stopButton.setEnabled(false);
|
|
127 stopButton.hide();
|
|
128 tryAgainButton.setEnabled(true);
|
|
129 tryAgainButton.show();
|
|
130 setUpdatesEnabled(true);
|
|
131 m_reply.abort();
|
|
132 }
|
45
|
133
|
|
134 void tryAgain()
|
46
|
135 {
|
|
136 if (!tryAgainButton.isEnabled())
|
|
137 return;
|
45
|
138
|
46
|
139 tryAgainButton.setEnabled(false);
|
|
140 tryAgainButton.setVisible(false);
|
|
141 stopButton.setEnabled(true);
|
|
142 stopButton.setVisible(true);
|
|
143 progressBar.setVisible(true);
|
45
|
144
|
46
|
145 QNetworkReply *r = BrowserApplication.networkAccessManager().get(QNetworkRequest(m_url));
|
|
146 if (m_reply)
|
|
147 m_reply.deleteLater();
|
|
148 if (m_output.exists())
|
|
149 m_output.remove();
|
|
150 m_reply = r;
|
|
151 init();
|
|
152 emit statusChanged();
|
|
153 }
|
45
|
154
|
|
155 void open()
|
46
|
156 {
|
|
157 QFileInfo info(m_output);
|
|
158 QUrl url = QUrl.fromLocalFile(info.absolutePath());
|
|
159 QDesktopServices.openUrl(url);
|
|
160 }
|
45
|
161
|
|
162 void downloadReadyRead()
|
46
|
163 {
|
|
164 if (m_requestFileName && m_output.fileName().isEmpty())
|
|
165 return;
|
|
166 if (!m_output.isOpen()) {
|
|
167 // in case someone else has already put a file there
|
|
168 if (!m_requestFileName)
|
|
169 getFileName();
|
|
170 if (!m_output.open(QIODevice.WriteOnly)) {
|
|
171 downloadInfoLabel.setText(tr("Error opening save file: %1")
|
|
172 .arg(m_output.errorString()));
|
|
173 stopButton.click();
|
|
174 emit statusChanged();
|
|
175 return;
|
|
176 }
|
|
177 emit statusChanged();
|
|
178 }
|
|
179 if (-1 == m_output.write(m_reply.readAll())) {
|
|
180 downloadInfoLabel.setText(tr("Error saving: %1")
|
45
|
181 .arg(m_output.errorString()));
|
|
182 stopButton.click();
|
|
183 }
|
|
184 }
|
|
185
|
46
|
186 void error(QNetworkReply.NetworkError code)
|
|
187 {
|
|
188 qDebug() << "DownloadItem::error" << m_reply.errorString() << m_url;
|
|
189 downloadInfoLabel.setText(tr("Network Error: %1").arg(m_reply.errorString()));
|
|
190 tryAgainButton.setEnabled(true);
|
|
191 tryAgainButton.setVisible(true);
|
|
192 }
|
45
|
193
|
|
194
|
|
195 void downloadProgress(qint64 bytesReceived, qint64 bytesTotal)
|
46
|
196 {
|
|
197 m_bytesReceived = bytesReceived;
|
|
198 if (bytesTotal == -1) {
|
|
199 progressBar.setValue(0);
|
|
200 progressBar.setMaximum(0);
|
|
201 } else {
|
|
202 progressBar.setValue(bytesReceived);
|
|
203 progressBar.setMaximum(bytesTotal);
|
|
204 }
|
|
205 updateInfoLabel();
|
45
|
206 }
|
|
207
|
|
208
|
|
209 void metaDataChanged()
|
46
|
210 {
|
|
211 qDebug() << "DownloadItem::metaDataChanged: not handled.";
|
|
212 }
|
45
|
213
|
|
214 void finished()
|
46
|
215 {
|
|
216 progressBar.hide();
|
|
217 stopButton.setEnabled(false);
|
|
218 stopButton.hide();
|
|
219 m_output.close();
|
|
220 updateInfoLabel();
|
|
221 emit statusChanged();
|
|
222 }
|
45
|
223
|
|
224 private:
|
|
225 void getFileName()
|
46
|
226 {
|
|
227 QSettings settings;
|
|
228 settings.beginGroup(QLatin1String("downloadmanager"));
|
|
229 QString defaultLocation = QDesktopServices.storageLocation(QDesktopServices.DesktopLocation);
|
|
230 QString downloadDirectory = settings.value(QLatin1String("downloadDirectory"), defaultLocation).toString();
|
|
231 if (!downloadDirectory.isEmpty())
|
|
232 downloadDirectory += QLatin1Char('/');
|
45
|
233
|
46
|
234 QString defaultFileName = saveFileName(downloadDirectory);
|
|
235 QString fileName = defaultFileName;
|
|
236 if (m_requestFileName) {
|
|
237 fileName = QFileDialog.getSaveFileName(this, tr("Save File"), defaultFileName);
|
|
238 if (fileName.isEmpty()) {
|
|
239 m_reply.close();
|
|
240 fileNameLabel.setText(tr("Download canceled: %1").arg(QFileInfo(defaultFileName).fileName()));
|
|
241 return;
|
|
242 }
|
45
|
243 }
|
46
|
244 m_output.setFileName(fileName);
|
|
245 fileNameLabel.setText(QFileInfo(m_output.fileName()).fileName());
|
|
246 if (m_requestFileName)
|
|
247 downloadReadyRead();
|
45
|
248 }
|
|
249
|
|
250 void init()
|
46
|
251 {
|
|
252 if (!m_reply)
|
|
253 return;
|
45
|
254
|
46
|
255 // attach to the m_reply
|
|
256 m_url = m_reply.url();
|
|
257 m_reply.setParent(this);
|
|
258 connect(m_reply, SIGNAL(readyRead()), this, SLOT(downloadReadyRead()));
|
|
259 connect(m_reply, SIGNAL(error(QNetworkReply.NetworkError)),
|
|
260 this, SLOT(error(QNetworkReply.NetworkError)));
|
|
261 connect(m_reply, SIGNAL(downloadProgress(qint64, qint64)),
|
|
262 this, SLOT(downloadProgress(qint64, qint64)));
|
|
263 connect(m_reply, SIGNAL(metaDataChanged()),
|
|
264 this, SLOT(metaDataChanged()));
|
|
265 connect(m_reply, SIGNAL(finished()),
|
|
266 this, SLOT(finished()));
|
45
|
267
|
46
|
268 // reset info
|
|
269 downloadInfoLabel.clear();
|
|
270 progressBar.setValue(0);
|
|
271 getFileName();
|
45
|
272
|
46
|
273 // start timer for the download estimation
|
|
274 m_downloadTime.start();
|
45
|
275
|
46
|
276 if (m_reply.error() != QNetworkReply.NoError) {
|
|
277 error(m_reply.error());
|
|
278 finished();
|
|
279 }
|
45
|
280 }
|
|
281
|
|
282 void updateInfoLabel()
|
46
|
283 {
|
|
284 if (m_reply.error() == QNetworkReply.NoError)
|
|
285 return;
|
45
|
286
|
46
|
287 qint64 bytesTotal = progressBar.maximum();
|
|
288 bool running = !downloadedSuccessfully();
|
45
|
289
|
46
|
290 // update info label
|
|
291 double speed = m_bytesReceived * 1000.0 / m_downloadTime.elapsed();
|
|
292 double timeRemaining = ((double)(bytesTotal - m_bytesReceived)) / speed;
|
|
293 QString timeRemainingString = tr("seconds");
|
|
294 if (timeRemaining > 60) {
|
|
295 timeRemaining = timeRemaining / 60;
|
|
296 timeRemainingString = tr("minutes");
|
|
297 }
|
|
298 timeRemaining = floor(timeRemaining);
|
45
|
299
|
46
|
300 // When downloading the eta should never be 0
|
|
301 if (timeRemaining == 0)
|
|
302 timeRemaining = 1;
|
45
|
303
|
46
|
304 QString info;
|
|
305 if (running) {
|
|
306 QString remaining;
|
|
307 if (bytesTotal != 0)
|
|
308 remaining = tr("- %4 %5 remaining")
|
|
309 .arg(timeRemaining)
|
|
310 .arg(timeRemainingString);
|
|
311 info = QString(tr("%1 of %2 (%3/sec) %4"))
|
45
|
312 .arg(dataString(m_bytesReceived))
|
46
|
313 .arg(bytesTotal == 0 ? tr("?") : dataString(bytesTotal))
|
|
314 .arg(dataString((int)speed))
|
|
315 .arg(remaining);
|
|
316 } else {
|
|
317 if (m_bytesReceived == bytesTotal)
|
|
318 info = dataString(m_output.size());
|
|
319 else
|
|
320 info = tr("%1 of %2 - Stopped")
|
|
321 .arg(dataString(m_bytesReceived))
|
|
322 .arg(dataString(bytesTotal));
|
|
323 }
|
|
324 downloadInfoLabel.setText(info);
|
45
|
325 }
|
|
326
|
|
327 QString dataString(int size)
|
46
|
328 {
|
|
329 QString unit;
|
|
330 if (size < 1024) {
|
|
331 unit = tr("bytes");
|
|
332 } else if (size < 1024*1024) {
|
|
333 size /= 1024;
|
|
334 unit = tr("kB");
|
|
335 } else {
|
|
336 size /= 1024*1024;
|
|
337 unit = tr("MB");
|
|
338 }
|
|
339 return QString(QLatin1String("%1 %2")).arg(size).arg(unit);
|
45
|
340 }
|
|
341
|
|
342 QString saveFileName(const QString &directory);
|
46
|
343 {
|
|
344 // Move this function into QNetworkReply to also get file name sent from the server
|
|
345 QString path = m_url.path();
|
|
346 QFileInfo info(path);
|
|
347 QString baseName = info.completeBaseName();
|
|
348 QString endName = info.suffix();
|
45
|
349
|
46
|
350 if (baseName.isEmpty()) {
|
|
351 baseName = QLatin1String("unnamed_download");
|
|
352 qDebug() << "DownloadManager:: downloading unknown file:" << m_url;
|
|
353 }
|
|
354 QString name = directory + baseName + QLatin1Char('.') + endName;
|
|
355 if (QFile.exists(name)) {
|
|
356 // already exists, don't overwrite
|
|
357 int i = 1;
|
|
358 do {
|
|
359 name = directory + baseName + QLatin1Char('-') + QString.number(i++) + QLatin1Char('.') + endName;
|
|
360 } while (QFile.exists(name));
|
|
361 }
|
|
362 return name;
|
45
|
363 }
|
|
364
|
|
365 bool m_requestFileName;
|
|
366 qint64 m_bytesReceived;
|
|
367 QTime m_downloadTime;
|
|
368 };
|
|
369
|
|
370 class AutoSaver;
|
|
371 class DownloadModel;
|
|
372 QT_BEGIN_NAMESPACE
|
|
373 class QFileIconProvider;
|
|
374 QT_END_NAMESPACE
|
|
375
|
|
376 class DownloadManager : public QDialog, public Ui_DownloadDialog
|
|
377 {
|
|
378 Q_OBJECT
|
|
379 Q_PROPERTY(RemovePolicy removePolicy READ removePolicy WRITE setRemovePolicy)
|
|
380 Q_ENUMS(RemovePolicy)
|
|
381
|
|
382 public:
|
|
383 enum RemovePolicy {
|
|
384 Never,
|
|
385 Exit,
|
|
386 SuccessFullDownload
|
|
387 };
|
|
388
|
|
389 /*!
|
|
390 DownloadManager is a Dialog that contains a list of DownloadItems
|
|
391
|
|
392 It is a basic download manager. It only downloads the file, doesn't do BitTorrent,
|
|
393 extract zipped files or anything fancy.
|
|
394 */
|
|
395 this(QWidget *parent = null)
|
|
396 : QDialog(parent)
|
|
397 , m_autoSaver(new AutoSaver(this))
|
46
|
398 , m_manager(BrowserApplication.networkAccessManager())
|
45
|
399 , m_iconProvider(0)
|
|
400 , m_removePolicy(Never)
|
|
401 {
|
|
402 setupUi(this);
|
|
403 downloadsView.setShowGrid(false);
|
|
404 downloadsView.verticalHeader().hide();
|
|
405 downloadsView.horizontalHeader().hide();
|
|
406 downloadsView.setAlternatingRowColors(true);
|
|
407 downloadsView.horizontalHeader().setStretchLastSection(true);
|
|
408 m_model = new DownloadModel(this);
|
|
409 downloadsView.setModel(m_model);
|
|
410 connect(cleanupButton, SIGNAL(clicked()), this, SLOT(cleanup()));
|
|
411 load();
|
|
412 }
|
|
413
|
|
414 ~this()
|
|
415 {
|
|
416 m_autoSaver.changeOccurred();
|
|
417 m_autoSaver.saveIfNeccessary();
|
|
418 if (m_iconProvider)
|
|
419 delete m_iconProvider;
|
|
420 }
|
|
421
|
|
422 int activeDownloads()
|
|
423 {
|
|
424 int count = 0;
|
|
425 for (int i = 0; i < m_downloads.count(); ++i) {
|
|
426 if (m_downloads.at(i).stopButton.isEnabled())
|
|
427 ++count;
|
|
428 }
|
|
429 return count;
|
|
430 }
|
|
431
|
|
432 RemovePolicy removePolicy()
|
|
433 {
|
|
434 return m_removePolicy;
|
|
435 }
|
|
436
|
|
437 void setRemovePolicy(RemovePolicy policy)
|
|
438 {
|
|
439 if (policy == m_removePolicy)
|
|
440 return;
|
|
441 m_removePolicy = policy;
|
|
442 m_autoSaver.changeOccurred();
|
|
443 }
|
|
444
|
|
445
|
|
446 public slots:
|
|
447 void download(const QNetworkRequest &request, bool requestFileName = false);
|
|
448 {
|
|
449 if (request.url().isEmpty())
|
|
450 return;
|
|
451 handleUnsupportedContent(m_manager.get(request), requestFileName);
|
|
452 }
|
|
453
|
|
454
|
|
455 inline void download(const QUrl &url, bool requestFileName = false)
|
|
456 { download(QNetworkRequest(url), requestFileName); }
|
|
457 void handleUnsupportedContent(QNetworkReply *reply, bool requestFileName = false);
|
|
458 {
|
|
459 if (!reply || reply.url().isEmpty())
|
|
460 return;
|
46
|
461 QVariant header = reply.header(QNetworkRequest.ContentLengthHeader);
|
45
|
462 bool ok;
|
|
463 int size = header.toInt(&ok);
|
|
464 if (ok && size == 0)
|
|
465 return;
|
|
466
|
|
467 qDebug() << "DownloadManager::handleUnsupportedContent" << reply.url() << "requestFileName" << requestFileName;
|
|
468 DownloadItem *item = new DownloadItem(reply, requestFileName, this);
|
|
469 addItem(item);
|
|
470 }
|
|
471
|
|
472 void cleanup()
|
|
473 {
|
|
474 if (m_downloads.isEmpty())
|
|
475 return;
|
|
476 m_model.removeRows(0, m_downloads.count());
|
|
477 updateItemCount();
|
|
478 if (m_downloads.isEmpty() && m_iconProvider) {
|
|
479 delete m_iconProvider;
|
|
480 m_iconProvider = 0;
|
|
481 }
|
|
482 m_autoSaver.changeOccurred();
|
|
483 }
|
|
484
|
|
485 private slots:
|
|
486 void save()
|
|
487 {
|
|
488 QSettings settings;
|
|
489 settings.beginGroup(QLatin1String("downloadmanager"));
|
|
490 QMetaEnum removePolicyEnum = staticMetaObject.enumerator(staticMetaObject.indexOfEnumerator("RemovePolicy"));
|
|
491 settings.setValue(QLatin1String("removeDownloadsPolicy"), QLatin1String(removePolicyEnum.valueToKey(m_removePolicy)));
|
|
492 settings.setValue(QLatin1String("size"), size());
|
|
493 if (m_removePolicy == Exit)
|
|
494 return;
|
|
495
|
|
496 for (int i = 0; i < m_downloads.count(); ++i) {
|
|
497 QString key = QString(QLatin1String("download_%1_")).arg(i);
|
|
498 settings.setValue(key + QLatin1String("url"), m_downloads[i].m_url);
|
|
499 settings.setValue(key + QLatin1String("location"), QFileInfo(m_downloads[i].m_output).filePath());
|
|
500 settings.setValue(key + QLatin1String("done"), m_downloads[i].downloadedSuccessfully());
|
|
501 }
|
|
502 int i = m_downloads.count();
|
|
503 QString key = QString(QLatin1String("download_%1_")).arg(i);
|
|
504 while (settings.contains(key + QLatin1String("url"))) {
|
|
505 settings.remove(key + QLatin1String("url"));
|
|
506 settings.remove(key + QLatin1String("location"));
|
|
507 settings.remove(key + QLatin1String("done"));
|
|
508 key = QString(QLatin1String("download_%1_")).arg(++i);
|
|
509 }
|
|
510 }
|
|
511
|
|
512 void updateRow()
|
|
513 {
|
|
514 DownloadItem *item = qobject_cast<DownloadItem*>(sender());
|
|
515 int row = m_downloads.indexOf(item);
|
|
516 if (-1 == row)
|
|
517 return;
|
|
518 if (!m_iconProvider)
|
|
519 m_iconProvider = new QFileIconProvider();
|
|
520 QIcon icon = m_iconProvider.icon(item.m_output.fileName());
|
|
521 if (icon.isNull())
|
46
|
522 icon = style().standardIcon(QStyle.SP_FileIcon);
|
45
|
523 item.fileIcon.setPixmap(icon.pixmap(48, 48));
|
|
524 downloadsView.setRowHeight(row, item.minimumSizeHint().height());
|
|
525
|
|
526 bool remove = false;
|
46
|
527 QWebSettings *globalSettings = QWebSettings.globalSettings();
|
45
|
528 if (!item.downloading()
|
46
|
529 && globalSettings.testAttribute(QWebSettings.PrivateBrowsingEnabled))
|
45
|
530 remove = true;
|
|
531
|
|
532 if (item.downloadedSuccessfully()
|
46
|
533 && removePolicy() == DownloadManager.SuccessFullDownload) {
|
45
|
534 remove = true;
|
|
535 }
|
|
536 if (remove)
|
|
537 m_model.removeRow(row);
|
|
538
|
|
539 cleanupButton.setEnabled(m_downloads.count() - activeDownloads() > 0);
|
|
540 }
|
|
541
|
|
542 private:
|
|
543 void addItem(DownloadItem *item)
|
|
544 {
|
|
545 connect(item, SIGNAL(statusChanged()), this, SLOT(updateRow()));
|
|
546 int row = m_downloads.count();
|
|
547 m_model.beginInsertRows(QModelIndex(), row, row);
|
|
548 m_downloads.append(item);
|
|
549 m_model.endInsertRows();
|
|
550 updateItemCount();
|
|
551 if (row == 0)
|
|
552 show();
|
|
553 downloadsView.setIndexWidget(m_model.index(row, 0), item);
|
46
|
554 QIcon icon = style().standardIcon(QStyle.SP_FileIcon);
|
45
|
555 item.fileIcon.setPixmap(icon.pixmap(48, 48));
|
|
556 downloadsView.setRowHeight(row, item.sizeHint().height());
|
|
557 }
|
|
558
|
|
559
|
|
560 void updateItemCount()
|
|
561 {
|
|
562 int count = m_downloads.count();
|
|
563 itemCount.setText(count == 1 ? tr("1 Download") : tr("%1 Downloads").arg(count));
|
|
564 }
|
|
565
|
46
|
566 DownloadModel.DownloadModel(DownloadManager *downloadManager, QObject *parent)
|
45
|
567 : QAbstractListModel(parent)
|
|
568 , m_downloadManager(downloadManager)
|
|
569 {
|
|
570 }
|
|
571
|
|
572 void load()
|
|
573 {
|
|
574 QSettings settings;
|
|
575 settings.beginGroup(QLatin1String("downloadmanager"));
|
|
576 QSize size = settings.value(QLatin1String("size")).toSize();
|
|
577 if (size.isValid())
|
|
578 resize(size);
|
|
579 QByteArray value = settings.value(QLatin1String("removeDownloadsPolicy"), QLatin1String("Never")).toByteArray();
|
|
580 QMetaEnum removePolicyEnum = staticMetaObject.enumerator(staticMetaObject.indexOfEnumerator("RemovePolicy"));
|
|
581 m_removePolicy = removePolicyEnum.keyToValue(value) == -1 ?
|
|
582 Never :
|
|
583 static_cast<RemovePolicy>(removePolicyEnum.keyToValue(value));
|
|
584
|
|
585 int i = 0;
|
|
586 QString key = QString(QLatin1String("download_%1_")).arg(i);
|
|
587 while (settings.contains(key + QLatin1String("url"))) {
|
|
588 QUrl url = settings.value(key + QLatin1String("url")).toUrl();
|
|
589 QString fileName = settings.value(key + QLatin1String("location")).toString();
|
|
590 bool done = settings.value(key + QLatin1String("done"), true).toBool();
|
|
591 if (!url.isEmpty() && !fileName.isEmpty()) {
|
|
592 DownloadItem *item = new DownloadItem(0, this);
|
|
593 item.m_output.setFileName(fileName);
|
|
594 item.fileNameLabel.setText(QFileInfo(item.m_output.fileName()).fileName());
|
|
595 item.m_url = url;
|
|
596 item.stopButton.setVisible(false);
|
|
597 item.stopButton.setEnabled(false);
|
|
598 item.tryAgainButton.setVisible(!done);
|
|
599 item.tryAgainButton.setEnabled(!done);
|
|
600 item.progressBar.setVisible(!done);
|
|
601 addItem(item);
|
|
602 }
|
|
603 key = QString(QLatin1String("download_%1_")).arg(++i);
|
|
604 }
|
|
605 cleanupButton.setEnabled(m_downloads.count() - activeDownloads() > 0);
|
|
606 }
|
|
607
|
|
608 AutoSaver *m_autoSaver;
|
|
609 DownloadModel *m_model;
|
|
610 QNetworkAccessManager *m_manager;
|
|
611 QFileIconProvider *m_iconProvider;
|
|
612 QList<DownloadItem*> m_downloads;
|
|
613 RemovePolicy m_removePolicy;
|
|
614 friend class DownloadModel;
|
|
615 };
|
|
616
|
|
617 class DownloadModel : public QAbstractListModel
|
|
618 {
|
|
619 friend class DownloadManager;
|
|
620 Q_OBJECT
|
|
621
|
|
622 public:
|
|
623 DownloadModel(DownloadManager *downloadManager, QObject *parent = 0);
|
|
624 QVariant data(const QModelIndex &index, int role = Qt.DisplayRole)
|
|
625 {
|
|
626 if (index.row() < 0 || index.row() >= rowCount(index.parent()))
|
|
627 return QVariant();
|
|
628 if (role == Qt.ToolTipRole)
|
|
629 if (!m_downloadManager.m_downloads.at(index.row()).downloadedSuccessfully())
|
|
630 return m_downloadManager.m_downloads.at(index.row()).downloadInfoLabel.text();
|
|
631 return QVariant();
|
|
632 }
|
|
633
|
|
634 int rowCount(const QModelIndex &parent = QModelIndex())
|
|
635 {
|
|
636 return (parent.isValid()) ? 0 : m_downloadManager.m_downloads.count();
|
|
637 }
|
|
638
|
|
639
|
|
640 bool removeRows(int row, int count, const QModelIndex &parent = QModelIndex())
|
|
641 {
|
|
642 if (parent.isValid())
|
|
643 return false;
|
|
644
|
|
645 int lastRow = row + count - 1;
|
|
646 for (int i = lastRow; i >= row; --i) {
|
|
647 if (m_downloadManager.m_downloads.at(i).downloadedSuccessfully()
|
|
648 || m_downloadManager.m_downloads.at(i).tryAgainButton.isEnabled()) {
|
|
649 beginRemoveRows(parent, i, i);
|
|
650 m_downloadManager.m_downloads.takeAt(i).deleteLater();
|
|
651 endRemoveRows();
|
|
652 }
|
|
653 }
|
|
654 m_downloadManager.m_autoSaver.changeOccurred();
|
|
655 return true;
|
|
656 }
|
|
657
|
|
658 private:
|
|
659 DownloadManager *m_downloadManager;
|
|
660
|
|
661 }
|