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 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 }
|