|
1 # -*- coding: utf-8 -*- |
|
2 |
|
3 # Copyright (c) 2010 - 2022 Detlev Offenbach <detlev@die-offenbachs.de> |
|
4 # |
|
5 |
|
6 """ |
|
7 Module implementing the download manager class. |
|
8 """ |
|
9 |
|
10 from PyQt6.QtCore import ( |
|
11 pyqtSlot, pyqtSignal, Qt, QModelIndex, QFileInfo, QUrl, QBasicTimer |
|
12 ) |
|
13 from PyQt6.QtGui import QCursor, QKeySequence, QShortcut |
|
14 from PyQt6.QtWidgets import ( |
|
15 QDialog, QStyle, QFileIconProvider, QMenu, QApplication |
|
16 ) |
|
17 |
|
18 from EricWidgets import EricMessageBox |
|
19 from EricWidgets.EricApplication import ericApp |
|
20 |
|
21 from .Ui_DownloadManager import Ui_DownloadManager |
|
22 |
|
23 from .DownloadModel import DownloadModel |
|
24 from .DownloadUtilities import speedString, timeString |
|
25 |
|
26 from WebBrowser.WebBrowserWindow import WebBrowserWindow |
|
27 |
|
28 from Utilities.AutoSaver import AutoSaver |
|
29 import UI.PixmapCache |
|
30 import Preferences |
|
31 import Globals |
|
32 |
|
33 |
|
34 class DownloadManager(QDialog, Ui_DownloadManager): |
|
35 """ |
|
36 Class implementing the download manager. |
|
37 |
|
38 @signal downloadsCountChanged() emitted to indicate a change of the |
|
39 count of download items |
|
40 """ |
|
41 RemoveNever = 0 |
|
42 RemoveExit = 1 |
|
43 RemoveSuccessFullDownload = 2 |
|
44 |
|
45 UpdateTimerTimeout = 1000 |
|
46 |
|
47 downloadsCountChanged = pyqtSignal() |
|
48 |
|
49 def __init__(self, parent=None): |
|
50 """ |
|
51 Constructor |
|
52 |
|
53 @param parent reference to the parent widget (QWidget) |
|
54 """ |
|
55 super().__init__(parent) |
|
56 self.setupUi(self) |
|
57 self.setWindowFlags(Qt.WindowType.Window) |
|
58 |
|
59 self.__winTaskbarButton = None |
|
60 |
|
61 self.__saveTimer = AutoSaver(self, self.save) |
|
62 |
|
63 self.__model = DownloadModel(self) |
|
64 self.__manager = WebBrowserWindow.networkManager() |
|
65 |
|
66 self.__iconProvider = None |
|
67 self.__downloads = [] |
|
68 self.__downloadDirectory = "" |
|
69 self.__loaded = False |
|
70 |
|
71 self.__rowHeightMultiplier = 1.1 |
|
72 |
|
73 self.setDownloadDirectory(Preferences.getUI("DownloadPath")) |
|
74 |
|
75 self.downloadsView.setShowGrid(False) |
|
76 self.downloadsView.verticalHeader().hide() |
|
77 self.downloadsView.horizontalHeader().hide() |
|
78 self.downloadsView.setAlternatingRowColors(True) |
|
79 self.downloadsView.horizontalHeader().setStretchLastSection(True) |
|
80 self.downloadsView.setModel(self.__model) |
|
81 self.downloadsView.setContextMenuPolicy( |
|
82 Qt.ContextMenuPolicy.CustomContextMenu) |
|
83 self.downloadsView.customContextMenuRequested.connect( |
|
84 self.__customContextMenuRequested) |
|
85 |
|
86 self.__clearShortcut = QShortcut(QKeySequence("Ctrl+L"), self) |
|
87 self.__clearShortcut.activated.connect(self.on_cleanupButton_clicked) |
|
88 |
|
89 self.__load() |
|
90 |
|
91 self.__updateTimer = QBasicTimer() |
|
92 |
|
93 def __customContextMenuRequested(self, pos): |
|
94 """ |
|
95 Private slot to handle the context menu request for the bookmarks tree. |
|
96 |
|
97 @param pos position the context menu was requested (QPoint) |
|
98 """ |
|
99 menu = QMenu() |
|
100 |
|
101 selectedRowsCount = len( |
|
102 self.downloadsView.selectionModel().selectedRows()) |
|
103 |
|
104 if selectedRowsCount == 1: |
|
105 row = self.downloadsView.selectionModel().selectedRows()[0].row() |
|
106 itm = self.__downloads[row] |
|
107 if itm.downloadedSuccessfully(): |
|
108 menu.addAction( |
|
109 UI.PixmapCache.getIcon("open"), |
|
110 self.tr("Open"), self.__contextMenuOpen) |
|
111 elif itm.downloading(): |
|
112 menu.addAction( |
|
113 UI.PixmapCache.getIcon("stopLoading"), |
|
114 self.tr("Cancel"), self.__contextMenuCancel) |
|
115 menu.addSeparator() |
|
116 menu.addAction( |
|
117 self.tr("Open Containing Folder"), |
|
118 self.__contextMenuOpenFolder) |
|
119 menu.addSeparator() |
|
120 menu.addAction( |
|
121 self.tr("Go to Download Page"), |
|
122 self.__contextMenuGotoPage) |
|
123 menu.addAction( |
|
124 self.tr("Copy Download Link"), |
|
125 self.__contextMenuCopyLink) |
|
126 menu.addSeparator() |
|
127 menu.addAction(self.tr("Select All"), self.__contextMenuSelectAll) |
|
128 if ( |
|
129 selectedRowsCount > 1 or |
|
130 (selectedRowsCount == 1 and |
|
131 not self.__downloads[ |
|
132 self.downloadsView.selectionModel().selectedRows()[0].row()] |
|
133 .downloading()) |
|
134 ): |
|
135 menu.addSeparator() |
|
136 menu.addAction( |
|
137 self.tr("Remove From List"), |
|
138 self.__contextMenuRemoveSelected) |
|
139 |
|
140 menu.exec(QCursor.pos()) |
|
141 |
|
142 def shutdown(self): |
|
143 """ |
|
144 Public method to stop the download manager. |
|
145 """ |
|
146 self.save() |
|
147 self.close() |
|
148 |
|
149 def activeDownloadsCount(self): |
|
150 """ |
|
151 Public method to get the number of active downloads. |
|
152 |
|
153 @return number of active downloads (integer) |
|
154 """ |
|
155 count = 0 |
|
156 |
|
157 for download in self.__downloads: |
|
158 if download.downloading(): |
|
159 count += 1 |
|
160 return count |
|
161 |
|
162 def allowQuit(self): |
|
163 """ |
|
164 Public method to check, if it is ok to quit. |
|
165 |
|
166 @return flag indicating allowance to quit (boolean) |
|
167 """ |
|
168 if self.activeDownloadsCount() > 0: |
|
169 res = EricMessageBox.yesNo( |
|
170 self, |
|
171 self.tr(""), |
|
172 self.tr("""There are %n downloads in progress.\n""" |
|
173 """Do you want to quit anyway?""", "", |
|
174 self.activeDownloadsCount()), |
|
175 icon=EricMessageBox.Warning) |
|
176 if not res: |
|
177 self.show() |
|
178 return False |
|
179 |
|
180 self.close() |
|
181 return True |
|
182 |
|
183 def __testWebBrowserView(self, view, url): |
|
184 """ |
|
185 Private method to test a web browser view against an URL. |
|
186 |
|
187 @param view reference to the web browser view to be tested |
|
188 @type WebBrowserView |
|
189 @param url URL to test against |
|
190 @type QUrl |
|
191 @return flag indicating, that the view is the one for the URL |
|
192 @rtype bool |
|
193 """ |
|
194 if view.tabWidget().count() < 2: |
|
195 return False |
|
196 |
|
197 page = view.page() |
|
198 if page.history().count() != 0: |
|
199 return False |
|
200 |
|
201 if ( |
|
202 not page.url().isEmpty() and |
|
203 page.url().host() == url.host() |
|
204 ): |
|
205 return True |
|
206 |
|
207 requestedUrl = page.requestedUrl() |
|
208 if requestedUrl.isEmpty(): |
|
209 requestedUrl = QUrl(view.tabWidget().urlBarForView(view).text()) |
|
210 return requestedUrl.isEmpty() or requestedUrl.host() == url.host() |
|
211 |
|
212 def __closeDownloadTab(self, url): |
|
213 """ |
|
214 Private method to close an empty tab, that was opened only for loading |
|
215 the download URL. |
|
216 |
|
217 @param url download URL |
|
218 @type QUrl |
|
219 """ |
|
220 if self.__testWebBrowserView( |
|
221 WebBrowserWindow.getWindow().currentBrowser(), url): |
|
222 WebBrowserWindow.getWindow().closeCurrentBrowser() |
|
223 return |
|
224 |
|
225 for window in WebBrowserWindow.mainWindows(): |
|
226 for browser in window.browsers(): |
|
227 if self.__testWebBrowserView(browser, url): |
|
228 window.closeBrowser(browser) |
|
229 return |
|
230 |
|
231 def download(self, downloadRequest): |
|
232 """ |
|
233 Public method to download a file. |
|
234 |
|
235 @param downloadRequest reference to the download object containing the |
|
236 download data. |
|
237 @type QWebEngineDownloadRequest |
|
238 """ |
|
239 url = downloadRequest.url() |
|
240 if url.isEmpty(): |
|
241 return |
|
242 |
|
243 self.__closeDownloadTab(url) |
|
244 |
|
245 # Safe Browsing |
|
246 from WebBrowser.SafeBrowsing.SafeBrowsingManager import ( |
|
247 SafeBrowsingManager |
|
248 ) |
|
249 if SafeBrowsingManager.isEnabled(): |
|
250 threatLists = ( |
|
251 WebBrowserWindow.safeBrowsingManager().lookupUrl(url)[0] |
|
252 ) |
|
253 if threatLists: |
|
254 threatMessages = ( |
|
255 WebBrowserWindow.safeBrowsingManager() |
|
256 .getThreatMessages(threatLists) |
|
257 ) |
|
258 res = EricMessageBox.warning( |
|
259 WebBrowserWindow.getWindow(), |
|
260 self.tr("Suspicuous URL detected"), |
|
261 self.tr("<p>The URL <b>{0}</b> was found in the Safe" |
|
262 " Browsing database.</p>{1}").format( |
|
263 url.toString(), "".join(threatMessages)), |
|
264 EricMessageBox.Abort | EricMessageBox.Ignore, |
|
265 EricMessageBox.Abort) |
|
266 if res == EricMessageBox.Abort: |
|
267 downloadRequest.cancel() |
|
268 return |
|
269 |
|
270 window = WebBrowserWindow.getWindow() |
|
271 pageUrl = window.currentBrowser().url() if window else QUrl() |
|
272 from .DownloadItem import DownloadItem |
|
273 itm = DownloadItem(downloadRequest=downloadRequest, pageUrl=pageUrl, |
|
274 parent=self) |
|
275 self.__addItem(itm) |
|
276 |
|
277 if Preferences.getWebBrowser("DownloadManagerAutoOpen"): |
|
278 self.show() |
|
279 else: |
|
280 self.__startUpdateTimer() |
|
281 |
|
282 def show(self): |
|
283 """ |
|
284 Public slot to show the download manager dialog. |
|
285 """ |
|
286 self.__startUpdateTimer() |
|
287 |
|
288 super().show() |
|
289 self.activateWindow() |
|
290 self.raise_() |
|
291 |
|
292 def __addItem(self, itm, append=False): |
|
293 """ |
|
294 Private method to add a download to the list of downloads. |
|
295 |
|
296 @param itm reference to the download item |
|
297 @type DownloadItem |
|
298 @param append flag indicating to append the item |
|
299 @type bool |
|
300 """ |
|
301 itm.statusChanged.connect(lambda: self.__updateRow(itm)) |
|
302 itm.downloadFinished.connect(self.__finished) |
|
303 |
|
304 # insert at top of window |
|
305 row = self.downloadsCount() if append else 0 |
|
306 self.__model.beginInsertRows(QModelIndex(), row, row) |
|
307 if append: |
|
308 self.__downloads.append(itm) |
|
309 else: |
|
310 self.__downloads.insert(0, itm) |
|
311 self.__model.endInsertRows() |
|
312 |
|
313 self.downloadsView.setIndexWidget(self.__model.index(row, 0), itm) |
|
314 icon = self.style().standardIcon(QStyle.StandardPixmap.SP_FileIcon) |
|
315 itm.setIcon(icon) |
|
316 self.downloadsView.setRowHeight( |
|
317 row, int(itm.sizeHint().height() * self.__rowHeightMultiplier)) |
|
318 # just in case the download finished before the constructor returned |
|
319 self.__updateRow(itm) |
|
320 self.changeOccurred() |
|
321 |
|
322 self.downloadsCountChanged.emit() |
|
323 |
|
324 def __updateRow(self, itm): |
|
325 """ |
|
326 Private slot to update a download item. |
|
327 |
|
328 @param itm reference to the download item |
|
329 @type DownloadItem |
|
330 """ |
|
331 if itm not in self.__downloads: |
|
332 return |
|
333 |
|
334 row = self.__downloads.index(itm) |
|
335 |
|
336 if self.__iconProvider is None: |
|
337 self.__iconProvider = QFileIconProvider() |
|
338 |
|
339 icon = self.__iconProvider.icon(QFileInfo(itm.fileName())) |
|
340 if icon.isNull(): |
|
341 icon = self.style().standardIcon(QStyle.StandardPixmap.SP_FileIcon) |
|
342 itm.setIcon(icon) |
|
343 |
|
344 self.downloadsView.setRowHeight( |
|
345 row, |
|
346 int(itm.minimumSizeHint().height() * self.__rowHeightMultiplier)) |
|
347 |
|
348 remove = False |
|
349 |
|
350 if ( |
|
351 itm.downloadedSuccessfully() and |
|
352 self.removePolicy() == DownloadManager.RemoveSuccessFullDownload |
|
353 ): |
|
354 remove = True |
|
355 |
|
356 if remove: |
|
357 self.__model.removeRow(row) |
|
358 |
|
359 self.cleanupButton.setEnabled( |
|
360 (self.downloadsCount() - self.activeDownloadsCount()) > 0) |
|
361 |
|
362 # record the change |
|
363 self.changeOccurred() |
|
364 |
|
365 def removePolicy(self): |
|
366 """ |
|
367 Public method to get the remove policy. |
|
368 |
|
369 @return remove policy (integer) |
|
370 """ |
|
371 return Preferences.getWebBrowser("DownloadManagerRemovePolicy") |
|
372 |
|
373 def setRemovePolicy(self, policy): |
|
374 """ |
|
375 Public method to set the remove policy. |
|
376 |
|
377 @param policy policy to be set |
|
378 (DownloadManager.RemoveExit, DownloadManager.RemoveNever, |
|
379 DownloadManager.RemoveSuccessFullDownload) |
|
380 """ |
|
381 if policy in (DownloadManager.RemoveExit, |
|
382 DownloadManager.RemoveNever, |
|
383 DownloadManager.RemoveSuccessFullDownload): |
|
384 |
|
385 if policy == self.removePolicy(): |
|
386 return |
|
387 |
|
388 Preferences.setWebBrowser("DownloadManagerRemovePolicy", |
|
389 self.policy) |
|
390 |
|
391 def save(self): |
|
392 """ |
|
393 Public method to save the download settings. |
|
394 """ |
|
395 if not self.__loaded: |
|
396 return |
|
397 |
|
398 Preferences.setWebBrowser("DownloadManagerSize", self.size()) |
|
399 Preferences.setWebBrowser("DownloadManagerPosition", self.pos()) |
|
400 if self.removePolicy() == DownloadManager.RemoveExit: |
|
401 return |
|
402 |
|
403 from WebBrowser.WebBrowserWindow import WebBrowserWindow |
|
404 if WebBrowserWindow.isPrivate(): |
|
405 return |
|
406 |
|
407 downloads = [] |
|
408 for download in self.__downloads: |
|
409 downloads.append(download.getData()) |
|
410 Preferences.setWebBrowser("DownloadManagerDownloads", downloads) |
|
411 |
|
412 def __load(self): |
|
413 """ |
|
414 Private method to load the download settings. |
|
415 """ |
|
416 if self.__loaded: |
|
417 return |
|
418 |
|
419 size = Preferences.getWebBrowser("DownloadManagerSize") |
|
420 if size.isValid(): |
|
421 self.resize(size) |
|
422 pos = Preferences.getWebBrowser("DownloadManagerPosition") |
|
423 self.move(pos) |
|
424 |
|
425 from WebBrowser.WebBrowserWindow import WebBrowserWindow |
|
426 if not WebBrowserWindow.isPrivate(): |
|
427 downloads = Preferences.getWebBrowser("DownloadManagerDownloads") |
|
428 for download in downloads: |
|
429 if ( |
|
430 not download["URL"].isEmpty() and |
|
431 bool(download["Location"]) |
|
432 ): |
|
433 from .DownloadItem import DownloadItem |
|
434 itm = DownloadItem(parent=self) |
|
435 itm.setData(download) |
|
436 self.__addItem(itm, append=True) |
|
437 self.cleanupButton.setEnabled( |
|
438 (self.downloadsCount() - self.activeDownloadsCount()) > 0) |
|
439 |
|
440 self.__loaded = True |
|
441 |
|
442 self.downloadsCountChanged.emit() |
|
443 |
|
444 def closeEvent(self, evt): |
|
445 """ |
|
446 Protected event handler for the close event. |
|
447 |
|
448 @param evt reference to the close event |
|
449 @type QCloseEvent |
|
450 """ |
|
451 self.save() |
|
452 |
|
453 def cleanup(self): |
|
454 """ |
|
455 Public slot to cleanup the downloads. |
|
456 """ |
|
457 self.on_cleanupButton_clicked() |
|
458 |
|
459 @pyqtSlot() |
|
460 def on_cleanupButton_clicked(self): |
|
461 """ |
|
462 Private slot to cleanup the downloads. |
|
463 """ |
|
464 if self.downloadsCount() == 0: |
|
465 return |
|
466 |
|
467 self.__model.removeRows(0, self.downloadsCount()) |
|
468 if ( |
|
469 self.downloadsCount() == 0 and |
|
470 self.__iconProvider is not None |
|
471 ): |
|
472 self.__iconProvider = None |
|
473 |
|
474 self.changeOccurred() |
|
475 |
|
476 self.downloadsCountChanged.emit() |
|
477 |
|
478 def __finished(self, success): |
|
479 """ |
|
480 Private slot to handle a finished download. |
|
481 |
|
482 @param success flag indicating a successful download |
|
483 @type bool |
|
484 """ |
|
485 if self.isVisible(): |
|
486 QApplication.alert(self) |
|
487 |
|
488 self.downloadsCountChanged.emit() |
|
489 |
|
490 if self.activeDownloadsCount() == 0: |
|
491 # all active downloads are done |
|
492 if success and ericApp().activeWindow() is not self: |
|
493 WebBrowserWindow.showNotification( |
|
494 UI.PixmapCache.getPixmap("downloads48"), |
|
495 self.tr("Downloads finished"), |
|
496 self.tr("All files have been downloaded.") |
|
497 ) |
|
498 if not Preferences.getWebBrowser("DownloadManagerAutoClose"): |
|
499 self.raise_() |
|
500 self.activateWindow() |
|
501 |
|
502 self.__stopUpdateTimer() |
|
503 self.infoLabel.clear() |
|
504 self.setWindowTitle(self.tr("Download Manager")) |
|
505 if Globals.isWindowsPlatform(): |
|
506 self.__taskbarButton().progress().hide() |
|
507 |
|
508 if Preferences.getWebBrowser("DownloadManagerAutoClose"): |
|
509 self.close() |
|
510 |
|
511 def setDownloadDirectory(self, directory): |
|
512 """ |
|
513 Public method to set the current download directory. |
|
514 |
|
515 @param directory current download directory (string) |
|
516 """ |
|
517 self.__downloadDirectory = directory |
|
518 if self.__downloadDirectory != "": |
|
519 self.__downloadDirectory += "/" |
|
520 |
|
521 def downloadDirectory(self): |
|
522 """ |
|
523 Public method to get the current download directory. |
|
524 |
|
525 @return current download directory (string) |
|
526 """ |
|
527 return self.__downloadDirectory |
|
528 |
|
529 def downloadsCount(self): |
|
530 """ |
|
531 Public method to get the number of downloads. |
|
532 |
|
533 @return number of downloads |
|
534 @rtype int |
|
535 """ |
|
536 return len(self.__downloads) |
|
537 |
|
538 def downloads(self): |
|
539 """ |
|
540 Public method to get a reference to the downloads. |
|
541 |
|
542 @return reference to the downloads (list of DownloadItem) |
|
543 """ |
|
544 return self.__downloads |
|
545 |
|
546 def changeOccurred(self): |
|
547 """ |
|
548 Public method to signal a change. |
|
549 """ |
|
550 self.__saveTimer.changeOccurred() |
|
551 |
|
552 def __taskbarButton(self): |
|
553 """ |
|
554 Private method to get a reference to the task bar button (Windows |
|
555 only). |
|
556 |
|
557 @return reference to the task bar button |
|
558 @rtype QWinTaskbarButton or None |
|
559 """ |
|
560 if Globals.isWindowsPlatform(): |
|
561 from PyQt6.QtWinExtras import QWinTaskbarButton |
|
562 if self.__winTaskbarButton is None: |
|
563 window = WebBrowserWindow.mainWindow() |
|
564 self.__winTaskbarButton = QWinTaskbarButton( |
|
565 window.windowHandle()) |
|
566 self.__winTaskbarButton.progress().setRange(0, 100) |
|
567 |
|
568 return self.__winTaskbarButton |
|
569 |
|
570 def timerEvent(self, evt): |
|
571 """ |
|
572 Protected event handler for timer events. |
|
573 |
|
574 @param evt reference to the timer event |
|
575 @type QTimerEvent |
|
576 """ |
|
577 if evt.timerId() == self.__updateTimer.timerId(): |
|
578 if self.activeDownloadsCount() == 0: |
|
579 self.__stopUpdateTimer() |
|
580 self.infoLabel.clear() |
|
581 self.setWindowTitle(self.tr("Download Manager")) |
|
582 if Globals.isWindowsPlatform(): |
|
583 self.__taskbarButton().progress().hide() |
|
584 else: |
|
585 progresses = [] |
|
586 for itm in self.__downloads: |
|
587 if ( |
|
588 itm is None or |
|
589 itm.downloadCanceled() or |
|
590 not itm.downloading() |
|
591 ): |
|
592 continue |
|
593 |
|
594 progresses.append(( |
|
595 itm.downloadProgress(), |
|
596 itm.remainingTime(), |
|
597 itm.currentSpeed() |
|
598 )) |
|
599 |
|
600 if not progresses: |
|
601 return |
|
602 |
|
603 remaining = 0 |
|
604 progress = 0 |
|
605 speed = 0.0 |
|
606 |
|
607 for progressData in progresses: |
|
608 if progressData[1] > remaining: |
|
609 remaining = progressData[1] |
|
610 progress += progressData[0] |
|
611 speed += progressData[2] |
|
612 progress /= len(progresses) |
|
613 |
|
614 if self.isVisible(): |
|
615 self.infoLabel.setText(self.tr( |
|
616 "{0}% of %n file(s) ({1}) {2}", "", |
|
617 len(progresses)).format( |
|
618 progress, |
|
619 speedString(speed), |
|
620 timeString(remaining), |
|
621 )) |
|
622 self.setWindowTitle(self.tr("{0}% - Download Manager")) |
|
623 |
|
624 if Globals.isWindowsPlatform(): |
|
625 self.__taskbarButton().progress().show() |
|
626 self.__taskbarButton().progress().setValue(progress) |
|
627 |
|
628 super().timerEvent(evt) |
|
629 |
|
630 def __startUpdateTimer(self): |
|
631 """ |
|
632 Private slot to start the update timer. |
|
633 """ |
|
634 if self.activeDownloadsCount() and not self.__updateTimer.isActive(): |
|
635 self.__updateTimer.start(DownloadManager.UpdateTimerTimeout, self) |
|
636 |
|
637 def __stopUpdateTimer(self): |
|
638 """ |
|
639 Private slot to stop the update timer. |
|
640 """ |
|
641 self.__updateTimer.stop() |
|
642 |
|
643 ########################################################################### |
|
644 ## Context menu related methods below |
|
645 ########################################################################### |
|
646 |
|
647 def __currentItem(self): |
|
648 """ |
|
649 Private method to get a reference to the current item. |
|
650 |
|
651 @return reference to the current item (DownloadItem) |
|
652 """ |
|
653 index = self.downloadsView.currentIndex() |
|
654 if index and index.isValid(): |
|
655 row = index.row() |
|
656 return self.__downloads[row] |
|
657 |
|
658 return None |
|
659 |
|
660 def __contextMenuOpen(self): |
|
661 """ |
|
662 Private method to open the downloaded file. |
|
663 """ |
|
664 itm = self.__currentItem() |
|
665 if itm is not None: |
|
666 itm.openFile() |
|
667 |
|
668 def __contextMenuOpenFolder(self): |
|
669 """ |
|
670 Private method to open the folder containing the downloaded file. |
|
671 """ |
|
672 itm = self.__currentItem() |
|
673 if itm is not None: |
|
674 itm.openFolder() |
|
675 |
|
676 def __contextMenuCancel(self): |
|
677 """ |
|
678 Private method to cancel the current download. |
|
679 """ |
|
680 itm = self.__currentItem() |
|
681 if itm is not None: |
|
682 itm.cancelDownload() |
|
683 |
|
684 def __contextMenuGotoPage(self): |
|
685 """ |
|
686 Private method to open the download page. |
|
687 """ |
|
688 itm = self.__currentItem() |
|
689 if itm is not None: |
|
690 url = itm.getPageUrl() |
|
691 WebBrowserWindow.mainWindow().openUrl(url, "") |
|
692 |
|
693 def __contextMenuCopyLink(self): |
|
694 """ |
|
695 Private method to copy the download link to the clipboard. |
|
696 """ |
|
697 itm = self.__currentItem() |
|
698 if itm is not None: |
|
699 url = itm.getPageUrl().toDisplayString( |
|
700 QUrl.ComponentFormattingOption.FullyDecoded) |
|
701 QApplication.clipboard().setText(url) |
|
702 |
|
703 def __contextMenuSelectAll(self): |
|
704 """ |
|
705 Private method to select all downloads. |
|
706 """ |
|
707 self.downloadsView.selectAll() |
|
708 |
|
709 def __contextMenuRemoveSelected(self): |
|
710 """ |
|
711 Private method to remove the selected downloads from the list. |
|
712 """ |
|
713 self.downloadsView.removeSelected() |