|
1 # -*- coding: utf-8 -*- |
|
2 |
|
3 # Copyright (c) 2010 - 2021 Detlev Offenbach <detlev@die-offenbachs.de> |
|
4 # |
|
5 |
|
6 """ |
|
7 Module implementing the download manager class. |
|
8 """ |
|
9 |
|
10 from PyQt5.QtCore import ( |
|
11 pyqtSlot, pyqtSignal, Qt, QModelIndex, QFileInfo, QUrl, QBasicTimer |
|
12 ) |
|
13 from PyQt5.QtGui import QCursor, QKeySequence |
|
14 from PyQt5.QtWidgets import ( |
|
15 QDialog, QStyle, QFileIconProvider, QMenu, QApplication, QShortcut |
|
16 ) |
|
17 |
|
18 from E5Gui import E5MessageBox |
|
19 from E5Gui.E5Application import e5App |
|
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 = E5MessageBox.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=E5MessageBox.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, downloadItem): |
|
232 """ |
|
233 Public method to download a file. |
|
234 |
|
235 @param downloadItem reference to the download object containing the |
|
236 download data. |
|
237 @type QWebEngineDownloadItem |
|
238 """ |
|
239 url = downloadItem.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 = E5MessageBox.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 E5MessageBox.StandardButtons( |
|
265 E5MessageBox.Abort | |
|
266 E5MessageBox.Ignore), |
|
267 E5MessageBox.Abort) |
|
268 if res == E5MessageBox.Abort: |
|
269 downloadItem.cancel() |
|
270 return |
|
271 |
|
272 window = WebBrowserWindow.getWindow() |
|
273 pageUrl = window.currentBrowser().url() if window else QUrl() |
|
274 from .DownloadItem import DownloadItem |
|
275 itm = DownloadItem(downloadItem=downloadItem, pageUrl=pageUrl, |
|
276 parent=self) |
|
277 self.__addItem(itm) |
|
278 |
|
279 if Preferences.getWebBrowser("DownloadManagerAutoOpen"): |
|
280 self.show() |
|
281 else: |
|
282 self.__startUpdateTimer() |
|
283 |
|
284 def show(self): |
|
285 """ |
|
286 Public slot to show the download manager dialog. |
|
287 """ |
|
288 self.__startUpdateTimer() |
|
289 |
|
290 super().show() |
|
291 self.activateWindow() |
|
292 self.raise_() |
|
293 |
|
294 def __addItem(self, itm, append=False): |
|
295 """ |
|
296 Private method to add a download to the list of downloads. |
|
297 |
|
298 @param itm reference to the download item |
|
299 @type DownloadItem |
|
300 @param append flag indicating to append the item |
|
301 @type bool |
|
302 """ |
|
303 itm.statusChanged.connect(lambda: self.__updateRow(itm)) |
|
304 itm.downloadFinished.connect(self.__finished) |
|
305 |
|
306 # insert at top of window |
|
307 row = self.downloadsCount() if append else 0 |
|
308 self.__model.beginInsertRows(QModelIndex(), row, row) |
|
309 if append: |
|
310 self.__downloads.append(itm) |
|
311 else: |
|
312 self.__downloads.insert(0, itm) |
|
313 self.__model.endInsertRows() |
|
314 |
|
315 self.downloadsView.setIndexWidget(self.__model.index(row, 0), itm) |
|
316 icon = self.style().standardIcon(QStyle.StandardPixmap.SP_FileIcon) |
|
317 itm.setIcon(icon) |
|
318 self.downloadsView.setRowHeight( |
|
319 row, itm.sizeHint().height() * self.__rowHeightMultiplier) |
|
320 # just in case the download finished before the constructor returned |
|
321 self.__updateRow(itm) |
|
322 self.changeOccurred() |
|
323 |
|
324 self.downloadsCountChanged.emit() |
|
325 |
|
326 def __updateRow(self, itm): |
|
327 """ |
|
328 Private slot to update a download item. |
|
329 |
|
330 @param itm reference to the download item |
|
331 @type DownloadItem |
|
332 """ |
|
333 if itm not in self.__downloads: |
|
334 return |
|
335 |
|
336 row = self.__downloads.index(itm) |
|
337 |
|
338 if self.__iconProvider is None: |
|
339 self.__iconProvider = QFileIconProvider() |
|
340 |
|
341 icon = self.__iconProvider.icon(QFileInfo(itm.fileName())) |
|
342 if icon.isNull(): |
|
343 icon = self.style().standardIcon(QStyle.StandardPixmap.SP_FileIcon) |
|
344 itm.setIcon(icon) |
|
345 |
|
346 self.downloadsView.setRowHeight( |
|
347 row, |
|
348 itm.minimumSizeHint().height() * self.__rowHeightMultiplier) |
|
349 |
|
350 remove = False |
|
351 |
|
352 if ( |
|
353 itm.downloadedSuccessfully() and |
|
354 self.removePolicy() == DownloadManager.RemoveSuccessFullDownload |
|
355 ): |
|
356 remove = True |
|
357 |
|
358 if remove: |
|
359 self.__model.removeRow(row) |
|
360 |
|
361 self.cleanupButton.setEnabled( |
|
362 (self.downloadsCount() - self.activeDownloadsCount()) > 0) |
|
363 |
|
364 # record the change |
|
365 self.changeOccurred() |
|
366 |
|
367 def removePolicy(self): |
|
368 """ |
|
369 Public method to get the remove policy. |
|
370 |
|
371 @return remove policy (integer) |
|
372 """ |
|
373 return Preferences.getWebBrowser("DownloadManagerRemovePolicy") |
|
374 |
|
375 def setRemovePolicy(self, policy): |
|
376 """ |
|
377 Public method to set the remove policy. |
|
378 |
|
379 @param policy policy to be set |
|
380 (DownloadManager.RemoveExit, DownloadManager.RemoveNever, |
|
381 DownloadManager.RemoveSuccessFullDownload) |
|
382 """ |
|
383 if policy in (DownloadManager.RemoveExit, |
|
384 DownloadManager.RemoveNever, |
|
385 DownloadManager.RemoveSuccessFullDownload): |
|
386 |
|
387 if policy == self.removePolicy(): |
|
388 return |
|
389 |
|
390 Preferences.setWebBrowser("DownloadManagerRemovePolicy", |
|
391 self.policy) |
|
392 |
|
393 def save(self): |
|
394 """ |
|
395 Public method to save the download settings. |
|
396 """ |
|
397 if not self.__loaded: |
|
398 return |
|
399 |
|
400 Preferences.setWebBrowser("DownloadManagerSize", self.size()) |
|
401 Preferences.setWebBrowser("DownloadManagerPosition", self.pos()) |
|
402 if self.removePolicy() == DownloadManager.RemoveExit: |
|
403 return |
|
404 |
|
405 from WebBrowser.WebBrowserWindow import WebBrowserWindow |
|
406 if WebBrowserWindow.isPrivate(): |
|
407 return |
|
408 |
|
409 downloads = [] |
|
410 for download in self.__downloads: |
|
411 downloads.append(download.getData()) |
|
412 Preferences.setWebBrowser("DownloadManagerDownloads", downloads) |
|
413 |
|
414 def __load(self): |
|
415 """ |
|
416 Private method to load the download settings. |
|
417 """ |
|
418 if self.__loaded: |
|
419 return |
|
420 |
|
421 size = Preferences.getWebBrowser("DownloadManagerSize") |
|
422 if size.isValid(): |
|
423 self.resize(size) |
|
424 pos = Preferences.getWebBrowser("DownloadManagerPosition") |
|
425 self.move(pos) |
|
426 |
|
427 from WebBrowser.WebBrowserWindow import WebBrowserWindow |
|
428 if not WebBrowserWindow.isPrivate(): |
|
429 downloads = Preferences.getWebBrowser("DownloadManagerDownloads") |
|
430 for download in downloads: |
|
431 if ( |
|
432 not download["URL"].isEmpty() and |
|
433 bool(download["Location"]) |
|
434 ): |
|
435 from .DownloadItem import DownloadItem |
|
436 itm = DownloadItem(parent=self) |
|
437 itm.setData(download) |
|
438 self.__addItem(itm, append=True) |
|
439 self.cleanupButton.setEnabled( |
|
440 (self.downloadsCount() - self.activeDownloadsCount()) > 0) |
|
441 |
|
442 self.__loaded = True |
|
443 |
|
444 self.downloadsCountChanged.emit() |
|
445 |
|
446 def closeEvent(self, evt): |
|
447 """ |
|
448 Protected event handler for the close event. |
|
449 |
|
450 @param evt reference to the close event |
|
451 @type QCloseEvent |
|
452 """ |
|
453 self.save() |
|
454 |
|
455 def cleanup(self): |
|
456 """ |
|
457 Public slot to cleanup the downloads. |
|
458 """ |
|
459 self.on_cleanupButton_clicked() |
|
460 |
|
461 @pyqtSlot() |
|
462 def on_cleanupButton_clicked(self): |
|
463 """ |
|
464 Private slot to cleanup the downloads. |
|
465 """ |
|
466 if self.downloadsCount() == 0: |
|
467 return |
|
468 |
|
469 self.__model.removeRows(0, self.downloadsCount()) |
|
470 if ( |
|
471 self.downloadsCount() == 0 and |
|
472 self.__iconProvider is not None |
|
473 ): |
|
474 self.__iconProvider = None |
|
475 |
|
476 self.changeOccurred() |
|
477 |
|
478 self.downloadsCountChanged.emit() |
|
479 |
|
480 def __finished(self, success): |
|
481 """ |
|
482 Private slot to handle a finished download. |
|
483 |
|
484 @param success flag indicating a successful download |
|
485 @type bool |
|
486 """ |
|
487 if self.isVisible(): |
|
488 QApplication.alert(self) |
|
489 |
|
490 self.downloadsCountChanged.emit() |
|
491 |
|
492 if self.activeDownloadsCount() == 0: |
|
493 # all active downloads are done |
|
494 if success and e5App().activeWindow() is not self: |
|
495 WebBrowserWindow.showNotification( |
|
496 UI.PixmapCache.getPixmap("downloads48"), |
|
497 self.tr("Downloads finished"), |
|
498 self.tr("All files have been downloaded.") |
|
499 ) |
|
500 if not Preferences.getWebBrowser("DownloadManagerAutoClose"): |
|
501 self.raise_() |
|
502 self.activateWindow() |
|
503 |
|
504 self.__stopUpdateTimer() |
|
505 self.infoLabel.clear() |
|
506 self.setWindowTitle(self.tr("Download Manager")) |
|
507 if Globals.isWindowsPlatform(): |
|
508 self.__taskbarButton().progress().hide() |
|
509 |
|
510 if Preferences.getWebBrowser("DownloadManagerAutoClose"): |
|
511 self.close() |
|
512 |
|
513 def setDownloadDirectory(self, directory): |
|
514 """ |
|
515 Public method to set the current download directory. |
|
516 |
|
517 @param directory current download directory (string) |
|
518 """ |
|
519 self.__downloadDirectory = directory |
|
520 if self.__downloadDirectory != "": |
|
521 self.__downloadDirectory += "/" |
|
522 |
|
523 def downloadDirectory(self): |
|
524 """ |
|
525 Public method to get the current download directory. |
|
526 |
|
527 @return current download directory (string) |
|
528 """ |
|
529 return self.__downloadDirectory |
|
530 |
|
531 def downloadsCount(self): |
|
532 """ |
|
533 Public method to get the number of downloads. |
|
534 |
|
535 @return number of downloads |
|
536 @rtype int |
|
537 """ |
|
538 return len(self.__downloads) |
|
539 |
|
540 def downloads(self): |
|
541 """ |
|
542 Public method to get a reference to the downloads. |
|
543 |
|
544 @return reference to the downloads (list of DownloadItem) |
|
545 """ |
|
546 return self.__downloads |
|
547 |
|
548 def changeOccurred(self): |
|
549 """ |
|
550 Public method to signal a change. |
|
551 """ |
|
552 self.__saveTimer.changeOccurred() |
|
553 |
|
554 def __taskbarButton(self): |
|
555 """ |
|
556 Private method to get a reference to the task bar button (Windows |
|
557 only). |
|
558 |
|
559 @return reference to the task bar button |
|
560 @rtype QWinTaskbarButton or None |
|
561 """ |
|
562 if Globals.isWindowsPlatform(): |
|
563 from PyQt5.QtWinExtras import QWinTaskbarButton |
|
564 if self.__winTaskbarButton is None: |
|
565 window = WebBrowserWindow.mainWindow() |
|
566 self.__winTaskbarButton = QWinTaskbarButton( |
|
567 window.windowHandle()) |
|
568 self.__winTaskbarButton.progress().setRange(0, 100) |
|
569 |
|
570 return self.__winTaskbarButton |
|
571 |
|
572 def timerEvent(self, evt): |
|
573 """ |
|
574 Protected event handler for timer events. |
|
575 |
|
576 @param evt reference to the timer event |
|
577 @type QTimerEvent |
|
578 """ |
|
579 if evt.timerId() == self.__updateTimer.timerId(): |
|
580 if self.activeDownloadsCount() == 0: |
|
581 self.__stopUpdateTimer() |
|
582 self.infoLabel.clear() |
|
583 self.setWindowTitle(self.tr("Download Manager")) |
|
584 if Globals.isWindowsPlatform(): |
|
585 self.__taskbarButton().progress().hide() |
|
586 else: |
|
587 progresses = [] |
|
588 for itm in self.__downloads: |
|
589 if ( |
|
590 itm is None or |
|
591 itm.downloadCanceled() or |
|
592 not itm.downloading() |
|
593 ): |
|
594 continue |
|
595 |
|
596 progresses.append(( |
|
597 itm.downloadProgress(), |
|
598 itm.remainingTime(), |
|
599 itm.currentSpeed() |
|
600 )) |
|
601 |
|
602 if not progresses: |
|
603 return |
|
604 |
|
605 remaining = 0 |
|
606 progress = 0 |
|
607 speed = 0.0 |
|
608 |
|
609 for progressData in progresses: |
|
610 if progressData[1] > remaining: |
|
611 remaining = progressData[1] |
|
612 progress += progressData[0] |
|
613 speed += progressData[2] |
|
614 progress /= len(progresses) |
|
615 |
|
616 if self.isVisible(): |
|
617 self.infoLabel.setText(self.tr( |
|
618 "{0}% of %n file(s) ({1}) {2}", "", |
|
619 len(progresses)).format( |
|
620 progress, |
|
621 speedString(speed), |
|
622 timeString(remaining), |
|
623 )) |
|
624 self.setWindowTitle(self.tr("{0}% - Download Manager")) |
|
625 |
|
626 if Globals.isWindowsPlatform(): |
|
627 self.__taskbarButton().progress().show() |
|
628 self.__taskbarButton().progress().setValue(progress) |
|
629 |
|
630 super().timerEvent(evt) |
|
631 |
|
632 def __startUpdateTimer(self): |
|
633 """ |
|
634 Private slot to start the update timer. |
|
635 """ |
|
636 if self.activeDownloadsCount() and not self.__updateTimer.isActive(): |
|
637 self.__updateTimer.start(DownloadManager.UpdateTimerTimeout, self) |
|
638 |
|
639 def __stopUpdateTimer(self): |
|
640 """ |
|
641 Private slot to stop the update timer. |
|
642 """ |
|
643 self.__updateTimer.stop() |
|
644 |
|
645 ########################################################################### |
|
646 ## Context menu related methods below |
|
647 ########################################################################### |
|
648 |
|
649 def __currentItem(self): |
|
650 """ |
|
651 Private method to get a reference to the current item. |
|
652 |
|
653 @return reference to the current item (DownloadItem) |
|
654 """ |
|
655 index = self.downloadsView.currentIndex() |
|
656 if index and index.isValid(): |
|
657 row = index.row() |
|
658 return self.__downloads[row] |
|
659 |
|
660 return None |
|
661 |
|
662 def __contextMenuOpen(self): |
|
663 """ |
|
664 Private method to open the downloaded file. |
|
665 """ |
|
666 itm = self.__currentItem() |
|
667 if itm is not None: |
|
668 itm.openFile() |
|
669 |
|
670 def __contextMenuOpenFolder(self): |
|
671 """ |
|
672 Private method to open the folder containing the downloaded file. |
|
673 """ |
|
674 itm = self.__currentItem() |
|
675 if itm is not None: |
|
676 itm.openFolder() |
|
677 |
|
678 def __contextMenuCancel(self): |
|
679 """ |
|
680 Private method to cancel the current download. |
|
681 """ |
|
682 itm = self.__currentItem() |
|
683 if itm is not None: |
|
684 itm.cancelDownload() |
|
685 |
|
686 def __contextMenuGotoPage(self): |
|
687 """ |
|
688 Private method to open the download page. |
|
689 """ |
|
690 itm = self.__currentItem() |
|
691 if itm is not None: |
|
692 url = itm.getPageUrl() |
|
693 WebBrowserWindow.mainWindow().openUrl(url, "") |
|
694 |
|
695 def __contextMenuCopyLink(self): |
|
696 """ |
|
697 Private method to copy the download link to the clipboard. |
|
698 """ |
|
699 itm = self.__currentItem() |
|
700 if itm is not None: |
|
701 url = itm.getPageUrl().toDisplayString( |
|
702 QUrl.ComponentFormattingOption.FullyDecoded) |
|
703 QApplication.clipboard().setText(url) |
|
704 |
|
705 def __contextMenuSelectAll(self): |
|
706 """ |
|
707 Private method to select all downloads. |
|
708 """ |
|
709 self.downloadsView.selectAll() |
|
710 |
|
711 def __contextMenuRemoveSelected(self): |
|
712 """ |
|
713 Private method to remove the selected downloads from the list. |
|
714 """ |
|
715 self.downloadsView.removeSelected() |