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