import os from PyQt5 import uic from PyQt5.QtCore import Qt, QUrl from PyQt5.QtGui import QDesktopServices from PyQt5.QtWidgets import QAction, QMenu from application.notification import IObserver, NotificationCenter from application.python import Null from application.system import makedirs from zope.interface import implementer from blink.configuration.settings import BlinkSettings from blink.resources import Resources from blink.sessions import FileTransferDelegate, FileTransferModel from blink.util import translate from blink.widgets.util import ContextMenuActions __all__ = ['FileTransferWindow'] ui_class, base_class = uic.loadUiType(Resources.get('filetransfer_window.ui')) @implementer(IObserver) class FileTransferWindow(base_class, ui_class): def __init__(self, parent=None): super(FileTransferWindow, self).__init__(parent) with Resources.directory: self.setupUi(self) self.model = FileTransferModel(self) self.listview.setModel(self.model) self.listview.setItemDelegate(FileTransferDelegate(self.listview)) self.listview.customContextMenuRequested.connect(self._SH_ContextMenuRequested) self.context_menu = QMenu(self.listview) self.actions = ContextMenuActions() self.actions.open_file = QAction(translate('filetransfer_window', "Open"), self, triggered=self._AH_OpenFile) self.actions.open_file_folder = QAction(translate('filetransfer_window', "Open File Folder"), self, triggered=self._AH_OpenFileFolder) self.actions.cancel_transfer = QAction(translate('filetransfer_window', "Cancel"), self, triggered=self._AH_CancelTransfer) self.actions.retry_transfer = QAction(translate('filetransfer_window', "Retry"), self, triggered=self._AH_RetryTransfer) self.actions.remove_entry = QAction(translate('filetransfer_window', "Remove From List"), self, triggered=self._AH_RemoveEntry) self.actions.open_downloads_folder = QAction(translate('filetransfer_window', "Open Transfers Folder"), self, triggered=self._AH_OpenTransfersFolder) self.actions.clear_list = QAction(translate('filetransfer_window', "Clear List"), self, triggered=self._AH_ClearList) self.model.itemAdded.connect(self.update_status) self.model.itemRemoved.connect(self.update_status) self.model.modelReset.connect(self.update_status) notification_center = NotificationCenter() notification_center.add_observer(self, name='BlinkFileTransferWillRetry') notification_center.add_observer(self, name='BlinkFileTransferDidEnd') def show(self, activate=True): settings = BlinkSettings() makedirs(settings.transfers_directory.normalized) self.setAttribute(Qt.WA_ShowWithoutActivating, not activate) super(FileTransferWindow, self).show() self.raise_() if activate: self.activateWindow() def update_status(self): total = len(self.model.items) active = len([item for item in self.model.items if not item.ended]) text = '%d %s' % (total, translate('filetransfer_window', 'transfer') if total == 1 else translate('filetransfer_window', 'transfers')) if active > 0: text += translate('filetransfer_window', ' (%d active)') % active self.status_label.setText(text) def handle_notification(self, notification): handler = getattr(self, '_NH_%s' % notification.name, Null) handler(notification) def _NH_BlinkFileTransferWillRetry(self, notification): self.update_status() def _NH_BlinkFileTransferDidEnd(self, notification): self.update_status() def _SH_ContextMenuRequested(self, pos): menu = self.context_menu menu.clear() index = self.listview.indexAt(pos) if index.isValid(): item = index.data(Qt.UserRole) if item.ended: if not item.failed: menu.addAction(self.actions.open_file) menu.addAction(self.actions.open_file_folder) elif item.direction == 'outgoing': menu.addAction(self.actions.retry_transfer) menu.addAction(self.actions.remove_entry) else: if item.direction == 'outgoing': menu.addAction(self.actions.open_file) menu.addAction(self.actions.open_file_folder) menu.addAction(self.actions.cancel_transfer) menu.addSeparator() menu.addAction(self.actions.open_downloads_folder) menu.addAction(self.actions.clear_list) elif self.model.rowCount() > 0: menu.addAction(self.actions.open_downloads_folder) menu.addAction(self.actions.clear_list) else: menu.addAction(self.actions.open_downloads_folder) menu.exec_(self.mapToGlobal(pos)) def _AH_OpenFile(self): item = self.listview.selectedIndexes()[0].data(Qt.UserRole) QDesktopServices.openUrl(QUrl.fromLocalFile(item.filename)) def _AH_OpenFileFolder(self): item = self.listview.selectedIndexes()[0].data(Qt.UserRole) QDesktopServices.openUrl(QUrl.fromLocalFile(os.path.dirname(item.filename))) def _AH_CancelTransfer(self): item = self.listview.selectedIndexes()[0].data(Qt.UserRole) item.end() def _AH_RetryTransfer(self): item = self.listview.selectedIndexes()[0].data(Qt.UserRole) item.retry() def _AH_RemoveEntry(self): item = self.listview.selectedIndexes()[0].data(Qt.UserRole) self.model.removeItem(item) def _AH_OpenTransfersFolder(self): settings = BlinkSettings() QDesktopServices.openUrl(QUrl.fromLocalFile(settings.transfers_directory.normalized)) def _AH_ClearList(self): self.model.clear_ended() del ui_class, base_class