src/eric7/WebBrowser/Download/DownloadItem.py

branch
eric7
changeset 9221
bf71ee032bb4
parent 9209
b99e7fd55fd3
child 9413
80c06d472826
equal deleted inserted replaced
9220:e9e7eca7efee 9221:bf71ee032bb4
9 9
10 import enum 10 import enum
11 import os 11 import os
12 import pathlib 12 import pathlib
13 13
14 from PyQt6.QtCore import ( 14 from PyQt6.QtCore import pyqtSlot, pyqtSignal, QTime, QUrl, QStandardPaths, QDateTime
15 pyqtSlot, pyqtSignal, QTime, QUrl, QStandardPaths, QDateTime
16 )
17 from PyQt6.QtGui import QDesktopServices 15 from PyQt6.QtGui import QDesktopServices
18 from PyQt6.QtWidgets import QWidget, QStyle, QDialog 16 from PyQt6.QtWidgets import QWidget, QStyle, QDialog
19 from PyQt6.QtWebEngineCore import QWebEngineDownloadRequest 17 from PyQt6.QtWebEngineCore import QWebEngineDownloadRequest
20 18
21 from EricWidgets import EricFileDialog 19 from EricWidgets import EricFileDialog
32 30
33 class DownloadState(enum.Enum): 31 class DownloadState(enum.Enum):
34 """ 32 """
35 Class implementing the various download states. 33 Class implementing the various download states.
36 """ 34 """
35
37 Downloading = 0 36 Downloading = 0
38 Successful = 1 37 Successful = 1
39 Cancelled = 2 38 Cancelled = 2
40 39
41 40
42 class DownloadItem(QWidget, Ui_DownloadItem): 41 class DownloadItem(QWidget, Ui_DownloadItem):
43 """ 42 """
44 Class implementing a widget controlling a download. 43 Class implementing a widget controlling a download.
45 44
46 @signal statusChanged() emitted upon a status change of a download 45 @signal statusChanged() emitted upon a status change of a download
47 @signal downloadFinished(success) emitted when a download finished 46 @signal downloadFinished(success) emitted when a download finished
48 @signal progress(int, int) emitted to signal the download progress 47 @signal progress(int, int) emitted to signal the download progress
49 """ 48 """
49
50 statusChanged = pyqtSignal() 50 statusChanged = pyqtSignal()
51 downloadFinished = pyqtSignal(bool) 51 downloadFinished = pyqtSignal(bool)
52 progress = pyqtSignal(int, int) 52 progress = pyqtSignal(int, int)
53 53
54 def __init__(self, downloadRequest=None, pageUrl=None, parent=None): 54 def __init__(self, downloadRequest=None, pageUrl=None, parent=None):
55 """ 55 """
56 Constructor 56 Constructor
57 57
58 @param downloadRequest reference to the download object containing the 58 @param downloadRequest reference to the download object containing the
59 download data. 59 download data.
60 @type QWebEngineDownloadRequest 60 @type QWebEngineDownloadRequest
61 @param pageUrl URL of the calling page 61 @param pageUrl URL of the calling page
62 @type QUrl 62 @type QUrl
63 @param parent reference to the parent widget 63 @param parent reference to the parent widget
64 @type QWidget 64 @type QWidget
65 """ 65 """
66 super().__init__(parent) 66 super().__init__(parent)
67 self.setupUi(self) 67 self.setupUi(self)
68 68
69 self.fileIcon.setStyleSheet("background-color: transparent") 69 self.fileIcon.setStyleSheet("background-color: transparent")
70 self.datetimeLabel.setStyleSheet("background-color: transparent") 70 self.datetimeLabel.setStyleSheet("background-color: transparent")
71 self.filenameLabel.setStyleSheet("background-color: transparent") 71 self.filenameLabel.setStyleSheet("background-color: transparent")
72 if ericApp().usesDarkPalette(): 72 if ericApp().usesDarkPalette():
73 self.infoLabel.setStyleSheet( 73 self.infoLabel.setStyleSheet(
74 "color: #c0c0c0; background-color: transparent" 74 "color: #c0c0c0; background-color: transparent"
75 ) # light gray 75 ) # light gray
76 else: 76 else:
77 self.infoLabel.setStyleSheet( 77 self.infoLabel.setStyleSheet(
78 "color: #808080; background-color: transparent" 78 "color: #808080; background-color: transparent"
79 ) # dark gray 79 ) # dark gray
80 80
81 self.progressBar.setMaximum(0) 81 self.progressBar.setMaximum(0)
82 82
83 self.pauseButton.setIcon(UI.PixmapCache.getIcon("pause")) 83 self.pauseButton.setIcon(UI.PixmapCache.getIcon("pause"))
84 self.stopButton.setIcon(UI.PixmapCache.getIcon("stopLoading")) 84 self.stopButton.setIcon(UI.PixmapCache.getIcon("stopLoading"))
85 self.openButton.setIcon(UI.PixmapCache.getIcon("open")) 85 self.openButton.setIcon(UI.PixmapCache.getIcon("open"))
86 self.openButton.setEnabled(False) 86 self.openButton.setEnabled(False)
87 self.openButton.setVisible(False) 87 self.openButton.setVisible(False)
88 88
89 self.__state = DownloadState.Downloading 89 self.__state = DownloadState.Downloading
90 90
91 icon = self.style().standardIcon(QStyle.StandardPixmap.SP_FileIcon) 91 icon = self.style().standardIcon(QStyle.StandardPixmap.SP_FileIcon)
92 self.fileIcon.setPixmap(icon.pixmap(48, 48)) 92 self.fileIcon.setPixmap(icon.pixmap(48, 48))
93 93
94 self.__downloadRequest = downloadRequest 94 self.__downloadRequest = downloadRequest
95 if pageUrl is None: 95 if pageUrl is None:
96 self.__pageUrl = QUrl() 96 self.__pageUrl = QUrl()
97 else: 97 else:
98 self.__pageUrl = pageUrl 98 self.__pageUrl = pageUrl
104 self.__finishedDownloading = False 104 self.__finishedDownloading = False
105 self.__gettingFileName = False 105 self.__gettingFileName = False
106 self.__canceledFileSelect = False 106 self.__canceledFileSelect = False
107 self.__autoOpen = False 107 self.__autoOpen = False
108 self.__downloadedDateTime = QDateTime() 108 self.__downloadedDateTime = QDateTime()
109 109
110 self.__initialize() 110 self.__initialize()
111 111
112 def __initialize(self): 112 def __initialize(self):
113 """ 113 """
114 Private method to initialize the widget. 114 Private method to initialize the widget.
115 """ 115 """
116 if self.__downloadRequest is None: 116 if self.__downloadRequest is None:
117 return 117 return
118 118
119 self.__finishedDownloading = False 119 self.__finishedDownloading = False
120 self.__bytesReceived = 0 120 self.__bytesReceived = 0
121 self.__bytesTotal = -1 121 self.__bytesTotal = -1
122 122
123 # start timer for the download estimation 123 # start timer for the download estimation
124 self.__downloadTime = QTime.currentTime() 124 self.__downloadTime = QTime.currentTime()
125 125
126 # attach to the download item object 126 # attach to the download item object
127 self.__url = self.__downloadRequest.url() 127 self.__url = self.__downloadRequest.url()
128 self.__downloadRequest.receivedBytesChanged.connect( 128 self.__downloadRequest.receivedBytesChanged.connect(self.__downloadProgress)
129 self.__downloadProgress)
130 self.__downloadRequest.isFinishedChanged.connect(self.__finished) 129 self.__downloadRequest.isFinishedChanged.connect(self.__finished)
131 130
132 # reset info 131 # reset info
133 self.datetimeLabel.clear() 132 self.datetimeLabel.clear()
134 self.datetimeLabel.hide() 133 self.datetimeLabel.hide()
135 self.infoLabel.clear() 134 self.infoLabel.clear()
136 self.progressBar.setValue(0) 135 self.progressBar.setValue(0)
137 if ( 136 if (
138 self.__downloadRequest.state() == 137 self.__downloadRequest.state()
139 QWebEngineDownloadRequest.DownloadState.DownloadRequested 138 == QWebEngineDownloadRequest.DownloadState.DownloadRequested
140 ): 139 ):
141 self.__getFileName() 140 self.__getFileName()
142 if not self.__fileName: 141 if not self.__fileName:
143 self.__downloadRequest.cancel() 142 self.__downloadRequest.cancel()
144 else: 143 else:
145 self.__downloadRequest.setDownloadFileName(self.__fileName) 144 self.__downloadRequest.setDownloadFileName(self.__fileName)
146 self.__downloadRequest.accept() 145 self.__downloadRequest.accept()
147 else: 146 else:
148 fileName = self.__downloadRequest.downloadFileName() 147 fileName = self.__downloadRequest.downloadFileName()
149 self.__setFileName(fileName) 148 self.__setFileName(fileName)
150 149
151 def __getFileName(self): 150 def __getFileName(self):
152 """ 151 """
153 Private method to get the file name to save to from the user. 152 Private method to get the file name to save to from the user.
154 """ 153 """
155 if self.__gettingFileName: 154 if self.__gettingFileName:
156 return 155 return
157 156
158 savePage = self.__downloadRequest.isSavePageDownload() 157 savePage = self.__downloadRequest.isSavePageDownload()
159 158
160 documentLocation = QStandardPaths.writableLocation( 159 documentLocation = QStandardPaths.writableLocation(
161 QStandardPaths.StandardLocation.DocumentsLocation) 160 QStandardPaths.StandardLocation.DocumentsLocation
162 downloadDirectory = (
163 WebBrowserWindow.downloadManager().downloadDirectory()
164 ) 161 )
165 162 downloadDirectory = WebBrowserWindow.downloadManager().downloadDirectory()
163
166 if self.__fileName: 164 if self.__fileName:
167 fileName = self.__fileName 165 fileName = self.__fileName
168 originalFileName = self.__originalFileName 166 originalFileName = self.__originalFileName
169 self.__toDownload = True 167 self.__toDownload = True
170 ask = False 168 ask = False
171 else: 169 else:
172 defaultFileName, originalFileName = self.__saveFileName( 170 defaultFileName, originalFileName = self.__saveFileName(
173 documentLocation if savePage else downloadDirectory) 171 documentLocation if savePage else downloadDirectory
172 )
174 fileName = defaultFileName 173 fileName = defaultFileName
175 self.__originalFileName = originalFileName 174 self.__originalFileName = originalFileName
176 ask = True 175 ask = True
177 self.__autoOpen = False 176 self.__autoOpen = False
178 177
179 if not savePage: 178 if not savePage:
180 from .DownloadAskActionDialog import DownloadAskActionDialog 179 from .DownloadAskActionDialog import DownloadAskActionDialog
180
181 url = self.__downloadRequest.url() 181 url = self.__downloadRequest.url()
182 mimetype = Utilities.MimeTypes.mimeType(originalFileName) 182 mimetype = Utilities.MimeTypes.mimeType(originalFileName)
183 dlg = DownloadAskActionDialog( 183 dlg = DownloadAskActionDialog(
184 pathlib.Path(originalFileName).name, 184 pathlib.Path(originalFileName).name,
185 mimetype, 185 mimetype,
186 "{0}://{1}".format(url.scheme(), url.authority()), 186 "{0}://{1}".format(url.scheme(), url.authority()),
187 self) 187 self,
188 188 )
189 if ( 189
190 dlg.exec() == QDialog.DialogCode.Rejected or 190 if dlg.exec() == QDialog.DialogCode.Rejected or dlg.getAction() == "cancel":
191 dlg.getAction() == "cancel"
192 ):
193 self.progressBar.setVisible(False) 191 self.progressBar.setVisible(False)
194 self.on_stopButton_clicked() 192 self.on_stopButton_clicked()
195 self.filenameLabel.setText( 193 self.filenameLabel.setText(
196 self.tr("Download canceled: {0}").format( 194 self.tr("Download canceled: {0}").format(
197 pathlib.Path(defaultFileName).name)) 195 pathlib.Path(defaultFileName).name
196 )
197 )
198 self.__canceledFileSelect = True 198 self.__canceledFileSelect = True
199 self.__setDateTime() 199 self.__setDateTime()
200 return 200 return
201 201
202 if dlg.getAction() == "scan": 202 if dlg.getAction() == "scan":
203 self.__mainWindow.requestVirusTotalScan(url) 203 self.__mainWindow.requestVirusTotalScan(url)
204 204
205 self.progressBar.setVisible(False) 205 self.progressBar.setVisible(False)
206 self.on_stopButton_clicked() 206 self.on_stopButton_clicked()
207 self.filenameLabel.setText( 207 self.filenameLabel.setText(
208 self.tr("VirusTotal scan scheduled: {0}").format( 208 self.tr("VirusTotal scan scheduled: {0}").format(
209 pathlib.Path(defaultFileName).name)) 209 pathlib.Path(defaultFileName).name
210 )
211 )
210 self.__canceledFileSelect = True 212 self.__canceledFileSelect = True
211 return 213 return
212 214
213 self.__autoOpen = dlg.getAction() == "open" 215 self.__autoOpen = dlg.getAction() == "open"
214 216
215 tempLocation = QStandardPaths.writableLocation( 217 tempLocation = QStandardPaths.writableLocation(
216 QStandardPaths.StandardLocation.TempLocation) 218 QStandardPaths.StandardLocation.TempLocation
217 fileName = (
218 tempLocation + '/' +
219 pathlib.Path(fileName).stem
220 ) 219 )
221 220 fileName = tempLocation + "/" + pathlib.Path(fileName).stem
221
222 if ask and not self.__autoOpen: 222 if ask and not self.__autoOpen:
223 self.__gettingFileName = True 223 self.__gettingFileName = True
224 fileName = EricFileDialog.getSaveFileName( 224 fileName = EricFileDialog.getSaveFileName(
225 None, 225 None, self.tr("Save File"), defaultFileName, ""
226 self.tr("Save File"), 226 )
227 defaultFileName,
228 "")
229 self.__gettingFileName = False 227 self.__gettingFileName = False
230 228
231 if not fileName: 229 if not fileName:
232 self.progressBar.setVisible(False) 230 self.progressBar.setVisible(False)
233 self.on_stopButton_clicked() 231 self.on_stopButton_clicked()
234 self.filenameLabel.setText( 232 self.filenameLabel.setText(
235 self.tr("Download canceled: {0}") 233 self.tr("Download canceled: {0}").format(
236 .format(pathlib.Path(defaultFileName).name)) 234 pathlib.Path(defaultFileName).name
235 )
236 )
237 self.__canceledFileSelect = True 237 self.__canceledFileSelect = True
238 self.__setDateTime() 238 self.__setDateTime()
239 return 239 return
240 240
241 self.__setFileName(fileName) 241 self.__setFileName(fileName)
242 242
243 def __setFileName(self, fileName): 243 def __setFileName(self, fileName):
244 """ 244 """
245 Private method to set the file name to save the download into. 245 Private method to set the file name to save the download into.
246 246
247 @param fileName name of the file to save into 247 @param fileName name of the file to save into
248 @type str 248 @type str
249 """ 249 """
250 fpath = pathlib.Path(fileName) 250 fpath = pathlib.Path(fileName)
251 WebBrowserWindow.downloadManager().setDownloadDirectory( 251 WebBrowserWindow.downloadManager().setDownloadDirectory(fpath.parent.resolve())
252 fpath.parent.resolve())
253 self.filenameLabel.setText(fpath.name) 252 self.filenameLabel.setText(fpath.name)
254 253
255 self.__fileName = str(fpath) 254 self.__fileName = str(fpath)
256 255
257 # check file path for saving 256 # check file path for saving
258 saveDirPath = pathlib.Path(self.__fileName).parent() 257 saveDirPath = pathlib.Path(self.__fileName).parent()
259 if not saveDirPath.exists(): 258 if not saveDirPath.exists():
260 saveDirPath.mkdir(parents=True) 259 saveDirPath.mkdir(parents=True)
261 260
262 def __saveFileName(self, directory): 261 def __saveFileName(self, directory):
263 """ 262 """
264 Private method to calculate a name for the file to download. 263 Private method to calculate a name for the file to download.
265 264
266 @param directory name of the directory to store the file into (string) 265 @param directory name of the directory to store the file into (string)
267 @return proposed filename and original filename (string, string) 266 @return proposed filename and original filename (string, string)
268 """ 267 """
269 fpath = pathlib.Path(self.__downloadRequest.downloadFileName()) 268 fpath = pathlib.Path(self.__downloadRequest.downloadFileName())
270 origName = fpath.name 269 origName = fpath.name
271 name = os.path.join(directory, origName) 270 name = os.path.join(directory, origName)
272 return name, origName 271 return name, origName
273 272
274 @pyqtSlot(bool) 273 @pyqtSlot(bool)
275 def on_pauseButton_clicked(self, checked): 274 def on_pauseButton_clicked(self, checked):
276 """ 275 """
277 Private slot to pause the download. 276 Private slot to pause the download.
278 277
279 @param checked flag indicating the state of the button 278 @param checked flag indicating the state of the button
280 @type bool 279 @type bool
281 """ 280 """
282 if checked: 281 if checked:
283 self.__downloadRequest.pause() 282 self.__downloadRequest.pause()
284 else: 283 else:
285 self.__downloadRequest.resume() 284 self.__downloadRequest.resume()
286 285
287 @pyqtSlot() 286 @pyqtSlot()
288 def on_stopButton_clicked(self): 287 def on_stopButton_clicked(self):
289 """ 288 """
290 Private slot to stop the download. 289 Private slot to stop the download.
291 """ 290 """
292 self.cancelDownload() 291 self.cancelDownload()
293 292
294 def cancelDownload(self): 293 def cancelDownload(self):
295 """ 294 """
296 Public slot to stop the download. 295 Public slot to stop the download.
297 """ 296 """
298 self.setUpdatesEnabled(False) 297 self.setUpdatesEnabled(False)
305 self.setUpdatesEnabled(True) 304 self.setUpdatesEnabled(True)
306 self.__state = DownloadState.Cancelled 305 self.__state = DownloadState.Cancelled
307 self.__downloadRequest.cancel() 306 self.__downloadRequest.cancel()
308 self.__setDateTime() 307 self.__setDateTime()
309 self.downloadFinished.emit(False) 308 self.downloadFinished.emit(False)
310 309
311 @pyqtSlot() 310 @pyqtSlot()
312 def on_openButton_clicked(self): 311 def on_openButton_clicked(self):
313 """ 312 """
314 Private slot to open the downloaded file. 313 Private slot to open the downloaded file.
315 """ 314 """
316 self.openFile() 315 self.openFile()
317 316
318 def openFile(self): 317 def openFile(self):
319 """ 318 """
320 Public slot to open the downloaded file. 319 Public slot to open the downloaded file.
321 """ 320 """
322 url = QUrl.fromLocalFile(pathlib.Path(self.__fileName).resolve()) 321 url = QUrl.fromLocalFile(pathlib.Path(self.__fileName).resolve())
323 QDesktopServices.openUrl(url) 322 QDesktopServices.openUrl(url)
324 323
325 def openFolder(self): 324 def openFolder(self):
326 """ 325 """
327 Public slot to open the folder containing the downloaded file. 326 Public slot to open the folder containing the downloaded file.
328 """ 327 """
329 url = QUrl.fromLocalFile(pathlib.Path(self.__fileName).resolve()) 328 url = QUrl.fromLocalFile(pathlib.Path(self.__fileName).resolve())
330 QDesktopServices.openUrl(url) 329 QDesktopServices.openUrl(url)
331 330
332 @pyqtSlot() 331 @pyqtSlot()
333 def __downloadProgress(self): 332 def __downloadProgress(self):
334 """ 333 """
335 Private slot to show the download progress. 334 Private slot to show the download progress.
336 """ 335 """
341 if self.__bytesTotal > 0: 340 if self.__bytesTotal > 0:
342 currentValue = self.__bytesReceived * 100 // self.__bytesTotal 341 currentValue = self.__bytesReceived * 100 // self.__bytesTotal
343 totalValue = 100 342 totalValue = 100
344 self.progressBar.setValue(currentValue) 343 self.progressBar.setValue(currentValue)
345 self.progressBar.setMaximum(totalValue) 344 self.progressBar.setMaximum(totalValue)
346 345
347 self.progress.emit(currentValue, totalValue) 346 self.progress.emit(currentValue, totalValue)
348 self.__updateInfoLabel() 347 self.__updateInfoLabel()
349 348
350 def downloadProgress(self): 349 def downloadProgress(self):
351 """ 350 """
352 Public method to get the download progress. 351 Public method to get the download progress.
353 352
354 @return current download progress 353 @return current download progress
355 @rtype int 354 @rtype int
356 """ 355 """
357 return self.progressBar.value() 356 return self.progressBar.value()
358 357
359 def bytesTotal(self): 358 def bytesTotal(self):
360 """ 359 """
361 Public method to get the total number of bytes of the download. 360 Public method to get the total number of bytes of the download.
362 361
363 @return total number of bytes (integer) 362 @return total number of bytes (integer)
364 """ 363 """
365 if self.__bytesTotal == -1: 364 if self.__bytesTotal == -1:
366 self.__bytesTotal = self.__downloadRequest.totalBytes() 365 self.__bytesTotal = self.__downloadRequest.totalBytes()
367 return self.__bytesTotal 366 return self.__bytesTotal
368 367
369 def bytesReceived(self): 368 def bytesReceived(self):
370 """ 369 """
371 Public method to get the number of bytes received. 370 Public method to get the number of bytes received.
372 371
373 @return number of bytes received (integer) 372 @return number of bytes received (integer)
374 """ 373 """
375 return self.__bytesReceived 374 return self.__bytesReceived
376 375
377 def remainingTime(self): 376 def remainingTime(self):
378 """ 377 """
379 Public method to get an estimation for the remaining time. 378 Public method to get an estimation for the remaining time.
380 379
381 @return estimation for the remaining time (float) 380 @return estimation for the remaining time (float)
382 """ 381 """
383 if not self.downloading(): 382 if not self.downloading():
384 return -1.0 383 return -1.0
385 384
386 if self.bytesTotal() == -1: 385 if self.bytesTotal() == -1:
387 return -1.0 386 return -1.0
388 387
389 cSpeed = self.currentSpeed() 388 cSpeed = self.currentSpeed()
390 timeRemaining = ( 389 timeRemaining = (
391 (self.bytesTotal() - self.bytesReceived()) / cSpeed 390 (self.bytesTotal() - self.bytesReceived()) / cSpeed if cSpeed != 0 else 1
392 if cSpeed != 0 else
393 1
394 ) 391 )
395 392
396 # ETA should never be 0 393 # ETA should never be 0
397 if timeRemaining == 0: 394 if timeRemaining == 0:
398 timeRemaining = 1 395 timeRemaining = 1
399 396
400 return timeRemaining 397 return timeRemaining
401 398
402 def currentSpeed(self): 399 def currentSpeed(self):
403 """ 400 """
404 Public method to get an estimation for the download speed. 401 Public method to get an estimation for the download speed.
405 402
406 @return estimation for the download speed (float) 403 @return estimation for the download speed (float)
407 """ 404 """
408 if not self.downloading(): 405 if not self.downloading():
409 return -1.0 406 return -1.0
410 407
411 return ( 408 return (
412 self.__bytesReceived * 1000.0 / 409 self.__bytesReceived
413 self.__downloadTime.msecsTo(QTime.currentTime()) 410 * 1000.0
411 / self.__downloadTime.msecsTo(QTime.currentTime())
414 ) 412 )
415 413
416 def __updateInfoLabel(self): 414 def __updateInfoLabel(self):
417 """ 415 """
418 Private method to update the info label. 416 Private method to update the info label.
419 """ 417 """
420 bytesTotal = self.bytesTotal() 418 bytesTotal = self.bytesTotal()
421 running = not self.downloadedSuccessfully() 419 running = not self.downloadedSuccessfully()
422 420
423 speed = self.currentSpeed() 421 speed = self.currentSpeed()
424 timeRemaining = self.remainingTime() 422 timeRemaining = self.remainingTime()
425 423
426 info = "" 424 info = ""
427 if running: 425 if running:
428 remaining = "" 426 remaining = ""
429 427
430 if bytesTotal > 0: 428 if bytesTotal > 0:
431 remaining = timeString(timeRemaining) 429 remaining = timeString(timeRemaining)
432 430
433 info = self.tr( 431 info = self.tr("{0} of {1} ({2}/sec) {3}").format(
434 "{0} of {1} ({2}/sec) {3}"
435 ).format(
436 dataString(self.__bytesReceived), 432 dataString(self.__bytesReceived),
437 bytesTotal == -1 and self.tr("?") or 433 bytesTotal == -1 and self.tr("?") or dataString(bytesTotal),
438 dataString(bytesTotal),
439 speedString(speed), 434 speedString(speed),
440 remaining 435 remaining,
441 ) 436 )
442 else: 437 else:
443 if bytesTotal in (self.__bytesReceived, -1): 438 if bytesTotal in (self.__bytesReceived, -1):
444 info = self.tr( 439 info = self.tr("{0} downloaded").format(
445 "{0} downloaded" 440 dataString(self.__bytesReceived)
446 ).format(dataString(self.__bytesReceived)) 441 )
447 else: 442 else:
448 info = self.tr( 443 info = self.tr("{0} of {1} - Stopped").format(
449 "{0} of {1} - Stopped" 444 dataString(self.__bytesReceived), dataString(bytesTotal)
450 ).format(dataString(self.__bytesReceived), 445 )
451 dataString(bytesTotal))
452 self.infoLabel.setText(info) 446 self.infoLabel.setText(info)
453 447
454 def downloading(self): 448 def downloading(self):
455 """ 449 """
456 Public method to determine, if a download is in progress. 450 Public method to determine, if a download is in progress.
457 451
458 @return flag indicating a download is in progress (boolean) 452 @return flag indicating a download is in progress (boolean)
459 """ 453 """
460 return self.__state == DownloadState.Downloading 454 return self.__state == DownloadState.Downloading
461 455
462 def downloadedSuccessfully(self): 456 def downloadedSuccessfully(self):
463 """ 457 """
464 Public method to check for a successful download. 458 Public method to check for a successful download.
465 459
466 @return flag indicating a successful download (boolean) 460 @return flag indicating a successful download (boolean)
467 """ 461 """
468 return self.__state == DownloadState.Successful 462 return self.__state == DownloadState.Successful
469 463
470 def downloadCanceled(self): 464 def downloadCanceled(self):
471 """ 465 """
472 Public method to check, if the download was cancelled. 466 Public method to check, if the download was cancelled.
473 467
474 @return flag indicating a canceled download (boolean) 468 @return flag indicating a canceled download (boolean)
475 """ 469 """
476 return self.__state == DownloadState.Cancelled 470 return self.__state == DownloadState.Cancelled
477 471
478 def __finished(self): 472 def __finished(self):
479 """ 473 """
480 Private slot to handle the download finished. 474 Private slot to handle the download finished.
481 """ 475 """
482 self.__finishedDownloading = True 476 self.__finishedDownloading = True
483 477
484 noError = (self.__downloadRequest.state() == 478 noError = (
485 QWebEngineDownloadRequest.DownloadState.DownloadCompleted) 479 self.__downloadRequest.state()
486 480 == QWebEngineDownloadRequest.DownloadState.DownloadCompleted
481 )
482
487 self.progressBar.setVisible(False) 483 self.progressBar.setVisible(False)
488 self.pauseButton.setEnabled(False) 484 self.pauseButton.setEnabled(False)
489 self.pauseButton.setVisible(False) 485 self.pauseButton.setVisible(False)
490 self.stopButton.setEnabled(False) 486 self.stopButton.setEnabled(False)
491 self.stopButton.setVisible(False) 487 self.stopButton.setVisible(False)
492 self.openButton.setEnabled(noError) 488 self.openButton.setEnabled(noError)
493 self.openButton.setVisible(noError) 489 self.openButton.setVisible(noError)
494 self.__state = DownloadState.Successful 490 self.__state = DownloadState.Successful
495 self.__updateInfoLabel() 491 self.__updateInfoLabel()
496 self.__setDateTime() 492 self.__setDateTime()
497 493
498 self.__adjustSize() 494 self.__adjustSize()
499 495
500 self.statusChanged.emit() 496 self.statusChanged.emit()
501 self.downloadFinished.emit(True) 497 self.downloadFinished.emit(True)
502 498
503 if self.__autoOpen: 499 if self.__autoOpen:
504 self.openFile() 500 self.openFile()
505 501
506 def canceledFileSelect(self): 502 def canceledFileSelect(self):
507 """ 503 """
508 Public method to check, if the user canceled the file selection. 504 Public method to check, if the user canceled the file selection.
509 505
510 @return flag indicating cancellation (boolean) 506 @return flag indicating cancellation (boolean)
511 """ 507 """
512 return self.__canceledFileSelect 508 return self.__canceledFileSelect
513 509
514 def setIcon(self, icon): 510 def setIcon(self, icon):
515 """ 511 """
516 Public method to set the download icon. 512 Public method to set the download icon.
517 513
518 @param icon reference to the icon to be set (QIcon) 514 @param icon reference to the icon to be set (QIcon)
519 """ 515 """
520 self.fileIcon.setPixmap(icon.pixmap(48, 48)) 516 self.fileIcon.setPixmap(icon.pixmap(48, 48))
521 517
522 def fileName(self): 518 def fileName(self):
523 """ 519 """
524 Public method to get the name of the output file. 520 Public method to get the name of the output file.
525 521
526 @return name of the output file (string) 522 @return name of the output file (string)
527 """ 523 """
528 return self.__fileName 524 return self.__fileName
529 525
530 def absoluteFilePath(self): 526 def absoluteFilePath(self):
531 """ 527 """
532 Public method to get the absolute path of the output file. 528 Public method to get the absolute path of the output file.
533 529
534 @return absolute path of the output file (string) 530 @return absolute path of the output file (string)
535 """ 531 """
536 return pathlib.Path(self.__fileName).resolve() 532 return pathlib.Path(self.__fileName).resolve()
537 533
538 def getData(self): 534 def getData(self):
539 """ 535 """
540 Public method to get the relevant download data. 536 Public method to get the relevant download data.
541 537
542 @return dictionary containing the URL, save location, done flag, 538 @return dictionary containing the URL, save location, done flag,
543 the URL of the related web page and the date and time of the 539 the URL of the related web page and the date and time of the
544 download 540 download
545 @rtype dict of {"URL": QUrl, "Location": str, "Done": bool, 541 @rtype dict of {"URL": QUrl, "Location": str, "Done": bool,
546 "PageURL": QUrl, "Downloaded": QDateTime} 542 "PageURL": QUrl, "Downloaded": QDateTime}
548 return { 544 return {
549 "URL": self.__url, 545 "URL": self.__url,
550 "Location": self.__fileName, 546 "Location": self.__fileName,
551 "Done": self.downloadedSuccessfully(), 547 "Done": self.downloadedSuccessfully(),
552 "PageURL": self.__pageUrl, 548 "PageURL": self.__pageUrl,
553 "Downloaded": self.__downloadedDateTime 549 "Downloaded": self.__downloadedDateTime,
554 } 550 }
555 551
556 def setData(self, data): 552 def setData(self, data):
557 """ 553 """
558 Public method to set the relevant download data. 554 Public method to set the relevant download data.
559 555
560 @param data dictionary containing the URL, save location, done flag, 556 @param data dictionary containing the URL, save location, done flag,
561 the URL of the related web page and the date and time of the 557 the URL of the related web page and the date and time of the
562 download 558 download
563 @type dict of {"URL": QUrl, "Location": str, "Done": bool, 559 @type dict of {"URL": QUrl, "Location": str, "Done": bool,
564 "PageURL": QUrl, "Downloaded": QDateTime} 560 "PageURL": QUrl, "Downloaded": QDateTime}
565 """ 561 """
566 self.__url = data["URL"] 562 self.__url = data["URL"]
567 self.__fileName = data["Location"] 563 self.__fileName = data["Location"]
568 self.__pageUrl = data["PageURL"] 564 self.__pageUrl = data["PageURL"]
569 565
570 self.filenameLabel.setText(pathlib.Path(self.__fileName).name) 566 self.filenameLabel.setText(pathlib.Path(self.__fileName).name)
571 self.infoLabel.setText(self.__fileName) 567 self.infoLabel.setText(self.__fileName)
572 568
573 try: 569 try:
574 self.__setDateTime(data["Downloaded"]) 570 self.__setDateTime(data["Downloaded"])
575 except KeyError: 571 except KeyError:
576 self.__setDateTime(QDateTime()) 572 self.__setDateTime(QDateTime())
577 573
578 self.pauseButton.setEnabled(False) 574 self.pauseButton.setEnabled(False)
579 self.pauseButton.setVisible(False) 575 self.pauseButton.setVisible(False)
580 self.stopButton.setEnabled(False) 576 self.stopButton.setEnabled(False)
581 self.stopButton.setVisible(False) 577 self.stopButton.setVisible(False)
582 self.openButton.setEnabled(data["Done"]) 578 self.openButton.setEnabled(data["Done"])
584 if data["Done"]: 580 if data["Done"]:
585 self.__state = DownloadState.Successful 581 self.__state = DownloadState.Successful
586 else: 582 else:
587 self.__state = DownloadState.Cancelled 583 self.__state = DownloadState.Cancelled
588 self.progressBar.setVisible(False) 584 self.progressBar.setVisible(False)
589 585
590 self.__adjustSize() 586 self.__adjustSize()
591 587
592 def getInfoData(self): 588 def getInfoData(self):
593 """ 589 """
594 Public method to get the text of the info label. 590 Public method to get the text of the info label.
595 591
596 @return text of the info label (string) 592 @return text of the info label (string)
597 """ 593 """
598 return self.infoLabel.text() 594 return self.infoLabel.text()
599 595
600 def getPageUrl(self): 596 def getPageUrl(self):
601 """ 597 """
602 Public method to get the URL of the download page. 598 Public method to get the URL of the download page.
603 599
604 @return URL of the download page (QUrl) 600 @return URL of the download page (QUrl)
605 """ 601 """
606 return self.__pageUrl 602 return self.__pageUrl
607 603
608 def __adjustSize(self): 604 def __adjustSize(self):
609 """ 605 """
610 Private method to adjust the size of the download item. 606 Private method to adjust the size of the download item.
611 """ 607 """
612 self.ensurePolished() 608 self.ensurePolished()
613 609
614 msh = self.minimumSizeHint() 610 msh = self.minimumSizeHint()
615 self.resize(max(self.width(), msh.width()), msh.height()) 611 self.resize(max(self.width(), msh.width()), msh.height())
616 612
617 def __setDateTime(self, dateTime=None): 613 def __setDateTime(self, dateTime=None):
618 """ 614 """
619 Private method to set the download date and time. 615 Private method to set the download date and time.
620 616
621 @param dateTime date and time to be set 617 @param dateTime date and time to be set
622 @type QDateTime 618 @type QDateTime
623 """ 619 """
624 if dateTime is None: 620 if dateTime is None:
625 self.__downloadedDateTime = QDateTime.currentDateTime() 621 self.__downloadedDateTime = QDateTime.currentDateTime()

eric ide

mercurial