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