class _TransferWidget(QFrame): cancel = pyqtSignal() cancelBeforeTransfer = pyqtSignal(int) # transfer ID retry = pyqtSignal(object, object, int) # filesOrData, peerID, transfer ID def __init__(self, parent, logger, filesOrData, name, targetDir, numFiles, totalSize, peerID, transferID, down): super(_TransferWidget, self).__init__(parent) self.logger = logger self._filesOrData = filesOrData self._targetDir = targetDir self._numFiles = numFiles self._totalSize = totalSize self._targetFile = None self._peerID = peerID self._transferID = transferID self._transferring = True self._down = down self._success = False self._connectedToThread = False self._currentFile = None self._initLayout() if type(filesOrData) is list and len(filesOrData) is 1: self._setCurrentFile(filesOrData[0]) elif name: f = NamedTemporaryFile(suffix=name, delete=True) f.flush() self._setCurrentFile(f.name, name) f.close() else: self._setCurrentFile(None) self.reset() def _initLayout(self): layout = QVBoxLayout(self) layout.setContentsMargins(5, 5, 5, 5) layout.setSpacing(0) nameLayout = QHBoxLayout() nameLayout.setContentsMargins(0, 0, 0, 0) self._fileIconLabel = QLabel(self) nameLayout.addWidget(self._fileIconLabel, 0, Qt.AlignLeft) self._nameLabel = QLabel(self) nameLayout.addSpacing(5) nameLayout.addWidget(self._nameLabel, 1, Qt.AlignLeft) layout.addLayout(nameLayout) progressWidget = QWidget(self) progressLayout = QHBoxLayout(progressWidget) progressLayout.setSpacing(5) progressLayout.setContentsMargins(0, 0, 0, 0) iconLabel = QLabel(progressWidget) if self._down: picFile = get_settings().get_resource("images", "down.png") else: picFile = get_settings().get_resource("images", "up.png") iconLabel.setPixmap(QPixmap(picFile)) iconLabel.setFixedSize(15,15) progressLayout.addWidget(iconLabel, 0, Qt.AlignBottom) self._progress = QProgressBar(progressWidget) self._progress.setMinimum(0) self._progress.setMaximum(100) if getPlatform() == PLATFORM_MAC: self._progress.setAttribute(Qt.WA_MacMiniSize) self._progress.setMaximumHeight(16) progressLayout.addWidget(self._progress, 1) self._button = QPushButton(progressWidget) self._button.clicked.connect(self._buttonClicked) progressLayout.addSpacing(5) progressLayout.addWidget(self._button, 0, Qt.AlignCenter) layout.addWidget(progressWidget, 0, Qt.AlignBottom) self._statusLabel = QLabel(self) if getPlatform() == PLATFORM_MAC: self._statusLabel.setAttribute(Qt.WA_MacSmallSize) layout.addWidget(self._statusLabel) self.setObjectName(u"__transfer_widget") self.setFrameShape(QFrame.StyledPanel) self.setStyleSheet("QFrame#__transfer_widget{border-width: 1px; border-top-style: none; border-right-style: none; border-bottom-style: solid; border-left-style: none; border-color:palette(mid)}"); self.setSizePolicy(QSizePolicy.MinimumExpanding, QSizePolicy.Fixed) def reset(self): self._transferring = True self._statusLabel.setText(u"Waiting for data..." if self._down else u"Waiting for peer...") self._checkButtonFunction() self._progress.setMaximum(0) def isFinished(self): return not self._transferring def isSuccessful(self): return self._success def getFilePath(self): if self._numFiles is 1: return self._currentFile def _setFileIcon(self, curPath): if os.path.exists(curPath): fileInfo = QFileInfo(curPath) iconProvider = QFileIconProvider() icon = iconProvider.icon(fileInfo) self._fileIconLabel.setPixmap(icon.pixmap(16,16)) def _setCurrentFile(self, path, dispName=None): if get_peers() is not None: peerName = get_peers().getDisplayedPeerName(self._peerID) else: peerName = u"<unknown peer>" if not path: if self._down: text = u"%d %s (total %s) \u2190 %s" else: text = u"%d %s (total %s) \u2192 %s" text = text % (self._numFiles, u"file" if self._numFiles is 1 else "files", formatSize(self._totalSize), peerName) else: if self._down: text = u"%s (%stotal %s) \u2190 %s" else: text = u"%s (%stotal %s) \u2192 %s" if dispName is None: dispName = os.path.basename(path) numFilesS = u"" if self._numFiles is 1 else u"%d files, " % self._numFiles text = text % (dispName, numFilesS, formatSize(self._totalSize), peerName) self._setFileIcon(path) self._currentFile = path self._nameLabel.setText(text) def _setIcon(self, baseName): if baseName is None: self._button.setStyleSheet(""" QPushButton {min-width: 15px; max-width: 15px; min-height: 15px; max-height: 15px; margin: 0px; padding: 0px; border:none; } """) else: defPath = get_settings().get_resource("images", "%s32.png" % baseName) pressPath = get_settings().get_resource("images", "%s32p.png" % baseName) self._button.setStyleSheet(""" QPushButton {min-width: 15px; max-width: 15px; min-height: 15px; max-height: 15px; margin: 0px; padding: 0px; border:none; border-image: url(%s); } QPushButton:pressed { border-image: url(%s); } """ % (defPath, pressPath) ) def _checkButtonFunction(self): if self._transferring: self._setIcon("cancel") elif self._down: if self._success: self._setIcon("reveal") else: self._setIcon(None) else: if self._success: self._setIcon("reveal") else: self._setIcon("retry") def _reveal(self): filePath = self.getFilePath() if filePath: revealFile(filePath, self.logger) elif self._down: openFile(self._targetDir, self.logger) elif self._currentFile and os.path.exists(self._currentFile): revealFile(self._currentFile, self.logger) def _buttonClicked(self): if self._transferring: if self._connectedToThread: self.cancel.emit() else: self.cancelBeforeTransfer.emit(self._transferID) elif self._down: if self._success: self._reveal() else: if self._success: self._reveal() else: self.retry.emit(self._filesOrData, self._peerID, self._transferID) @loggingSlot(object, int) def nextFile(self, nameOrPath, _size): self._setCurrentFile(nameOrPath) def connectDataThread(self, dataThread): if not dataThread.isRunning(): self.transferError(dataThread, u"Transfer didn't start.") return self._connectedToThread = True dataThread.progressChanged.connect(self.progressChanged) dataThread.errorOnTransfer.connect(self.transferError) dataThread.successfullyTransferred.connect(self.successfullyTransferred) dataThread.transferCanceled.connect(self.transferCanceled) dataThread.nextFile.connect(self.nextFile) self.cancel.connect(dataThread.cancelTransfer) def disconnectDataThread(self, dataThread): if self._connectedToThread: self._connectedToThread = False dataThread.progressChanged.disconnect(self.progressChanged) dataThread.errorOnTransfer.disconnect(self.transferError) dataThread.successfullyTransferred.disconnect(self.successfullyTransferred) dataThread.transferCanceled.disconnect(self.transferCanceled) dataThread.nextFile.disconnect(self.nextFile) self.cancel.disconnect(dataThread.cancelTransfer) @loggingSlot(int, int) def progressChanged(self, newVal, maxVal): if newVal is 0: self._transferring = True self._progress.setMaximum(maxVal) self._statusLabel.setText(u"Receiving data" if self._down else u"Sending data") self._progress.setValue(newVal) @pyqtSlot(QThread) @loggingSlot(QThread, object) def successfullyTransferred(self, thread, _path=None): self._transferring = False self._success = True self._statusLabel.setText(u"Transfer finished successfully") self.disconnectDataThread(thread) self._checkButtonFunction() @loggingSlot(QThread, object) def transferError(self, thread, message=None): if not self._transferring: return self._transferring = False self._statusLabel.setText(u"Error transferring file (%s)" % message) self.disconnectDataThread(thread) self._checkButtonFunction() if self._progress.maximum() == 0: self._progress.setMaximum(100) @loggingSlot(QThread) def transferCanceled(self, thread): self._transferring = False self._statusLabel.setText(u"Transfer canceled") self.disconnectDataThread(thread) self._checkButtonFunction() def canceledBeforeTransfer(self, isTimeout): self._progress.setMaximum(100) self._transferring = False if isTimeout: self._statusLabel.setText(u"Transfer timed out") else: self._statusLabel.setText(u"Transfer canceled") self._checkButtonFunction()