Mercurial > projects > qtd
comparison demos/browser/downloadmanager.d @ 73:7bfd46c330dc
more porting
author | mandel |
---|---|
date | Fri, 22 May 2009 10:59:00 +0000 |
parents | fd6eb3a1759d |
children | 37caa90ce503 |
comparison
equal
deleted
inserted
replaced
72:b149ef2cb18b | 73:7bfd46c330dc |
---|---|
36 ** If you are unsure which license is appropriate for your use, please | 36 ** If you are unsure which license is appropriate for your use, please |
37 ** contact the sales department at qt-sales@nokia.com. | 37 ** contact the sales department at qt-sales@nokia.com. |
38 ** $QT_END_LICENSE$ | 38 ** $QT_END_LICENSE$ |
39 ** | 39 ** |
40 ****************************************************************************/ | 40 ****************************************************************************/ |
41 | |
41 module downloadmanager; | 42 module downloadmanager; |
42 | 43 |
43 import ui_downloads; | 44 |
44 import ui_downloaditem; | 45 import qt.core.QFile; |
45 | 46 import qt.core.QTime; |
46 import QtNetwork.QNetworkReply; | 47 import qt.core.QMetaEnum; |
47 | 48 import qt.core.QSettings; |
48 import QtCore.QFile; | 49 import qt.core.QDebug; |
49 import QtCore.QTime; | 50 |
50 | 51 import qt.gui.QDesktopServices; |
51 | 52 import qt.gui.QFileDialog; |
53 import qt.gui.QHeaderView; | |
54 import qt.gui.QFileIconProvider; | |
55 | |
56 import qt.network.QNetworkReply; | |
57 import qt.webkit.QWebSettings; | |
58 | |
59 import math; | |
52 import autosaver; | 60 import autosaver; |
53 import browserapplication; | 61 import browserapplication; |
54 import networkaccessmanager; | 62 import networkaccessmanager; |
55 | 63 import ui_downloads; |
56 import math; | 64 import ui_downloaditem; |
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 | 65 |
71 | 66 |
72 class DownloadItem : public QWidget, public Ui_DownloadItem | 67 class DownloadItem : public QWidget, public Ui_DownloadItem |
73 { | 68 { |
74 | |
75 mixin Signal!("statusChanged"); | 69 mixin Signal!("statusChanged"); |
76 | 70 |
77 public: | 71 public: |
78 | 72 |
79 /*! | 73 /*! |
80 DownloadItem is a widget that is displayed in the download manager list. | 74 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 | 75 It moves the data from the QNetworkReply into the QFile as well |
82 as update the information/progressbar and report errors. | 76 as update the information/progressbar and report errors. |
83 */ | 77 */ |
84 this(QNetworkReply reply = null, bool requestFileName = false, QWidget parent = null) | 78 this(QNetworkReply reply = null, bool requestFileName = false, QWidget parent = null) |
85 { | 79 { |
86 super(parent); | 80 super(parent); |
87 m_reply = reply; | 81 m_reply = reply; |
88 m_requestFileName = requestFileName; | 82 m_requestFileName = requestFileName; |
89 m_bytesReceived = 0; | 83 m_bytesReceived = 0; |
90 | 84 |
91 setupUi(this); | 85 setupUi(this); |
92 QPalette p = downloadInfoLabel.palette(); | 86 QPalette p = downloadInfoLabel.palette(); |
93 p.setColor(QPalette.Text, Qt.darkGray); | 87 p.setColor(QPalette.Text, Qt.darkGray); |
94 downloadInfoLabel.setPalette(p); | 88 downloadInfoLabel.setPalette(p); |
95 progressBar.setMaximum(0); | 89 progressBar.setMaximum(0); |
96 tryAgainButton.hide(); | 90 tryAgainButton.hide(); |
97 stopButton.clicked.connect(&this.stop); | 91 stopButton.clicked.connect(&this.stop); |
98 openButton.clicked.connect(&this.open); | 92 openButton.clicked.connect(&this.open); |
99 tryAgainButton.clicked.connect(&this.tryAgain); | 93 tryAgainButton.clicked.connect(&this.tryAgain); |
100 | 94 |
101 init(); | 95 init(); |
102 } | 96 } |
103 | 97 |
104 | 98 bool downloading() |
105 bool downloading() | 99 { |
106 { | 100 return (progressBar.isVisible()); |
107 return (progressBar.isVisible()); | 101 } |
108 } | 102 |
109 | 103 bool downloadedSuccessfully() |
110 | 104 { |
111 bool downloadedSuccessfully() | 105 return (stopButton.isHidden() && tryAgainButton.isHidden()); |
112 { | 106 } |
113 return (stopButton.isHidden() && tryAgainButton.isHidden()); | 107 |
114 } | 108 QUrl m_url; |
115 | 109 QFile m_output; |
116 | 110 QNetworkReply m_reply; |
117 QUrl m_url; | |
118 | |
119 QFile m_output; | |
120 QNetworkReply *m_reply; | |
121 | |
122 private: // slots: | |
123 void stop() | |
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 } | |
133 | |
134 void tryAgain() | |
135 { | |
136 if (!tryAgainButton.isEnabled()) | |
137 return; | |
138 | |
139 tryAgainButton.setEnabled(false); | |
140 tryAgainButton.setVisible(false); | |
141 stopButton.setEnabled(true); | |
142 stopButton.setVisible(true); | |
143 progressBar.setVisible(true); | |
144 | |
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 } | |
154 | |
155 void open() | |
156 { | |
157 QFileInfo info(m_output); | |
158 QUrl url = QUrl.fromLocalFile(info.absolutePath()); | |
159 QDesktopServices.openUrl(url); | |
160 } | |
161 | |
162 void downloadReadyRead() | |
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") | |
181 .arg(m_output.errorString())); | |
182 stopButton.click(); | |
183 } | |
184 } | |
185 | |
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 } | |
193 | |
194 | |
195 void downloadProgress(qint64 bytesReceived, qint64 bytesTotal) | |
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(); | |
206 } | |
207 | |
208 | |
209 void metaDataChanged() | |
210 { | |
211 qDebug() << "DownloadItem::metaDataChanged: not handled."; | |
212 } | |
213 | |
214 void finished() | |
215 { | |
216 progressBar.hide(); | |
217 stopButton.setEnabled(false); | |
218 stopButton.hide(); | |
219 m_output.close(); | |
220 updateInfoLabel(); | |
221 emit statusChanged(); | |
222 } | |
223 | 111 |
224 private: | 112 private: |
225 void getFileName() | 113 |
226 { | 114 void stop() |
227 QSettings settings; | 115 { |
228 settings.beginGroup(QLatin1String("downloadmanager")); | 116 setUpdatesEnabled(false); |
229 QString defaultLocation = QDesktopServices.storageLocation(QDesktopServices.DesktopLocation); | 117 stopButton.setEnabled(false); |
230 QString downloadDirectory = settings.value(QLatin1String("downloadDirectory"), defaultLocation).toString(); | 118 stopButton.hide(); |
231 if (!downloadDirectory.isEmpty()) | 119 tryAgainButton.setEnabled(true); |
232 downloadDirectory += QLatin1Char('/'); | 120 tryAgainButton.show(); |
233 | 121 setUpdatesEnabled(true); |
234 QString defaultFileName = saveFileName(downloadDirectory); | 122 m_reply.abort(); |
235 QString fileName = defaultFileName; | 123 } |
236 if (m_requestFileName) { | 124 |
237 fileName = QFileDialog.getSaveFileName(this, tr("Save File"), defaultFileName); | 125 void tryAgain() |
238 if (fileName.isEmpty()) { | 126 { |
239 m_reply.close(); | 127 if (!tryAgainButton.isEnabled()) |
240 fileNameLabel.setText(tr("Download canceled: %1").arg(QFileInfo(defaultFileName).fileName())); | 128 return; |
241 return; | 129 |
242 } | 130 tryAgainButton.setEnabled(false); |
243 } | 131 tryAgainButton.setVisible(false); |
244 m_output.setFileName(fileName); | 132 stopButton.setEnabled(true); |
245 fileNameLabel.setText(QFileInfo(m_output.fileName()).fileName()); | 133 stopButton.setVisible(true); |
246 if (m_requestFileName) | 134 progressBar.setVisible(true); |
247 downloadReadyRead(); | 135 |
248 } | 136 QNetworkReply r = BrowserApplication.networkAccessManager().get(QNetworkRequest(m_url)); |
249 | 137 if (m_reply) |
250 void init() | 138 m_reply.deleteLater(); |
251 { | 139 if (m_output.exists()) |
252 if (!m_reply) | 140 m_output.remove(); |
253 return; | 141 m_reply = r; |
254 | 142 init(); |
255 // attach to the m_reply | 143 emit statusChanged(); |
256 m_url = m_reply.url(); | 144 } |
257 m_reply.setParent(this); | 145 |
258 connect(m_reply, SIGNAL(readyRead()), this, SLOT(downloadReadyRead())); | 146 void open() |
259 connect(m_reply, SIGNAL(error(QNetworkReply.NetworkError)), | 147 { |
260 this, SLOT(error(QNetworkReply.NetworkError))); | 148 QFileInfo info(m_output); |
261 connect(m_reply, SIGNAL(downloadProgress(qint64, qint64)), | 149 QUrl url = QUrl.fromLocalFile(info.absolutePath()); |
262 this, SLOT(downloadProgress(qint64, qint64))); | 150 QDesktopServices.openUrl(url); |
263 connect(m_reply, SIGNAL(metaDataChanged()), | 151 } |
264 this, SLOT(metaDataChanged())); | 152 |
265 connect(m_reply, SIGNAL(finished()), | 153 void downloadReadyRead() |
266 this, SLOT(finished())); | 154 { |
267 | 155 if (m_requestFileName && m_output.fileName().isEmpty()) |
268 // reset info | 156 return; |
269 downloadInfoLabel.clear(); | 157 if (!m_output.isOpen()) { |
270 progressBar.setValue(0); | 158 // in case someone else has already put a file there |
271 getFileName(); | 159 if (!m_requestFileName) |
272 | 160 getFileName(); |
273 // start timer for the download estimation | 161 if (!m_output.open(QIODevice.WriteOnly)) { |
274 m_downloadTime.start(); | 162 downloadInfoLabel.setText(tr("Error opening save file: %1") |
275 | 163 .arg(m_output.errorString())); |
276 if (m_reply.error() != QNetworkReply.NoError) { | 164 stopButton.click(); |
277 error(m_reply.error()); | 165 emit statusChanged(); |
278 finished(); | 166 return; |
279 } | 167 } |
280 } | 168 emit statusChanged(); |
281 | 169 } |
282 void updateInfoLabel() | 170 if (-1 == m_output.write(m_reply.readAll())) { |
283 { | 171 downloadInfoLabel.setText(tr("Error saving: %1") |
284 if (m_reply.error() == QNetworkReply.NoError) | 172 .arg(m_output.errorString())); |
285 return; | 173 stopButton.click(); |
286 | 174 } |
287 qint64 bytesTotal = progressBar.maximum(); | 175 } |
288 bool running = !downloadedSuccessfully(); | 176 |
289 | 177 void error(QNetworkReply.NetworkError code) |
290 // update info label | 178 { |
291 double speed = m_bytesReceived * 1000.0 / m_downloadTime.elapsed(); | 179 qDebug() << "DownloadItem::error" << m_reply.errorString() << m_url; |
292 double timeRemaining = ((double)(bytesTotal - m_bytesReceived)) / speed; | 180 downloadInfoLabel.setText(tr("Network Error: %1").arg(m_reply.errorString())); |
293 QString timeRemainingString = tr("seconds"); | 181 tryAgainButton.setEnabled(true); |
294 if (timeRemaining > 60) { | 182 tryAgainButton.setVisible(true); |
295 timeRemaining = timeRemaining / 60; | 183 } |
296 timeRemainingString = tr("minutes"); | 184 |
297 } | 185 void downloadProgress(qint64 bytesReceived, qint64 bytesTotal) |
298 timeRemaining = floor(timeRemaining); | 186 { |
299 | 187 m_bytesReceived = bytesReceived; |
300 // When downloading the eta should never be 0 | 188 if (bytesTotal == -1) { |
301 if (timeRemaining == 0) | 189 progressBar.setValue(0); |
302 timeRemaining = 1; | 190 progressBar.setMaximum(0); |
303 | 191 } else { |
304 QString info; | 192 progressBar.setValue(bytesReceived); |
305 if (running) { | 193 progressBar.setMaximum(bytesTotal); |
306 QString remaining; | 194 } |
307 if (bytesTotal != 0) | 195 updateInfoLabel(); |
308 remaining = tr("- %4 %5 remaining") | 196 } |
309 .arg(timeRemaining) | 197 |
310 .arg(timeRemainingString); | 198 void metaDataChanged() |
311 info = QString(tr("%1 of %2 (%3/sec) %4")) | 199 { |
312 .arg(dataString(m_bytesReceived)) | 200 qDebug() << "DownloadItem::metaDataChanged: not handled."; |
313 .arg(bytesTotal == 0 ? tr("?") : dataString(bytesTotal)) | 201 } |
314 .arg(dataString((int)speed)) | 202 |
315 .arg(remaining); | 203 void finished() |
316 } else { | 204 { |
317 if (m_bytesReceived == bytesTotal) | 205 progressBar.hide(); |
318 info = dataString(m_output.size()); | 206 stopButton.setEnabled(false); |
319 else | 207 stopButton.hide(); |
320 info = tr("%1 of %2 - Stopped") | 208 m_output.close(); |
321 .arg(dataString(m_bytesReceived)) | 209 updateInfoLabel(); |
322 .arg(dataString(bytesTotal)); | 210 emit statusChanged(); |
323 } | 211 } |
324 downloadInfoLabel.setText(info); | 212 |
325 } | 213 private: |
326 | 214 |
327 QString dataString(int size) | 215 void getFileName() |
328 { | 216 { |
329 QString unit; | 217 QSettings settings; |
330 if (size < 1024) { | 218 settings.beginGroup(QLatin1String("downloadmanager")); |
331 unit = tr("bytes"); | 219 QString defaultLocation = QDesktopServices.storageLocation(QDesktopServices.DesktopLocation); |
332 } else if (size < 1024*1024) { | 220 QString downloadDirectory = settings.value(QLatin1String("downloadDirectory"), defaultLocation).toString(); |
333 size /= 1024; | 221 if (!downloadDirectory.isEmpty()) |
334 unit = tr("kB"); | 222 downloadDirectory += QLatin1Char('/'); |
335 } else { | 223 |
336 size /= 1024*1024; | 224 QString defaultFileName = saveFileName(downloadDirectory); |
337 unit = tr("MB"); | 225 QString fileName = defaultFileName; |
338 } | 226 if (m_requestFileName) { |
339 return QString(QLatin1String("%1 %2")).arg(size).arg(unit); | 227 fileName = QFileDialog.getSaveFileName(this, tr("Save File"), defaultFileName); |
340 } | 228 if (fileName.isEmpty()) { |
341 | 229 m_reply.close(); |
342 QString saveFileName(const QString &directory); | 230 fileNameLabel.setText(tr("Download canceled: %1").arg(QFileInfo(defaultFileName).fileName())); |
343 { | 231 return; |
344 // Move this function into QNetworkReply to also get file name sent from the server | 232 } |
345 QString path = m_url.path(); | 233 } |
346 QFileInfo info(path); | 234 m_output.setFileName(fileName); |
347 QString baseName = info.completeBaseName(); | 235 fileNameLabel.setText(QFileInfo(m_output.fileName()).fileName()); |
348 QString endName = info.suffix(); | 236 if (m_requestFileName) |
349 | 237 downloadReadyRead(); |
350 if (baseName.isEmpty()) { | 238 } |
351 baseName = QLatin1String("unnamed_download"); | 239 |
352 qDebug() << "DownloadManager:: downloading unknown file:" << m_url; | 240 void init() |
353 } | 241 { |
354 QString name = directory + baseName + QLatin1Char('.') + endName; | 242 if (!m_reply) |
355 if (QFile.exists(name)) { | 243 return; |
356 // already exists, don't overwrite | 244 |
357 int i = 1; | 245 // attach to the m_reply |
358 do { | 246 m_url = m_reply.url(); |
359 name = directory + baseName + QLatin1Char('-') + QString.number(i++) + QLatin1Char('.') + endName; | 247 m_reply.setParent(this); |
360 } while (QFile.exists(name)); | 248 m_reply.readyRead.connect(&this.downloadReadyRead); |
361 } | 249 m_reply.error.connect(&this.error); |
362 return name; | 250 m_reply.downloadProgress.connect(&this.downloadProgress); |
363 } | 251 m_reply.metaDataChanged.connect(&this.metaDataChanged); |
364 | 252 m_reply.finished.connect(&this.finished); |
365 bool m_requestFileName; | 253 |
366 qint64 m_bytesReceived; | 254 // reset info |
367 QTime m_downloadTime; | 255 downloadInfoLabel.clear(); |
368 }; | 256 progressBar.setValue(0); |
369 | 257 getFileName(); |
370 class AutoSaver; | 258 |
371 class DownloadModel; | 259 // start timer for the download estimation |
372 QT_BEGIN_NAMESPACE | 260 m_downloadTime.start(); |
373 class QFileIconProvider; | 261 |
374 QT_END_NAMESPACE | 262 if (m_reply.error() != QNetworkReply.NoError) { |
263 error(m_reply.error()); | |
264 finished(); | |
265 } | |
266 } | |
267 | |
268 void updateInfoLabel() | |
269 { | |
270 if (m_reply.error() == QNetworkReply.NoError) | |
271 return; | |
272 | |
273 qint64 bytesTotal = progressBar.maximum(); | |
274 bool running = !downloadedSuccessfully(); | |
275 | |
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); | |
285 | |
286 // When downloading the eta should never be 0 | |
287 if (timeRemaining == 0) | |
288 timeRemaining = 1; | |
289 | |
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 } | |
313 | |
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 } | |
328 | |
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(); | |
336 | |
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 } | |
351 | |
352 bool m_requestFileName; | |
353 qint64 m_bytesReceived; | |
354 QTime m_downloadTime; | |
355 } | |
356 | |
375 | 357 |
376 class DownloadManager : public QDialog, public Ui_DownloadDialog | 358 class DownloadManager : public QDialog, public Ui_DownloadDialog |
377 { | 359 { |
378 Q_OBJECT | |
379 Q_PROPERTY(RemovePolicy removePolicy READ removePolicy WRITE setRemovePolicy) | |
380 Q_ENUMS(RemovePolicy) | |
381 | 360 |
382 public: | 361 public: |
383 enum RemovePolicy { | 362 |
384 Never, | 363 enum RemovePolicy { |
385 Exit, | 364 Never, |
386 SuccessFullDownload | 365 Exit, |
387 }; | 366 SuccessFullDownload |
388 | 367 }; |
389 /*! | 368 |
390 DownloadManager is a Dialog that contains a list of DownloadItems | 369 /*! |
391 | 370 DownloadManager is a Dialog that contains a list of DownloadItems |
392 It is a basic download manager. It only downloads the file, doesn't do BitTorrent, | 371 |
393 extract zipped files or anything fancy. | 372 It is a basic download manager. It only downloads the file, doesn't do BitTorrent, |
394 */ | 373 extract zipped files or anything fancy. |
395 this(QWidget *parent = null) | 374 */ |
396 : QDialog(parent) | 375 this(QWidget parent = null) : QDialog(parent) |
397 , m_autoSaver(new AutoSaver(this)) | 376 { |
398 , m_manager(BrowserApplication.networkAccessManager()) | 377 m_autoSaver = new AutoSaver(this); |
399 , m_iconProvider(0) | 378 m_manager = BrowserApplication.networkAccessManager(); |
400 , m_removePolicy(Never) | 379 m_iconProvider = 0; |
401 { | 380 m_removePolicy = RemovePolicy.Never; |
402 setupUi(this); | 381 |
403 downloadsView.setShowGrid(false); | 382 setupUi(this); |
404 downloadsView.verticalHeader().hide(); | 383 downloadsView.setShowGrid(false); |
405 downloadsView.horizontalHeader().hide(); | 384 downloadsView.verticalHeader().hide(); |
406 downloadsView.setAlternatingRowColors(true); | 385 downloadsView.horizontalHeader().hide(); |
407 downloadsView.horizontalHeader().setStretchLastSection(true); | 386 downloadsView.setAlternatingRowColors(true); |
408 m_model = new DownloadModel(this); | 387 downloadsView.horizontalHeader().setStretchLastSection(true); |
409 downloadsView.setModel(m_model); | 388 m_model = new DownloadModel(this); |
410 connect(cleanupButton, SIGNAL(clicked()), this, SLOT(cleanup())); | 389 downloadsView.setModel(m_model); |
411 load(); | 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 } | |
424 | |
425 public: | |
426 | |
427 void download(QNetworkRequest request, bool requestFileName = false); | |
428 { | |
429 if (request.url().isEmpty()) | |
430 return; | |
431 handleUnsupportedContent(m_manager.get(request), requestFileName); | |
432 } | |
433 | |
434 | |
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; | |
412 } | 590 } |
413 | 591 |
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; | |
461 QVariant header = reply.header(QNetworkRequest.ContentLengthHeader); | |
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()) | |
522 icon = style().standardIcon(QStyle.SP_FileIcon); | |
523 item.fileIcon.setPixmap(icon.pixmap(48, 48)); | |
524 downloadsView.setRowHeight(row, item.minimumSizeHint().height()); | |
525 | |
526 bool remove = false; | |
527 QWebSettings *globalSettings = QWebSettings.globalSettings(); | |
528 if (!item.downloading() | |
529 && globalSettings.testAttribute(QWebSettings.PrivateBrowsingEnabled)) | |
530 remove = true; | |
531 | |
532 if (item.downloadedSuccessfully() | |
533 && removePolicy() == DownloadManager.SuccessFullDownload) { | |
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); | |
554 QIcon icon = style().standardIcon(QStyle.SP_FileIcon); | |
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 | |
566 DownloadModel.DownloadModel(DownloadManager *downloadManager, QObject *parent) | |
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 | 592 |
617 class DownloadModel : public QAbstractListModel | 593 class DownloadModel : public QAbstractListModel |
618 { | 594 { |
619 friend class DownloadManager; | 595 |
620 Q_OBJECT | |
621 | |
622 public: | 596 public: |
623 DownloadModel(DownloadManager *downloadManager, QObject *parent = 0); | 597 |
624 QVariant data(const QModelIndex &index, int role = Qt.DisplayRole) | 598 this(DownloadManager downloadManager, QObject parent = null) |
625 { | 599 { |
626 if (index.row() < 0 || index.row() >= rowCount(index.parent())) | 600 super(parent); |
627 return QVariant(); | 601 m_downloadManager = downloadManager; |
628 if (role == Qt.ToolTipRole) | 602 } |
629 if (!m_downloadManager.m_downloads.at(index.row()).downloadedSuccessfully()) | 603 |
630 return m_downloadManager.m_downloads.at(index.row()).downloadInfoLabel.text(); | 604 QVariant data(QModelIndex index, int role = Qt.DisplayRole) |
631 return QVariant(); | 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 } | |
613 | |
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; | |
623 | |
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 } | |
636 | |
637 private: | |
638 | |
639 DownloadManager m_downloadManager; | |
632 } | 640 } |
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 } |