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