Exemple #1
0
class StreamHandler(QObject):

    commandReceived = pyqtSignal(str)
    
    def __init__(self, parent = None):
    
        QObject.__init__(self, parent)
    
    def openInput(self):
    
        self.stdin = QFile()
        self.stdin.open(0, QFile.ReadOnly)
    
    def openOutput(self):
    
        self.stdout = QFile()
        self.stdout.open(1, QFile.WriteOnly)
    
    def handleInput(self):
    
        while self.stdin.isOpen():
        
            command = str(self.stdin.readLine(), "utf8")
            if not command:
                break
            
            self.commandReceived.emit(command.strip())
            
            # This shouldn't be needed, but QFile can get into a state where
            # readLine no longer blocks.
        
        print("Input stream closed.")
    
    @pyqtSlot(QByteArray)
    def handleOutput(self, data):
    
        while self.stdout.isOpen() and data.size() > 0:
        
            written = self.stdout.write(data)
            data = data.right(data.size() - written)
    
    @pyqtSlot(str)
    def handleOutput(self, data):
    
        data = QByteArray(bytes(data, "utf8"))
        while self.stdout.isOpen() and data.size() > 0:
        
            written = self.stdout.write(data)
            self.stdout.flush()
            data = data.right(data.size() - written)
def vizCompressed(fileName):
    #fileName = 'D:/Data/10_23_shunfengmix/rgb_image_58'

    filenamesplit = os.path.splitext(filename)
    print("file name:", filenamesplit)
    file = QFile(filenamesplit[0] + '.compressed')
    file.open(QFile.ReadOnly)
    if file.isOpen():
        data = file.readAll()
        labels = qUncompress(data)
    img = cv2.imread(filenamesplit[0] + '.jpg')

    for r in range(img.shape[0]):
        for c in range(img.shape[1]):
            index = r * img.shape[1] + c
            if (labels[index] == '1'):  #tape
                img[r, c] = [0, 0, 255]
            elif (labels[index] == '2'):  #boundry
                img[r, c] = [0, 165, 255]
            elif (labels[index] != '0'):  #exception
                img[r, c] = [255, 255, 0]

    cv2.imshow('image', img)
    cv2.waitKey(0)
    cv2.imwrite(filenamesplit[0] + '_rf.jpg', img)
Exemple #3
0
 def set_widgetlist(self):
     self.treeWidget_widgetlist.clear()
     file = self.format_content
     qfile = QFile(file)
     self.dom = QDomDocument()
     # 找到文件,则设置引擎,否则向xml文件直接添加数据
     if qfile.open(QFile.ReadWrite | QFile.Text):
         self.dom.setContent(QFile)
         # self.file = QFile
     else:
         self.dom.setContent(file)
         # self.file = file
     if self.dom.isNull():
         return False
     # 获得根目录的元素,返回QDomElement    <GMPPaper>
     element = self.dom.documentElement()
     # 获得第一个子元素,返回QDomNode
     n = element.firstChild()
     # 如果没有读到文档结尾,而且没有出现错误
     self.nodelist = element.childNodes()
     line_number = 1
     for i in range(len(self.nodelist)):
         tag_name = self.nodelist.item(i).toElement().tagName()
         qtreeitem = QTreeWidgetItem(self.treeWidget_widgetlist)
         qtreeitem.setText(0, str(i))
         qtreeitem.setText(1, str(line_number))
         qtreeitem.setText(2, TAG_NAME_DICT[tag_name])
         if tag_name == "br":
             line_number += 1
     if qfile.isOpen():
         qfile.close()
Exemple #4
0
    def openxml(self, file):

        # 传入的是地址
        qfile = QFile(file)
        # 找到文件,则设置引擎,否则向xml文件直接添加数据
        if qfile.open(QFile.ReadWrite | QFile.Text):
            self.dom.setContent(QFile)
        else:
            self.dom.setContent(file)
        if self.dom.isNull():
            return False
        # 获得根目录的元素,返回QDomElement    <GMPPaper>
        element = self.dom.documentElement()
        # 获得第一个子元素,返回QDomNode
        n = element.firstChild()
        # 如果没有读到文档结尾,而且没有出现错误
        while not n.isNull():
            # 把当前的QDomNode转为QDomElement
            e = n.toElement()

            if not e.isNull():
                name = e.tagName()
                # 标题框
                if name == "Title":
                    self.titleBox(e)
                # 标题输入框
                elif name == "TextBox":
                    self.inputBox(e)
                # 线框
                elif name == "Box":
                    self.wireframe(e)
                # 检测框
                elif name == "CheckBox":
                    self.checkBox(e)
                # 下拉框
                elif name == "ComboBox":
                    self.comboBox(e)
                # 签名框
                elif name == "Signature":
                    self.signBox(e)
                # 表达式
                elif name == "Expr":
                    self.exprBox(e)
                # 换行
                elif name == "br":
                    self.wrapBox()
            # 空格组成的字符,包括换行
            elif self.dom.isWhitespace():
                pass
            # 纯文本
            elif self.dom.isCharacters():
                pass
            # 获取下一个同级标签
            n = n.nextSibling()

        if qfile.isOpen():
            qfile.close()
        # self.update()
        self.scrollAreaWidgetContents.setLineBorder(self.line_border)
        '''
Exemple #5
0
    def __init__(self, character):
        super().__init__(character)
        self.myChar = character

        qss_file = QFile("QSS/NumberButtonStyle.qss")
        qss_file.open(QFile.ReadOnly)
        if qss_file.isOpen():
            qss_stream = QtCore.QTextStream(qss_file).readAll()
            self.setStylesheet(qss_stream)
        else:
            # 退出值为1说明打开qss失败
            sys.exit(1)
Exemple #6
0
    def __init__(self):
        # 读取qss文件
        qss_file = QFile("QSS/BasicStyle.qss")
        qss_file.open(QFile.ReadOnly)
        # 读取qss文件
        if qss_file.isOpen():
            qss_stream = QtCore.QTextStream(qss_file).readAll()
            self.setStylesheet(qss_stream)
        else:
            # 退出值为1说明打开qss失败
            sys.exit(1)

        self.setGeometry(windows_static_data.left, windows_static_data.top, windows_static_data.width,
                         windows_static_data.height)
class DocumentReader:
    def __init__(self, filename):
        self.file = QFile()
        self.file.setFileName(filename)
        self.is_error = False
        self.errorString = ""
        if not self.file.open(QFile.ReadOnly):
            error = self.file.errorString()
            qDebug("cannot open file \"{1}\"".format(error))
            self.is_error = True
            self.errorString = error

    def read(self, document):
        if not self.file.isOpen():
            return
        text = str(self.file.readAll().data(), encoding='utf-8')
        document.setPlainText(text)
class DocumentWriter:
    def __init__(self, filename):
        self.file = QFile()
        self.file.setFileName(filename)
        self.is_error = False
        self.errorString = ""
        if not self.file.open(QFile.WriteOnly):
            error = self.file.errorString()
            qDebug("cannot open file \"{1}\"".format(error))
            self.is_error = True
            self.errorString = error

    def write(self, document):
        if not self.file.isOpen():
            return
        writer = QTextDocumentWriter()
        writer.setFormat(QByteArray().append("plaintext"))
        writer.setDevice(self.file)
        writer.write(document)
Exemple #9
0
class TcpS(QDialog, Ui_TcpServer):
    """
    文件传输服务器
    """

    sendFileName = pyqtSignal(str)

    def __init__(self, parent=None):
        """
        一些初始设置
        """
        super(TcpS, self).__init__(parent)
        self.setupUi(self)
        self.payloadSize = 64 * 1024
        # 读取数据64KB

        self.totalBytes = 0
        # 总大小

        self.bytesWritten = 0
        # 保存的数据

        self.bytesToWrite = 0
        # 每次减少连接写的数据量大小

        self.theFileName = ""
        # 文件名(不含路径)

        self.fileName = ""
        # 文件全名

        self.localFile = QFile()
        self.outBlock = QByteArray()
        # QByteArray()的对象,即字节数组

        self.time = QTime()
        self.initServer()

    def initServer(self):
        """
        网络设置初始化
        """
        self.tcpPort = 7788
        # 指定了TCP端口为7788

        self.tcpServer = QTcpServer(self)
        self.clientConnection = QTcpSocket(self)
        # 创建一个Tcp服务器和一个Tcp套接字

        self.tcpServer.newConnection.connect(self.sendMessage)
        # 当有新的连接来的时候发出newConnection信号,我们连接到sendMessage()函数。

        self.serverStatuslabel.setText("请选择要传送的文件")
        self.progressBar.reset()
        self.serverOpenBtn.setEnabled(True)
        self.serverSendBtn.setEnabled(False)
        self.tcpServer.close()
        # 显示我们开始创建的对话框,打开按钮是可用的,发送按钮是不可用的,进度条复位,先关闭服务器。

    def refused(self):
        """
        对端拒绝接收文件,主程序会调用服务器的refused()函数,关闭服务器。
        """
        self.tcpServer.close()
        self.serverStatuslabel.setText("对方拒绝接收")

    def closeEvent(self, event):
        """
        关闭事件
        """
        self.on_serverCloseBtn_clicked()
        # 产生关闭事件,直接调用关闭窗口按钮函数。

    def sendMessage(self):
        """
        发送文件
        """
        self.serverSendBtn.setEnabled(False)
        # 发送按钮不可用

        self.clientConnection = self.tcpServer.nextPendingConnection()
        # self.clientConnection作为连接的QTcpSocket对象返回下一个挂起的连接。

        self.clientConnection.bytesWritten.connect(self.updateClientProgress)
        # 当连接中每次将数据有效载荷写入设备的当前写通道时,都会发出此信号。在此有效负载中写入的数据量为字节数。

        self.serverStatuslabel.setText("开始传送文件 {} !".format(self.theFileName))

        self.localFile = QFile(self.fileName)
        if not (self.localFile.open(QFile.ReadOnly)):
            errorMsg = "无法读取文件 {}:\n {}".format(self.fileName,
                                                self.localFile.errorString())
            QMessageBox.warning(self, "应用程序", errorMsg)
            return
        # 尝试打开文件,要是存在问题就报错。

        self.serverCloseBtn.setText("取消")

        self.totalBytes = self.localFile.size()
        # 记录一下需要传输的文件大小。单位:字节

        sendOut = QDataStream(self.outBlock, QIODevice.WriteOnly)
        # 这里的self.outBlock是QByteArray()的对象,即字节数组;QIODevice的模式为WriteOnly

        sendOut.setVersion(QDataStream.Qt_5_4)
        # 设定QDataStream的版本为Qt_5_4

        self.time.start()
        # 开始计时

        currentFile = self.fileName.split("/")[-1]
        # 传输的文件名

        sendOut.writeInt64(0)
        sendOut.writeInt64(0)
        sendOut.writeQString(currentFile)
        self.totalBytes += self.outBlock.size()
        # 在sendOut中写入文件名以及文件名和文件的大小,大小都是以字节为单位的。

        sendOut.device().seek(0)
        sendOut.writeInt64(self.totalBytes)
        sendOut.writeInt64(self.outBlock.size() - 2)
        # QIODevice读写位置移动到0。然后分别写入总的大小和文件名大小。

        self.bytesToWrite = self.totalBytes - self.clientConnection.write(
            self.outBlock)
        # 待传输文件的大小。

        self.outBlock.resize(0)
        # outBlock清零。

    def updateClientProgress(self, numBytes):
        """
        发送进度显示
        """
        qApp.processEvents()
        # 长时间工作用,以免窗口假死

        self.bytesWritten += numBytes
        if self.bytesWritten > 0:
            self.block = self.localFile.read(
                min(self.bytesToWrite, self.payloadSize))
            self.bytesToWrite -= self.clientConnection.write(self.block)
        else:
            self.localFile.close()
        # 当我们待写入的字节数大于0时,我们每次读取的数据都是小于等于self.payloadSize的,这个self.payloadSize我们定义是64KB。
        # self.bytesToWrite每次减少连接写的数据量大小。
        # 要是待写入的字节数小于等于0,则关闭文件。

        byteSent = self.bytesWritten / (1024 * 1024)
        # 已经写了多少文件
        useTime = self.time.elapsed() / 1000
        # 传输用了多长时间
        speed = self.bytesWritten / useTime / (1024 * 1024)
        # 传输速度
        total = self.totalBytes / (1024 * 1024)
        # 总大小
        left = (total - byteSent) / speed
        # 表示剩余时间

        if byteSent < 0.01:
            byteSent = self.bytesWritten / 1024
            speed = self.bytesWritten / useTime / 1024
            total = self.totalBytes / 1024
            if left > 0:
                sendInfo = "已发送 {0:.2f}KB({1:.2f}KB/s)\n共{2:.2f}KB 已用时:{3:.1f}秒\n 估计剩余时间:{4:.1f}秒".format(
                    byteSent, speed, total, useTime, left)
            else:
                sendInfo = "已发送 {0:.2f}KB({1:.2f}KB/s)\n共{2:.2f}KB 用时:{3:.1f}秒\n".format(
                    byteSent, speed, total, useTime)
        else:
            if left > 0:
                sendInfo = "已发送 {0:.2f}MB({1:.2f}MB/s)\n共{2:.2f}MB 已用时:{3:.1f}秒\n 估计剩余时间:{4:.1f}秒".format(
                    byteSent, speed, total, useTime, left)
            else:
                sendInfo = "已发送 {0:.2f}MB({1:.2f}MB/s)\n共{2:.2f}MB 用时:{3:.1f}秒\n".format(
                    byteSent, speed, total, useTime)

        self.progressBar.setMaximum(total)
        self.progressBar.setValue(byteSent)

        if self.bytesWritten == self.totalBytes:
            self.serverCloseBtn.setText("关闭")
        # 进度条显示的方式,以及当传输的字节数等于总的字节数的时候,按钮就显示关闭。

        self.serverStatuslabel.setText(sendInfo)

    @pyqtSlot()
    def on_serverOpenBtn_clicked(self):
        """
        打开文件准备发送
        """
        self.fileName = QFileDialog.getOpenFileName(self, '打开文件', './')[0]
        if self.fileName:
            self.theFileName = self.fileName.split("/")[-1]
            self.serverStatuslabel.setText("要传送的文件为:{}".format(
                self.theFileName))
            self.serverSendBtn.setEnabled(True)
            self.serverOpenBtn.setEnabled(False)

    @pyqtSlot()
    def on_serverSendBtn_clicked(self):
        """
        发送文件,等待接收
        """
        if not (self.tcpServer.listen(QHostAddress.Any, self.tcpPort)):
            errorMsg = self.tcpServer.errorString()
            QMessageBox.warning(self, "错误", "发送失败:\n {}".format(errorMsg))
            self.TcpServer.close()
            return

        self.serverStatuslabel.setText("等待对方接收... ...")
        self.serverSendBtn.setEnabled(False)
        self.sendFileName.emit(self.theFileName)

    @pyqtSlot()
    def on_serverCloseBtn_clicked(self):
        """
        取消或者关闭
        """
        if self.tcpServer.isListening():
            self.tcpServer.close()
            if self.localFile.isOpen():
                self.localFile.close()
            self.clientConnection.abort()

        if self.serverCloseBtn.text() == "取消":
            self.serverCloseBtn.setText("关闭")
        else:
            self.close()
            self.serverOpenBtn.setEnabled(True)
            self.serverSendBtn.setEnabled(False)
            self.progressBar.reset()
            self.totalBytes = 0
            self.bytesWritten = 0
            self.bytesToWrite = 0
            self.serverStatuslabel.setText("请选择要传送的文件")
Exemple #10
0
class NSwapFile(QObject):
    """
    In case Ninja-IDE crash, this can be used to recover the lost data.

    When the user begins to edit an existing file on the disk, this object
    creates a swap file and activates a timer that will execute a function,
    that will update that swap file as soon as the timeout ends (by default,
    is 15 seconds).
    The swap file is deleted when the original file is saved or closed.
    When system or Ninja crash, the swap file exists on disk and Ninja will
    used to recover the lost data.
    """

    canBeRecovered = pyqtSignal()

    def __init__(self, neditable):
        QObject.__init__(self)
        self._neditable = neditable
        self.__swap_file = QFile()
        self.__stream = QTextStream()

        # Activate timer when user typing
        self.__timer = QTimer()
        self.__timer.setSingleShot(True)

        self.__timer.timeout.connect(self._finish_typing)
        self._neditable.fileLoaded.connect(self._file_loaded)
        self._neditable.fileSaved.connect(self._file_saved)

        self.init(tracking=True)

    def init(self, tracking):
        if tracking:
            self._neditable.editor.textChanged.connect(self._start_typing)
            self._neditable.fileClosing.connect(self._file_closed)
        else:
            self._neditable.editor.textChanged.disconnect(self._start_typing)
            self._neditable.fileClosing.disconnect(self._file_closed)

    def _file_closed(self):
        """Editor was closed normally, now remove swap file"""

        self.__remove()

    def _file_saved(self):
        """If file is saved, remove swap file"""

        # Remove old swap file and set the name for the new swap file
        self.__remove()
        self.__update_filename()

    def __remove(self):
        """Remove swap file"""

        if self.__swap_file.fileName() and self.__swap_file.exists():
            self.__stream.setDevice(None)
            self.__swap_file.close()
            self.__swap_file.remove()

    def _file_loaded(self):
        """This slot is executed when a file is loaded on the editor and
        look for swap file, if exists then can be recover"""

        self.__update_filename()
        if self.__swap_file.exists():
            # In recovery process can't edit
            self._neditable.editor.setReadOnly(True)
            # Ok, can be recover
            self.canBeRecovered.emit()

    def __update_filename(self):
        # First clear filename
        self.__swap_file.setFileName("")
        # Get new path
        filename = self.filename()
        self.__swap_file.setFileName(filename)

    def _start_typing(self):
        # Skip if editor is not modified
        if not self._neditable.editor.is_modified:
            return
        # No swap file, no work
        if not self.__swap_file.fileName():
            return
        # Create the file
        if not self.__swap_file.exists():
            self.__swap_file.open(QIODevice.WriteOnly)
            permissions = QFileDevice.ReadOwner | QFileDevice.WriteOwner
            self.__swap_file.setPermissions(permissions)
            self.__stream.setDevice(self.__swap_file)

        if self.__timer.isActive():
            self.__timer.stop()
        # Write swap file to the disk every 10 seconds by default
        self.__timer.start(settings.SWAP_FILE_INTERVAL * 1000)

    def _finish_typing(self):
        if not self.__swap_file.isOpen():
            return
        logger.debug("Now write the swap file...")
        text = self._neditable.editor.text
        self.__swap_file.write(text.encode())
        self.__swap_file.flush()

    def filename(self):
        """Returns the filename for swap file"""

        path, name = os.path.split(
            os.path.join(SWAP_PATH, self._neditable.nfile.file_name))
        filename = os.path.join(path, "%s.ninja-swap" % name)
        return filename

    def recover(self):
        self._neditable.editor.setReadOnly(False)
        # Disconnect signals
        self.init(tracking=False)

        self.__stream.setDevice(self.__swap_file)
        if not self.__swap_file.open(QIODevice.ReadOnly):
            logger.warning("Can't open swap file")
            return
        # Ok
        data = []
        append = data.append
        while not self.__stream.atEnd():
            line = self.__stream.readLine()
            append(line)

        # Set data in the editor
        self._neditable.editor.text = "\n".join(data)
        self._neditable.document.setModified(True)

        # Close swap file
        self.__stream.setDevice(None)
        self.__swap_file.close()
        # Reconnect signals
        self.init(tracking=True)

    def discard(self):
        self._neditable.editor.setReadOnly(False)
        # Remove swap file
        self.__remove()
Exemple #11
0
class CardPDFWriter:
    RESOLUTION = 300  # 300dpi

    @staticmethod
    def mm2pix(args):
        return [x * (CardPDFWriter.RESOLUTION / 25.4) for x in args]

    def __init__(self,
                 file_name,
                 card_format,
                 paper_format,
                 separation=[0.8, 0.8]):
        self.cardFormat = self.mm2pix(card_format)
        self.paperFormat = self.mm2pix(paper_format)
        self.separation = self.mm2pix(separation)
        self.paperFormatMM = paper_format
        self.file = QFile(str(file_name))
        self.file.open(QIODevice.WriteOnly)

        self.writer = QPdfWriter(self.file)
        self.writer.setResolution(self.RESOLUTION)
        self.writer.setPageSizeMM(QSizeF(*self.paperFormatMM))
        self.writer.setPageMargins(QMarginsF(0, 0, 0, 0))

        self.painter = QPainter(self.writer)
        self.pen = QPen()
        self.pen.setWidth(self.mm2pix([1])[0])
        self.painter.setPen(self.pen)

        self.bleeding = [0, 0]
        self.bleeding[0] = (self.paperFormat[0] %
                            int(self.cardFormat[0] + self.separation[0])) / 2
        self.bleeding[1] = (self.paperFormat[1] %
                            int(self.cardFormat[1] + self.separation[1])) / 2
        self.cursor = self.bleeding[:]

        self._setupPage()

    def _setupPage(self):
        # self.writer.setPageSizeMM(QSizeF(*self.paperFormatMM))
        # self.writer.setPageMargins(QMarginsF(0, 0, 0, 0))
        # Horizontal lines
        pos = self.bleeding[0] - self.separation[0] / 2
        while (pos < self.paperFormat[0]):
            self.painter.drawLine(pos, 0, pos, self.paperFormat[1])
            pos += self.cardFormat[0] + self.separation[0]

        # Vertical lines
        pos = self.bleeding[1] - self.separation[1] / 2
        while (pos < self.paperFormat[1]):
            self.painter.drawLine(0, pos, self.paperFormat[0], pos)
            pos += self.cardFormat[1] + self.separation[1]

    @assert_file_open
    def addPage(self):
        self.writer.newPage()
        self._setupPage()

    @assert_file_open
    def addCard(self, card, num_copies):
        for _ in range(num_copies):
            if self.cursor[1] > (self.paperFormat[1] - self.bleeding[1] -
                                 self.cardFormat[1]):
                self.cursor = self.bleeding[:]
                self.addPage()

            self.painter.drawPixmap(*self.cursor, *self.cardFormat, card)
            self.cursor[0] += self.cardFormat[0] + self.separation[0]

            if self.cursor[0] > (self.paperFormat[0] - self.bleeding[0] -
                                 self.cardFormat[0]):
                self.cursor[0] = self.bleeding[0]
                self.cursor[1] += self.cardFormat[1] + self.separation[1]

    @assert_file_open
    def close(self):
        self.painter.end()
        self.file.flush()
        self.file.close()

    def isOpen(self):
        return self.file.isOpen()
Exemple #12
0
class DownloadItem(QWidget, Ui_DownloadItem):
    """
    Class implementing a widget controlling a download.
    
    @signal statusChanged() emitted upon a status change of a download
    @signal downloadFinished() emitted when a download finished
    @signal progress(int, int) emitted to signal the download progress
    """
    statusChanged = pyqtSignal()
    downloadFinished = pyqtSignal()
    progress = pyqtSignal(int, int)
    
    Downloading = 0
    DownloadSuccessful = 1
    DownloadCancelled = 2
    
    def __init__(self, reply=None, requestFilename=False, webPage=None,
                 download=False, parent=None, mainWindow=None):
        """
        Constructor
        
        @keyparam reply reference to the network reply object (QNetworkReply)
        @keyparam requestFilename flag indicating to ask the user for a
            filename (boolean)
        @keyparam webPage reference to the web page object the download
            originated from (QWebPage)
        @keyparam download flag indicating a download operation (boolean)
        @keyparam parent reference to the parent widget (QWidget)
        @keyparam mainWindow reference to the main window (HelpWindow)
        """
        super(DownloadItem, self).__init__(parent)
        self.setupUi(self)
        
        p = self.infoLabel.palette()
        p.setColor(QPalette.Text, Qt.darkGray)
        self.infoLabel.setPalette(p)
        
        self.progressBar.setMaximum(0)
        
        self.__isFtpDownload = reply is not None and \
            reply.url().scheme() == "ftp"
        
        self.tryAgainButton.setIcon(UI.PixmapCache.getIcon("restart.png"))
        self.tryAgainButton.setEnabled(False)
        self.tryAgainButton.setVisible(False)
        self.stopButton.setIcon(UI.PixmapCache.getIcon("stopLoading.png"))
        self.pauseButton.setIcon(UI.PixmapCache.getIcon("pause.png"))
        self.openButton.setIcon(UI.PixmapCache.getIcon("open.png"))
        self.openButton.setEnabled(False)
        self.openButton.setVisible(False)
        if self.__isFtpDownload:
            self.stopButton.setEnabled(False)
            self.stopButton.setVisible(False)
            self.pauseButton.setEnabled(False)
            self.pauseButton.setVisible(False)
        
        self.__state = DownloadItem.Downloading
        
        icon = self.style().standardIcon(QStyle.SP_FileIcon)
        self.fileIcon.setPixmap(icon.pixmap(48, 48))
        
        self.__mainWindow = mainWindow
        self.__reply = reply
        self.__requestFilename = requestFilename
        self.__page = webPage
        self.__pageUrl = webPage and webPage.mainFrame().url() or QUrl()
        self.__toDownload = download
        self.__bytesReceived = 0
        self.__bytesTotal = -1
        self.__downloadTime = QTime()
        self.__output = QFile()
        self.__fileName = ""
        self.__originalFileName = ""
        self.__startedSaving = False
        self.__finishedDownloading = False
        self.__gettingFileName = False
        self.__canceledFileSelect = False
        self.__autoOpen = False
        
        self.__sha1Hash = QCryptographicHash(QCryptographicHash.Sha1)
        self.__md5Hash = QCryptographicHash(QCryptographicHash.Md5)
        
        if not requestFilename:
            self.__requestFilename = \
                Preferences.getUI("RequestDownloadFilename")
        
        self.__initialize()
    
    def __initialize(self, tryAgain=False):
        """
        Private method to (re)initialize the widget.
        
        @param tryAgain flag indicating a retry (boolean)
        """
        if self.__reply is None:
            return
        
        self.__startedSaving = False
        self.__finishedDownloading = False
        self.__bytesReceived = 0
        self.__bytesTotal = -1
        
        self.__sha1Hash.reset()
        self.__md5Hash.reset()
        
        # start timer for the download estimation
        self.__downloadTime.start()
        
        # attach to the reply object
        self.__url = self.__reply.url()
        self.__reply.setParent(self)
        self.__reply.setReadBufferSize(16 * 1024 * 1024)
        self.__reply.readyRead.connect(self.__readyRead)
        self.__reply.error.connect(self.__networkError)
        self.__reply.downloadProgress.connect(self.__downloadProgress)
        self.__reply.metaDataChanged.connect(self.__metaDataChanged)
        self.__reply.finished.connect(self.__finished)
        
        # reset info
        self.infoLabel.clear()
        self.progressBar.setValue(0)
        self.__getFileName()
        
        if self.__reply.error() != QNetworkReply.NoError:
            self.__networkError()
            self.__finished()
    
    def __getFileName(self):
        """
        Private method to get the file name to save to from the user.
        """
        if self.__gettingFileName:
            return
        
        import Helpviewer.HelpWindow
        downloadDirectory = Helpviewer.HelpWindow.HelpWindow\
            .downloadManager().downloadDirectory()
        
        if self.__fileName:
            fileName = self.__fileName
            originalFileName = self.__originalFileName
            self.__toDownload = True
            ask = False
        else:
            defaultFileName, originalFileName = \
                self.__saveFileName(downloadDirectory)
            fileName = defaultFileName
            self.__originalFileName = originalFileName
            ask = True
        self.__autoOpen = False
        if not self.__toDownload:
            from .DownloadAskActionDialog import DownloadAskActionDialog
            url = self.__reply.url()
            dlg = DownloadAskActionDialog(
                QFileInfo(originalFileName).fileName(),
                self.__reply.header(QNetworkRequest.ContentTypeHeader),
                "{0}://{1}".format(url.scheme(), url.authority()),
                self)
            if dlg.exec_() == QDialog.Rejected or dlg.getAction() == "cancel":
                self.progressBar.setVisible(False)
                self.__reply.close()
                self.on_stopButton_clicked()
                self.filenameLabel.setText(
                    self.tr("Download canceled: {0}").format(
                        QFileInfo(defaultFileName).fileName()))
                self.__canceledFileSelect = True
                return
            
            if dlg.getAction() == "scan":
                self.__mainWindow.requestVirusTotalScan(url)
                
                self.progressBar.setVisible(False)
                self.__reply.close()
                self.on_stopButton_clicked()
                self.filenameLabel.setText(
                    self.tr("VirusTotal scan scheduled: {0}").format(
                        QFileInfo(defaultFileName).fileName()))
                self.__canceledFileSelect = True
                return
            
            self.__autoOpen = dlg.getAction() == "open"
            if PYQT_VERSION_STR >= "5.0.0":
                from PyQt5.QtCore import QStandardPaths
                tempLocation = QStandardPaths.standardLocations(
                    QStandardPaths.TempLocation)[0]
            else:
                from PyQt5.QtGui import QDesktopServices
                tempLocation = QDesktopServices.storageLocation(
                    QDesktopServices.TempLocation)
            fileName = tempLocation + '/' + \
                QFileInfo(fileName).completeBaseName()
        
        if ask and not self.__autoOpen and self.__requestFilename:
            self.__gettingFileName = True
            fileName = E5FileDialog.getSaveFileName(
                None,
                self.tr("Save File"),
                defaultFileName,
                "")
            self.__gettingFileName = False
            if not fileName:
                self.progressBar.setVisible(False)
                self.__reply.close()
                self.on_stopButton_clicked()
                self.filenameLabel.setText(
                    self.tr("Download canceled: {0}")
                        .format(QFileInfo(defaultFileName).fileName()))
                self.__canceledFileSelect = True
                return
        
        fileInfo = QFileInfo(fileName)
        Helpviewer.HelpWindow.HelpWindow.downloadManager()\
            .setDownloadDirectory(fileInfo.absoluteDir().absolutePath())
        self.filenameLabel.setText(fileInfo.fileName())
        
        self.__output.setFileName(fileName + ".part")
        self.__fileName = fileName
        
        # check file path for saving
        saveDirPath = QFileInfo(self.__fileName).dir()
        if not saveDirPath.exists():
            if not saveDirPath.mkpath(saveDirPath.absolutePath()):
                self.progressBar.setVisible(False)
                self.on_stopButton_clicked()
                self.infoLabel.setText(self.tr(
                    "Download directory ({0}) couldn't be created.")
                    .format(saveDirPath.absolutePath()))
                return
        
        self.filenameLabel.setText(QFileInfo(self.__fileName).fileName())
        if self.__requestFilename:
            self.__readyRead()
    
    def __saveFileName(self, directory):
        """
        Private method to calculate a name for the file to download.
        
        @param directory name of the directory to store the file into (string)
        @return proposed filename and original filename (string, string)
        """
        path = parseContentDisposition(self.__reply)
        info = QFileInfo(path)
        baseName = info.completeBaseName()
        endName = info.suffix()
        
        origName = baseName
        if endName:
            origName += '.' + endName
        
        name = directory + baseName
        if endName:
            name += '.' + endName
            if not self.__requestFilename:
                # do not overwrite, if the user is not being asked
                i = 1
                while QFile.exists(name):
                    # file exists already, don't overwrite
                    name = directory + baseName + ('-{0:d}'.format(i))
                    if endName:
                        name += '.' + endName
                    i += 1
        return name, origName
    
    def __open(self):
        """
        Private slot to open the downloaded file.
        """
        info = QFileInfo(self.__output)
        url = QUrl.fromLocalFile(info.absoluteFilePath())
        QDesktopServices.openUrl(url)
    
    @pyqtSlot()
    def on_tryAgainButton_clicked(self):
        """
        Private slot to retry the download.
        """
        self.retry()
    
    def retry(self):
        """
        Public slot to retry the download.
        """
        if not self.tryAgainButton.isEnabled():
            return
        
        self.tryAgainButton.setEnabled(False)
        self.tryAgainButton.setVisible(False)
        self.openButton.setEnabled(False)
        self.openButton.setVisible(False)
        if not self.__isFtpDownload:
            self.stopButton.setEnabled(True)
            self.stopButton.setVisible(True)
            self.pauseButton.setEnabled(True)
            self.pauseButton.setVisible(True)
        self.progressBar.setVisible(True)
        
        if self.__page:
            nam = self.__page.networkAccessManager()
        else:
            import Helpviewer.HelpWindow
            nam = Helpviewer.HelpWindow.HelpWindow.networkAccessManager()
        reply = nam.get(QNetworkRequest(self.__url))
        if self.__output.exists():
            self.__output.remove()
        self.__output = QFile()
        self.__reply = reply
        self.__initialize(tryAgain=True)
        self.__state = DownloadItem.Downloading
        self.statusChanged.emit()
    
    @pyqtSlot(bool)
    def on_pauseButton_clicked(self, checked):
        """
        Private slot to pause the download.
        
        @param checked flag indicating the state of the button (boolean)
        """
        if checked:
            self.__reply.readyRead.disconnect(self.__readyRead)
            self.__reply.setReadBufferSize(16 * 1024)
        else:
            self.__reply.readyRead.connect(self.__readyRead)
            self.__reply.setReadBufferSize(16 * 1024 * 1024)
            self.__readyRead()
    
    @pyqtSlot()
    def on_stopButton_clicked(self):
        """
        Private slot to stop the download.
        """
        self.cancelDownload()
    
    def cancelDownload(self):
        """
        Public slot to stop the download.
        """
        self.setUpdatesEnabled(False)
        if not self.__isFtpDownload:
            self.stopButton.setEnabled(False)
            self.stopButton.setVisible(False)
            self.pauseButton.setEnabled(False)
            self.pauseButton.setVisible(False)
        self.tryAgainButton.setEnabled(True)
        self.tryAgainButton.setVisible(True)
        self.openButton.setEnabled(False)
        self.openButton.setVisible(False)
        self.setUpdatesEnabled(True)
        self.__state = DownloadItem.DownloadCancelled
        self.__reply.abort()
        self.downloadFinished.emit()
    
    @pyqtSlot()
    def on_openButton_clicked(self):
        """
        Private slot to open the downloaded file.
        """
        self.openFile()
    
    def openFile(self):
        """
        Public slot to open the downloaded file.
        """
        info = QFileInfo(self.__fileName)
        url = QUrl.fromLocalFile(info.absoluteFilePath())
        QDesktopServices.openUrl(url)
    
    def openFolder(self):
        """
        Public slot to open the folder containing the downloaded file.
        """
        info = QFileInfo(self.__fileName)
        url = QUrl.fromLocalFile(info.absolutePath())
        QDesktopServices.openUrl(url)
    
    def __readyRead(self):
        """
        Private slot to read the available data.
        """
        if self.__requestFilename and not self.__output.fileName():
            return
        
        if not self.__output.isOpen():
            # in case someone else has already put a file there
            if not self.__requestFilename:
                self.__getFileName()
            if not self.__output.open(QIODevice.WriteOnly):
                self.infoLabel.setText(
                    self.tr("Error opening save file: {0}")
                    .format(self.__output.errorString()))
                self.on_stopButton_clicked()
                self.statusChanged.emit()
                return
            self.statusChanged.emit()
        
        buffer = self.__reply.readAll()
        self.__sha1Hash.addData(buffer)
        self.__md5Hash.addData(buffer)
        bytesWritten = self.__output.write(buffer)
        if bytesWritten == -1:
            self.infoLabel.setText(
                self.tr("Error saving: {0}")
                    .format(self.__output.errorString()))
            self.on_stopButton_clicked()
        else:
            self.__startedSaving = True
            if self.__finishedDownloading:
                self.__finished()
    
    def __networkError(self):
        """
        Private slot to handle a network error.
        """
        self.infoLabel.setText(
            self.tr("Network Error: {0}")
                .format(self.__reply.errorString()))
        self.tryAgainButton.setEnabled(True)
        self.tryAgainButton.setVisible(True)
        self.downloadFinished.emit()
    
    def __metaDataChanged(self):
        """
        Private slot to handle a change of the meta data.
        """
        locationHeader = self.__reply.header(QNetworkRequest.LocationHeader)
        if locationHeader and locationHeader.isValid():
            self.__url = QUrl(locationHeader)
            import Helpviewer.HelpWindow
            self.__reply = Helpviewer.HelpWindow.HelpWindow\
                .networkAccessManager().get(QNetworkRequest(self.__url))
            self.__initialize()
    
    def __downloadProgress(self, bytesReceived, bytesTotal):
        """
        Private method to show the download progress.
        
        @param bytesReceived number of bytes received (integer)
        @param bytesTotal number of total bytes (integer)
        """
        self.__bytesReceived = bytesReceived
        self.__bytesTotal = bytesTotal
        currentValue = 0
        totalValue = 0
        if bytesTotal > 0:
            currentValue = bytesReceived * 100 / bytesTotal
            totalValue = 100
        self.progressBar.setValue(currentValue)
        self.progressBar.setMaximum(totalValue)
        
        self.progress.emit(currentValue, totalValue)
        self.__updateInfoLabel()
    
    def bytesTotal(self):
        """
        Public method to get the total number of bytes of the download.
        
        @return total number of bytes (integer)
        """
        if self.__bytesTotal == -1:
            self.__bytesTotal = self.__reply.header(
                QNetworkRequest.ContentLengthHeader)
            if self.__bytesTotal is None:
                self.__bytesTotal = -1
        return self.__bytesTotal
    
    def bytesReceived(self):
        """
        Public method to get the number of bytes received.
        
        @return number of bytes received (integer)
        """
        return self.__bytesReceived
    
    def remainingTime(self):
        """
        Public method to get an estimation for the remaining time.
        
        @return estimation for the remaining time (float)
        """
        if not self.downloading():
            return -1.0
        
        if self.bytesTotal() == -1:
            return -1.0
        
        cSpeed = self.currentSpeed()
        if cSpeed != 0:
            timeRemaining = (self.bytesTotal() - self.bytesReceived()) / cSpeed
        else:
            timeRemaining = 1
        
        # ETA should never be 0
        if timeRemaining == 0:
            timeRemaining = 1
        
        return timeRemaining
    
    def currentSpeed(self):
        """
        Public method to get an estimation for the download speed.
        
        @return estimation for the download speed (float)
        """
        if not self.downloading():
            return -1.0
        
        return self.__bytesReceived * 1000.0 / self.__downloadTime.elapsed()
    
    def __updateInfoLabel(self):
        """
        Private method to update the info label.
        """
        if self.__reply.error() != QNetworkReply.NoError:
            return
        
        bytesTotal = self.bytesTotal()
        running = not self.downloadedSuccessfully()
        
        speed = self.currentSpeed()
        timeRemaining = self.remainingTime()
        
        info = ""
        if running:
            remaining = ""
            
            if bytesTotal > 0:
                remaining = timeString(timeRemaining)
            
            info = self.tr("{0} of {1} ({2}/sec)\n{3}")\
                .format(
                    dataString(self.__bytesReceived),
                    bytesTotal == -1 and self.tr("?")
                    or dataString(bytesTotal),
                    dataString(int(speed)),
                    remaining)
        else:
            if self.__bytesReceived == bytesTotal or bytesTotal == -1:
                info = self.tr("{0} downloaded\nSHA1: {1}\nMD5: {2}")\
                    .format(dataString(self.__output.size()),
                            str(self.__sha1Hash.result().toHex(),
                                encoding="ascii"),
                            str(self.__md5Hash.result().toHex(),
                                encoding="ascii")
                            )
            else:
                info = self.tr("{0} of {1} - Stopped")\
                    .format(dataString(self.__bytesReceived),
                            dataString(bytesTotal))
        self.infoLabel.setText(info)
    
    def downloading(self):
        """
        Public method to determine, if a download is in progress.
        
        @return flag indicating a download is in progress (boolean)
        """
        return self.__state == DownloadItem.Downloading
    
    def downloadedSuccessfully(self):
        """
        Public method to check for a successful download.
        
        @return flag indicating a successful download (boolean)
        """
        return self.__state == DownloadItem.DownloadSuccessful
    
    def downloadCanceled(self):
        """
        Public method to check, if the download was cancelled.
        
        @return flag indicating a canceled download (boolean)
        """
        return self.__state == DownloadItem.DownloadCancelled
    
    def __finished(self):
        """
        Private slot to handle the download finished.
        """
        self.__finishedDownloading = True
        if not self.__startedSaving:
            return
        
        noError = self.__reply.error() == QNetworkReply.NoError
        
        self.progressBar.setVisible(False)
        if not self.__isFtpDownload:
            self.stopButton.setEnabled(False)
            self.stopButton.setVisible(False)
            self.pauseButton.setEnabled(False)
            self.pauseButton.setVisible(False)
        self.openButton.setEnabled(noError)
        self.openButton.setVisible(noError)
        self.__output.close()
        if QFile.exists(self.__fileName):
            QFile.remove(self.__fileName)
        self.__output.rename(self.__fileName)
        self.__updateInfoLabel()
        self.__state = DownloadItem.DownloadSuccessful
        self.statusChanged.emit()
        self.downloadFinished.emit()
        
        if self.__autoOpen:
            self.__open()
    
    def canceledFileSelect(self):
        """
        Public method to check, if the user canceled the file selection.
        
        @return flag indicating cancellation (boolean)
        """
        return self.__canceledFileSelect
    
    def setIcon(self, icon):
        """
        Public method to set the download icon.
        
        @param icon reference to the icon to be set (QIcon)
        """
        self.fileIcon.setPixmap(icon.pixmap(48, 48))
    
    def fileName(self):
        """
        Public method to get the name of the output file.
        
        @return name of the output file (string)
        """
        return self.__fileName
    
    def absoluteFilePath(self):
        """
        Public method to get the absolute path of the output file.
        
        @return absolute path of the output file (string)
        """
        return QFileInfo(self.__fileName).absoluteFilePath()
    
    def getData(self):
        """
        Public method to get the relevant download data.
        
        @return tuple of URL, save location, flag and the
            URL of the related web page (QUrl, string, boolean,QUrl)
        """
        return (self.__url, QFileInfo(self.__fileName).filePath(),
                self.downloadedSuccessfully(), self.__pageUrl)
    
    def setData(self, data):
        """
        Public method to set the relevant download data.
        
        @param data tuple of URL, save location, flag and the
            URL of the related web page (QUrl, string, boolean, QUrl)
        """
        self.__url = data[0]
        self.__fileName = data[1]
        self.__pageUrl = data[3]
        self.__isFtpDownload = self.__url.scheme() == "ftp"
        
        self.filenameLabel.setText(QFileInfo(self.__fileName).fileName())
        self.infoLabel.setText(self.__fileName)
        
        self.stopButton.setEnabled(False)
        self.stopButton.setVisible(False)
        self.pauseButton.setEnabled(False)
        self.pauseButton.setVisible(False)
        self.openButton.setEnabled(data[2])
        self.openButton.setVisible(data[2])
        self.tryAgainButton.setEnabled(not data[2])
        self.tryAgainButton.setVisible(not data[2])
        if data[2]:
            self.__state = DownloadItem.DownloadSuccessful
        else:
            self.__state = DownloadItem.DownloadCancelled
        self.progressBar.setVisible(False)
    
    def getInfoData(self):
        """
        Public method to get the text of the info label.
        
        @return text of the info label (string)
        """
        return self.infoLabel.text()
    
    def getPageUrl(self):
        """
        Public method to get the URL of the download page.
        
        @return URL of the download page (QUrl)
        """
        return self.__pageUrl
class TcpC(QDialog, Ui_TcpClient):
    """
    Class documentation goes here.
    """
    def __init__(self, parent=None):
        """
        Constructor
        
        @param parent reference to the parent widget
        @type QWidget
        """
        super(TcpC, self).__init__(parent)
        self.setupUi(self)
        self.TotalBytes = 0
        self.bytesReceive = 0
        self.fileNameSize = 0
        self.bytesToReceive = 0
        self.fileName = ""
        self.tcpClient = QTcpSocket(self)
        self.tcpPort = 7788
        self.time = QTime()

        self.tcpClient.readyRead.connect(self.readMessage)
        self.tcpClient.error.connect(self.displayError)

    def setHostAddress(self, address):
        """
        设置服务器地址
        """
        self.hostAddress = address
        self.newConnect()

    def setFileName(self, file):
        """
        待接收文件的文件名
        """
        self.localFile = QFile(file)

    def closeEvent(self, event):
        """
        关闭事件
        """
        self.on_tcpClientCloseBtn_clicked()

    def newConnect(self):
        """
        连接服务器并开始计时
        """
        self.tcpClient.abort()
        self.tcpClient.connectToHost(self.hostAddress, self.tcpPort)
        self.time.start()

    def readMessage(self):
        """
        读取文件数据
        """
        receiver = QDataStream(self.tcpClient)
        receiver.setVersion(QDataStream.Qt_5_4)

        if self.bytesReceive <= 2:
            if self.tcpClient.bytesAvailable() >= 2 and self.fileNameSize == 0:
                self.TotalBytes = receiver.readInt64()
                self.fileNameSize = receiver.readInt64()
                self.bytesReceive += 2

            if self.tcpClient.bytesAvailable() >= self.fileNameSize and self.fileNameSize != 0:
                self.fileName = receiver.readQString()
                self.bytesReceive += self.fileNameSize
                if not(self.localFile.open(QFile.WriteOnly)):
                    QMessageBox.warning(self, "应用程序", "无法读取文件 {}:\n {}".format(self.fileName, self.localFile.errorString()))
                    return
            else:
                return

        if self.bytesReceive < self.TotalBytes:
            self.bytesReceive += self.tcpClient.bytesAvailable()
            inBlock = self.tcpClient.readAll()
            self.localFile.write(inBlock)
            inBlock.resize(0)

        useTime = self.time.elapsed() / 1000
        
        bytesReceived = self.bytesReceive / (1024*1024)
        speed = bytesReceived / useTime
        total = self.TotalBytes / (1024*1024)
        left = (total - bytesReceived) / speed

        if bytesReceived < 0.01:
            bytesReceived = self.bytesReceive / 1024
            speed = bytesReceived / useTime / 1024
            total = self.TotalBytes / 1024
            if left > 0:
                msg = "已接收 {0:.2f} KB ({1:.2f}KB/s)\n共{2:.2f}KB.已用时:{3:.1f}秒\n估计剩余时间:{4:.1f}秒".format(bytesReceived, speed, total, useTime, left)
            else:
                msg = "已接收 {0:.2f} KB ({1:.2f}KB/s)\n共{2:.2f}KB.已用时:{3:.1f}秒\n".format(bytesReceived, speed, total, useTime)

        else:
            if left > 0:
                msg = "已接收 {0:.2f} MB ({1:.2f}MB/s)\n共{2:.2f}MB.已用时:{3:.1f}秒\n估计剩余时间:{4:.1f}秒".format(bytesReceived, speed, total, useTime, left)
            else:
                msg = "已接收 {0:.2f} MB ({1:.2f}MB/s)\n共{2:.2f}MB.已用时:{3:.1f}秒\n".format(bytesReceived, speed, total, useTime)

        self.progressBar.setMaximum(total)
        self.progressBar.setValue(bytesReceived)

        self.tcpClientStatuslabel.setText(msg)
        
        if self.bytesReceive == self.TotalBytes:
            self.localFile.close()
            self.tcpClient.close()
            self.tcpClientStatuslabel.setText("接收文件{}完毕".format(self.fileName))
            self.tcpClientBtn.setEnabled(False)


    def displayError(self, socketError):
        """
        显示错误
        """
        if socketError == QAbstractSocket.RemoteHostClosedError:
            pass
        else:
            errorMsg = self.tcpClient.errorString()
            QMessageBox.warning(self, "应用程序", errorMsg)
            return

    @pyqtSlot()
    def on_tcpClientBtn_clicked(self):
        """
        取消接收
        """
        self.tcpClient.abort()
        if self.localFile.isOpen():
            self.localFile.close()
        
        self.tcpClientBtn.setEnabled(False)
    
    @pyqtSlot()
    def on_tcpClientCloseBtn_clicked(self):
        """
        关闭
        """
        self.tcpClient.abort()
        if self.localFile.isOpen():
            self.localFile.close()
        self.close()
        self.tcpClientBtn.setEnabled(True)
Exemple #14
0
class DownloadItem(QWidget, Ui_DownloadItem):
    """
    Class implementing a widget controlling a download.
    
    @signal statusChanged() emitted upon a status change of a download
    @signal downloadFinished() emitted when a download finished
    @signal progress(int, int) emitted to signal the download progress
    """
    statusChanged = pyqtSignal()
    downloadFinished = pyqtSignal()
    progress = pyqtSignal(int, int)

    Downloading = 0
    DownloadSuccessful = 1
    DownloadCancelled = 2

    def __init__(self,
                 reply=None,
                 requestFilename=False,
                 webPage=None,
                 download=False,
                 parent=None,
                 mainWindow=None):
        """
        Constructor
        
        @keyparam reply reference to the network reply object (QNetworkReply)
        @keyparam requestFilename flag indicating to ask the user for a
            filename (boolean)
        @keyparam webPage reference to the web page object the download
            originated from (QWebPage)
        @keyparam download flag indicating a download operation (boolean)
        @keyparam parent reference to the parent widget (QWidget)
        @keyparam mainWindow reference to the main window (HelpWindow)
        """
        super(DownloadItem, self).__init__(parent)
        self.setupUi(self)

        p = self.infoLabel.palette()
        p.setColor(QPalette.Text, Qt.darkGray)
        self.infoLabel.setPalette(p)

        self.progressBar.setMaximum(0)

        self.__isFtpDownload = reply is not None and \
            reply.url().scheme() == "ftp"

        self.tryAgainButton.setIcon(UI.PixmapCache.getIcon("restart.png"))
        self.tryAgainButton.setEnabled(False)
        self.tryAgainButton.setVisible(False)
        self.stopButton.setIcon(UI.PixmapCache.getIcon("stopLoading.png"))
        self.pauseButton.setIcon(UI.PixmapCache.getIcon("pause.png"))
        self.openButton.setIcon(UI.PixmapCache.getIcon("open.png"))
        self.openButton.setEnabled(False)
        self.openButton.setVisible(False)
        if self.__isFtpDownload:
            self.stopButton.setEnabled(False)
            self.stopButton.setVisible(False)
            self.pauseButton.setEnabled(False)
            self.pauseButton.setVisible(False)

        self.__state = DownloadItem.Downloading

        icon = self.style().standardIcon(QStyle.SP_FileIcon)
        self.fileIcon.setPixmap(icon.pixmap(48, 48))

        self.__mainWindow = mainWindow
        self.__reply = reply
        self.__requestFilename = requestFilename
        self.__page = webPage
        self.__pageUrl = webPage and webPage.mainFrame().url() or QUrl()
        self.__toDownload = download
        self.__bytesReceived = 0
        self.__bytesTotal = -1
        self.__downloadTime = QTime()
        self.__output = QFile()
        self.__fileName = ""
        self.__originalFileName = ""
        self.__startedSaving = False
        self.__finishedDownloading = False
        self.__gettingFileName = False
        self.__canceledFileSelect = False
        self.__autoOpen = False

        self.__sha1Hash = QCryptographicHash(QCryptographicHash.Sha1)
        self.__md5Hash = QCryptographicHash(QCryptographicHash.Md5)

        if not requestFilename:
            self.__requestFilename = \
                Preferences.getUI("RequestDownloadFilename")

        self.__initialize()

    def __initialize(self, tryAgain=False):
        """
        Private method to (re)initialize the widget.
        
        @param tryAgain flag indicating a retry (boolean)
        """
        if self.__reply is None:
            return

        self.__startedSaving = False
        self.__finishedDownloading = False
        self.__bytesReceived = 0
        self.__bytesTotal = -1

        self.__sha1Hash.reset()
        self.__md5Hash.reset()

        # start timer for the download estimation
        self.__downloadTime.start()

        # attach to the reply object
        self.__url = self.__reply.url()
        self.__reply.setParent(self)
        self.__reply.setReadBufferSize(16 * 1024 * 1024)
        self.__reply.readyRead.connect(self.__readyRead)
        self.__reply.error.connect(self.__networkError)
        self.__reply.downloadProgress.connect(self.__downloadProgress)
        self.__reply.metaDataChanged.connect(self.__metaDataChanged)
        self.__reply.finished.connect(self.__finished)

        # reset info
        self.infoLabel.clear()
        self.progressBar.setValue(0)
        self.__getFileName()

        if self.__reply.error() != QNetworkReply.NoError:
            self.__networkError()
            self.__finished()

    def __getFileName(self):
        """
        Private method to get the file name to save to from the user.
        """
        if self.__gettingFileName:
            return

        import Helpviewer.HelpWindow
        downloadDirectory = Helpviewer.HelpWindow.HelpWindow\
            .downloadManager().downloadDirectory()

        if self.__fileName:
            fileName = self.__fileName
            originalFileName = self.__originalFileName
            self.__toDownload = True
            ask = False
        else:
            defaultFileName, originalFileName = \
                self.__saveFileName(downloadDirectory)
            fileName = defaultFileName
            self.__originalFileName = originalFileName
            ask = True
        self.__autoOpen = False
        if not self.__toDownload:
            from .DownloadAskActionDialog import DownloadAskActionDialog
            url = self.__reply.url()
            dlg = DownloadAskActionDialog(
                QFileInfo(originalFileName).fileName(),
                self.__reply.header(QNetworkRequest.ContentTypeHeader),
                "{0}://{1}".format(url.scheme(), url.authority()), self)
            if dlg.exec_() == QDialog.Rejected or dlg.getAction() == "cancel":
                self.progressBar.setVisible(False)
                self.__reply.close()
                self.on_stopButton_clicked()
                self.filenameLabel.setText(
                    self.tr("Download canceled: {0}").format(
                        QFileInfo(defaultFileName).fileName()))
                self.__canceledFileSelect = True
                return

##            if dlg.getAction() == "scan":
##                self.__mainWindow.requestVirusTotalScan(url)
##
##                self.progressBar.setVisible(False)
##                self.__reply.close()
##                self.on_stopButton_clicked()
##                self.filenameLabel.setText(
##                    self.tr("VirusTotal scan scheduled: {0}").format(
##                        QFileInfo(defaultFileName).fileName()))
##                self.__canceledFileSelect = True
##                return
##
            self.__autoOpen = dlg.getAction() == "open"
            if PYQT_VERSION_STR >= "5.0.0":
                from PyQt5.QtCore import QStandardPaths
                tempLocation = QStandardPaths.storageLocation(
                    QStandardPaths.TempLocation)
            else:
                from PyQt5.QtGui import QDesktopServices
                tempLocation = QDesktopServices.storageLocation(
                    QDesktopServices.TempLocation)
            fileName = tempLocation + '/' + \
                QFileInfo(fileName).completeBaseName()

        if ask and not self.__autoOpen and self.__requestFilename:
            self.__gettingFileName = True
            fileName = E5FileDialog.getSaveFileName(None, self.tr("Save File"),
                                                    defaultFileName, "")
            self.__gettingFileName = False
            if not fileName:
                self.progressBar.setVisible(False)
                self.__reply.close()
                self.on_stopButton_clicked()
                self.filenameLabel.setText(
                    self.tr("Download canceled: {0}").format(
                        QFileInfo(defaultFileName).fileName()))
                self.__canceledFileSelect = True
                return

        fileInfo = QFileInfo(fileName)
        Helpviewer.HelpWindow.HelpWindow.downloadManager()\
            .setDownloadDirectory(fileInfo.absoluteDir().absolutePath())
        self.filenameLabel.setText(fileInfo.fileName())

        self.__output.setFileName(fileName + ".part")
        self.__fileName = fileName

        # check file path for saving
        saveDirPath = QFileInfo(self.__fileName).dir()
        if not saveDirPath.exists():
            if not saveDirPath.mkpath(saveDirPath.absolutePath()):
                self.progressBar.setVisible(False)
                self.on_stopButton_clicked()
                self.infoLabel.setText(
                    self.tr("Download directory ({0}) couldn't be created.").
                    format(saveDirPath.absolutePath()))
                return

        self.filenameLabel.setText(QFileInfo(self.__fileName).fileName())
        if self.__requestFilename:
            self.__readyRead()

    def __saveFileName(self, directory):
        """
        Private method to calculate a name for the file to download.
        
        @param directory name of the directory to store the file into (string)
        @return proposed filename and original filename (string, string)
        """
        path = ""
        if self.__reply.hasRawHeader("Content-Disposition"):
            header = bytes(self.__reply.rawHeader("Content-Disposition"))\
                .decode()
            if header:
                pos = header.find("filename=")
                if pos != -1:
                    path = header[pos + 9:]
                    if path.startswith('"') and path.endswith('"'):
                        path = path[1:-1]
        if not path:
            path = self.__url.path()

        info = QFileInfo(path)
        baseName = info.completeBaseName()
        endName = info.suffix()

        if not baseName:
            baseName = "unnamed_download"

        origName = baseName
        if endName:
            origName += '.' + endName

        name = directory + baseName
        if endName:
            name += '.' + endName
            if not self.__requestFilename:
                # do not overwrite, if the user is not being asked
                i = 1
                while QFile.exists(name):
                    # file exists already, don't overwrite
                    name = directory + baseName + ('-{0:d}'.format(i))
                    if endName:
                        name += '.' + endName
                    i += 1
        return name, origName

    def __open(self):
        """
        Private slot to open the downloaded file.
        """
        info = QFileInfo(self.__output)
        url = QUrl.fromLocalFile(info.absoluteFilePath())
        QDesktopServices.openUrl(url)

    @pyqtSlot()
    def on_tryAgainButton_clicked(self):
        """
        Private slot to retry the download.
        """
        self.retry()

    def retry(self):
        """
        Public slot to retry the download.
        """
        if not self.tryAgainButton.isEnabled():
            return

        self.tryAgainButton.setEnabled(False)
        self.tryAgainButton.setVisible(False)
        self.openButton.setEnabled(False)
        self.openButton.setVisible(False)
        if not self.__isFtpDownload:
            self.stopButton.setEnabled(True)
            self.stopButton.setVisible(True)
            self.pauseButton.setEnabled(True)
            self.pauseButton.setVisible(True)
        self.progressBar.setVisible(True)

        if self.__page:
            nam = self.__page.networkAccessManager()
        else:
            import Helpviewer.HelpWindow
            nam = Helpviewer.HelpWindow.HelpWindow.networkAccessManager()
        reply = nam.get(QNetworkRequest(self.__url))
        if self.__output.exists():
            self.__output.remove()
        self.__output = QFile()
        self.__reply = reply
        self.__initialize(tryAgain=True)
        self.__state = DownloadItem.Downloading
        self.statusChanged.emit()

    @pyqtSlot(bool)
    def on_pauseButton_clicked(self, checked):
        """
        Private slot to pause the download.
        
        @param checked flag indicating the state of the button (boolean)
        """
        if checked:
            self.__reply.readyRead.disconnect(self.__readyRead)
            self.__reply.setReadBufferSize(16 * 1024)
        else:
            self.__reply.readyRead.connect(self.__readyRead)
            self.__reply.setReadBufferSize(16 * 1024 * 1024)
            self.__readyRead()

    @pyqtSlot()
    def on_stopButton_clicked(self):
        """
        Private slot to stop the download.
        """
        self.cancelDownload()

    def cancelDownload(self):
        """
        Public slot to stop the download.
        """
        self.setUpdatesEnabled(False)
        if not self.__isFtpDownload:
            self.stopButton.setEnabled(False)
            self.stopButton.setVisible(False)
            self.pauseButton.setEnabled(False)
            self.pauseButton.setVisible(False)
        self.tryAgainButton.setEnabled(True)
        self.tryAgainButton.setVisible(True)
        self.openButton.setEnabled(False)
        self.openButton.setVisible(False)
        self.setUpdatesEnabled(True)
        self.__state = DownloadItem.DownloadCancelled
        self.__reply.abort()
        self.downloadFinished.emit()

    @pyqtSlot()
    def on_openButton_clicked(self):
        """
        Private slot to open the downloaded file.
        """
        self.openFile()

    def openFile(self):
        """
        Public slot to open the downloaded file.
        """
        info = QFileInfo(self.__fileName)
        url = QUrl.fromLocalFile(info.absoluteFilePath())
        QDesktopServices.openUrl(url)

    def openFolder(self):
        """
        Public slot to open the folder containing the downloaded file.
        """
        info = QFileInfo(self.__fileName)
        url = QUrl.fromLocalFile(info.absolutePath())
        QDesktopServices.openUrl(url)

    def __readyRead(self):
        """
        Private slot to read the available data.
        """
        if self.__requestFilename and not self.__output.fileName():
            return

        if not self.__output.isOpen():
            # in case someone else has already put a file there
            if not self.__requestFilename:
                self.__getFileName()
            if not self.__output.open(QIODevice.WriteOnly):
                self.infoLabel.setText(
                    self.tr("Error opening save file: {0}").format(
                        self.__output.errorString()))
                self.on_stopButton_clicked()
                self.statusChanged.emit()
                return
            self.statusChanged.emit()

        buffer = self.__reply.readAll()
        self.__sha1Hash.addData(buffer)
        self.__md5Hash.addData(buffer)
        bytesWritten = self.__output.write(buffer)
        if bytesWritten == -1:
            self.infoLabel.setText(
                self.tr("Error saving: {0}").format(
                    self.__output.errorString()))
            self.on_stopButton_clicked()
        else:
            self.__startedSaving = True
            if self.__finishedDownloading:
                self.__finished()

    def __networkError(self):
        """
        Private slot to handle a network error.
        """
        self.infoLabel.setText(
            self.tr("Network Error: {0}").format(self.__reply.errorString()))
        self.tryAgainButton.setEnabled(True)
        self.tryAgainButton.setVisible(True)
        self.downloadFinished.emit()

    def __metaDataChanged(self):
        """
        Private slot to handle a change of the meta data.
        """
        locationHeader = self.__reply.header(QNetworkRequest.LocationHeader)
        if locationHeader and locationHeader.isValid():
            self.__url = QUrl(locationHeader)
            import Helpviewer.HelpWindow
            self.__reply = Helpviewer.HelpWindow.HelpWindow\
                .networkAccessManager().get(QNetworkRequest(self.__url))
            self.__initialize()

    def __downloadProgress(self, bytesReceived, bytesTotal):
        """
        Private method to show the download progress.
        
        @param bytesReceived number of bytes received (integer)
        @param bytesTotal number of total bytes (integer)
        """
        self.__bytesReceived = bytesReceived
        self.__bytesTotal = bytesTotal
        currentValue = 0
        totalValue = 0
        if bytesTotal > 0:
            currentValue = bytesReceived * 100 / bytesTotal
            totalValue = 100
        self.progressBar.setValue(currentValue)
        self.progressBar.setMaximum(totalValue)

        self.progress.emit(currentValue, totalValue)
        self.__updateInfoLabel()

    def bytesTotal(self):
        """
        Public method to get the total number of bytes of the download.
        
        @return total number of bytes (integer)
        """
        if self.__bytesTotal == -1:
            self.__bytesTotal = self.__reply.header(
                QNetworkRequest.ContentLengthHeader)
            if self.__bytesTotal is None:
                self.__bytesTotal = -1
        return self.__bytesTotal

    def bytesReceived(self):
        """
        Public method to get the number of bytes received.
        
        @return number of bytes received (integer)
        """
        return self.__bytesReceived

    def remainingTime(self):
        """
        Public method to get an estimation for the remaining time.
        
        @return estimation for the remaining time (float)
        """
        if not self.downloading():
            return -1.0

        if self.bytesTotal() == -1:
            return -1.0

        timeRemaining = (self.bytesTotal() -
                         self.bytesReceived()) / self.currentSpeed()

        # ETA should never be 0
        if timeRemaining == 0:
            timeRemaining = 1

        return timeRemaining

    def currentSpeed(self):
        """
        Public method to get an estimation for the download speed.
        
        @return estimation for the download speed (float)
        """
        if not self.downloading():
            return -1.0

        return self.__bytesReceived * 1000.0 / self.__downloadTime.elapsed()

    def __updateInfoLabel(self):
        """
        Private method to update the info label.
        """
        if self.__reply.error() != QNetworkReply.NoError:
            return

        bytesTotal = self.bytesTotal()
        running = not self.downloadedSuccessfully()

        speed = self.currentSpeed()
        timeRemaining = self.remainingTime()

        info = ""
        if running:
            remaining = ""

            if bytesTotal > 0:
                remaining = timeString(timeRemaining)

            info = self.tr("{0} of {1} ({2}/sec)\n{3}")\
                .format(
                    dataString(self.__bytesReceived),
                    bytesTotal == -1 and self.tr("?")
                    or dataString(bytesTotal),
                    dataString(int(speed)),
                    remaining)
        else:
            if self.__bytesReceived == bytesTotal or bytesTotal == -1:
                info = self.tr("{0} downloaded\nSHA1: {1}\nMD5: {2}")\
                    .format(dataString(self.__output.size()),
                            str(self.__sha1Hash.result().toHex(),
                                encoding="ascii"),
                            str(self.__md5Hash.result().toHex(),
                                encoding="ascii")
                            )
            else:
                info = self.tr("{0} of {1} - Stopped")\
                    .format(dataString(self.__bytesReceived),
                            dataString(bytesTotal))
        self.infoLabel.setText(info)

    def downloading(self):
        """
        Public method to determine, if a download is in progress.
        
        @return flag indicating a download is in progress (boolean)
        """
        return self.__state == DownloadItem.Downloading

    def downloadedSuccessfully(self):
        """
        Public method to check for a successful download.
        
        @return flag indicating a successful download (boolean)
        """
        return self.__state == DownloadItem.DownloadSuccessful

    def downloadCanceled(self):
        """
        Public method to check, if the download was cancelled.
        
        @return flag indicating a canceled download (boolean)
        """
        return self.__state == DownloadItem.DownloadCancelled

    def __finished(self):
        """
        Private slot to handle the download finished.
        """
        self.__finishedDownloading = True
        if not self.__startedSaving:
            return

        noError = self.__reply.error() == QNetworkReply.NoError

        self.progressBar.setVisible(False)
        if not self.__isFtpDownload:
            self.stopButton.setEnabled(False)
            self.stopButton.setVisible(False)
            self.pauseButton.setEnabled(False)
            self.pauseButton.setVisible(False)
        self.openButton.setEnabled(noError)
        self.openButton.setVisible(noError)
        self.__output.close()
        if QFile.exists(self.__fileName):
            QFile.remove(self.__fileName)
        self.__output.rename(self.__fileName)
        self.__updateInfoLabel()
        self.__state = DownloadItem.DownloadSuccessful
        self.statusChanged.emit()
        self.downloadFinished.emit()

        if self.__autoOpen:
            self.__open()

    def canceledFileSelect(self):
        """
        Public method to check, if the user canceled the file selection.
        
        @return flag indicating cancellation (boolean)
        """
        return self.__canceledFileSelect

    def setIcon(self, icon):
        """
        Public method to set the download icon.
        
        @param icon reference to the icon to be set (QIcon)
        """
        self.fileIcon.setPixmap(icon.pixmap(48, 48))

    def fileName(self):
        """
        Public method to get the name of the output file.
        
        @return name of the output file (string)
        """
        return self.__fileName

    def absoluteFilePath(self):
        """
        Public method to get the absolute path of the output file.
        
        @return absolute path of the output file (string)
        """
        return QFileInfo(self.__fileName).absoluteFilePath()

    def getData(self):
        """
        Public method to get the relevant download data.
        
        @return tuple of URL, save location, flag and the
            URL of the related web page (QUrl, string, boolean,QUrl)
        """
        return (self.__url, QFileInfo(self.__fileName).filePath(),
                self.downloadedSuccessfully(), self.__pageUrl)

    def setData(self, data):
        """
        Public method to set the relevant download data.
        
        @param data tuple of URL, save location, flag and the
            URL of the related web page (QUrl, string, boolean, QUrl)
        """
        self.__url = data[0]
        self.__fileName = data[1]
        self.__pageUrl = data[3]
        self.__isFtpDownload = self.__url.scheme() == "ftp"

        self.filenameLabel.setText(QFileInfo(self.__fileName).fileName())
        self.infoLabel.setText(self.__fileName)

        self.stopButton.setEnabled(False)
        self.stopButton.setVisible(False)
        self.pauseButton.setEnabled(False)
        self.pauseButton.setVisible(False)
        self.openButton.setEnabled(data[2])
        self.openButton.setVisible(data[2])
        self.tryAgainButton.setEnabled(not data[2])
        self.tryAgainButton.setVisible(not data[2])
        if data[2]:
            self.__state = DownloadItem.DownloadSuccessful
        else:
            self.__state = DownloadItem.DownloadCancelled
        self.progressBar.setVisible(False)

    def getInfoData(self):
        """
        Public method to get the text of the info label.
        
        @return text of the info label (string)
        """
        return self.infoLabel.text()

    def getPageUrl(self):
        """
        Public method to get the URL of the download page.
        
        @return URL of the download page (QUrl)
        """
        return self.__pageUrl
class TcpS(QDialog, Ui_TcpServer):
    """
    Class documentation goes here.
    """

    sendFileName = pyqtSignal(str)

    def __init__(self, parent=None):
        """
        Constructor
        
        @param parent reference to the parent widget
        @type QWidget
        """
        super(TcpS, self).__init__(parent)
        self.setupUi(self)
        self.payloadSize = 64 * 1024
        self.totalBytes = 0
        self.bytesWritten = 0
        self.bytesToWrite = 0
        self.theFileName = ""
        self.fileName = ""
        self.localFile = QFile()
        self.outBlock = QByteArray()
        self.time = QTime()
        self.initServer()

    def initServer(self):
        """
        网络设置初始化
        """
        self.tcpPort = 7788
        self.tcpServer = QTcpServer(self)
        self.clientConnection = QTcpSocket(self)
        self.tcpServer.newConnection.connect(self.sendMessage)
        self.serverStatuslabel.setText("请选择要传送的文件")
        self.progressBar.reset()
        self.serverOpenBtn.setEnabled(True)
        self.serverSendBtn.setEnabled(False)
        self.tcpServer.close()

    def refused(self):
        """
        对端拒绝接收文件
        """
        self.tcpServer.close()
        self.serverStatuslabel.setText("对方拒绝接收")

    def closeEvent(self, event):
        """
        关闭事件
        """
        self.on_serverCloseBtn_clicked()

    def sendMessage(self):
        """
        发送文件
        """
        self.serverSendBtn.setEnabled(False)
        self.clientConnection = self.tcpServer.nextPendingConnection()
        self.clientConnection.bytesWritten.connect(self.updateClientProgress)
        self.serverStatuslabel.setText("开始传送文件 {} !".format(self.theFileName))

        self.localFile = QFile(self.fileName)
        if not (self.localFile.open(QFile.ReadOnly)):
            errorMsg = "无法读取文件 {}:\n {}".format(self.fileName,
                                                self.localFile.errorString())
            QMessageBox.warning(self, "应用程序", errorMsg)
            return

        self.serverCloseBtn.setText("取消")

        self.totalBytes = self.localFile.size()  #单位:字节
        sendOut = QDataStream(self.outBlock, QIODevice.WriteOnly)
        sendOut.setVersion(QDataStream.Qt_5_4)
        self.time.start()
        currentFile = self.fileName.split("/")[-1]
        sendOut.writeInt64(0)
        sendOut.writeInt64(0)
        sendOut.writeQString(currentFile)
        self.totalBytes += self.outBlock.size()
        sendOut.device().seek(0)
        sendOut.writeInt64(self.totalBytes)
        sendOut.writeInt64(self.outBlock.size() - 2)
        self.bytesToWrite = self.totalBytes - self.clientConnection.write(
            self.outBlock)
        self.outBlock.resize(0)

    def updateClientProgress(self, numBytes):
        """
        发送进度显示
        """
        qApp.processEvents()
        self.bytesWritten += numBytes
        if self.bytesWritten > 0:
            self.block = self.localFile.read(
                min(self.bytesToWrite, self.payloadSize))
            self.bytesToWrite -= self.clientConnection.write(self.block)
        else:
            self.localFile.close()

        byteSent = self.bytesWritten / (1024 * 1024)
        useTime = self.time.elapsed() / 1000
        speed = self.bytesWritten / useTime / (1024 * 1024)
        total = self.totalBytes / (1024 * 1024)
        left = (total - byteSent) / speed

        if byteSent < 0.01:
            byteSent = self.bytesWritten / 1024
            speed = self.bytesWritten / useTime / 1024
            total = self.totalBytes / 1024
            if left > 0:
                sendInfo = "已发送 {0:.2f}KB({1:.2f}KB/s)\n共{2:.2f}KB 已用时:{3:.1f}秒\n 估计剩余时间:{4:.1f}秒".format(
                    byteSent, speed, total, useTime, left)
            else:
                sendInfo = "已发送 {0:.2f}KB({1:.2f}KB/s)\n共{2:.2f}KB 用时:{3:.1f}秒\n".format(
                    byteSent, speed, total, useTime)
        else:
            if left > 0:
                sendInfo = "已发送 {0:.2f}MB({1:.2f}MB/s)\n共{2:.2f}MB 已用时:{3:.1f}秒\n 估计剩余时间:{4:.1f}秒".format(
                    byteSent, speed, total, useTime, left)
            else:
                sendInfo = "已发送 {0:.2f}MB({1:.2f}MB/s)\n共{2:.2f}MB 用时:{3:.1f}秒\n".format(
                    byteSent, speed, total, useTime)

        self.progressBar.setMaximum(total)
        self.progressBar.setValue(byteSent)

        if self.bytesWritten == self.totalBytes:
            self.serverCloseBtn.setText("关闭")

        self.serverStatuslabel.setText(sendInfo)

    @pyqtSlot()
    def on_serverOpenBtn_clicked(self):
        """
        打开文件
        """
        self.fileName = QFileDialog.getOpenFileName(self, '打开文件', './')[0]
        if self.fileName:
            self.theFileName = self.fileName.split("/")[-1]
            self.serverStatuslabel.setText("要传送的文件为:{}".format(
                self.theFileName))
            self.serverSendBtn.setEnabled(True)
            self.serverOpenBtn.setEnabled(False)

    @pyqtSlot()
    def on_serverSendBtn_clicked(self):
        """
        发送文件
        """
        if not (self.tcpServer.listen(QHostAddress.Any, self.tcpPort)):
            errorMsg = self.tcpServer.errorString()
            QMessageBox.warning(self, "错误", "发送失败:\n {}".format(errorMsg))
            self.TcpServer.close()
            return

        self.serverStatuslabel.setText("等待对方接收... ...")
        self.serverSendBtn.setEnabled(False)
        self.sendFileName.emit(self.theFileName)

    @pyqtSlot()
    def on_serverCloseBtn_clicked(self):
        """
        取消或者关闭
        """
        if self.tcpServer.isListening():
            self.tcpServer.close()
            if self.localFile.isOpen():
                self.localFile.close()
            self.clientConnection.abort()

        if self.serverCloseBtn.text() == "取消":
            self.serverCloseBtn.setText("关闭")
        else:
            self.close()
            self.serverOpenBtn.setEnabled(True)
            self.serverSendBtn.setEnabled(False)
            self.progressBar.reset()
            self.totalBytes = 0
            self.bytesWritten = 0
            self.bytesToWrite = 0
            self.serverStatuslabel.setText("请选择要传送的文件")
Exemple #16
0
class TcpC(QDialog, Ui_TcpClient):
    """
    Tcp客户端
    """
    def __init__(self, parent=None):
        """
        一些初始设置
        """
        super(TcpC, self).__init__(parent)
        self.setupUi(self)
        self.TotalBytes = 0
        self.bytesReceive = 0
        self.fileNameSize = 0
        self.bytesToReceive = 0
        self.fileName = ""
        self.tcpClient = QTcpSocket(self)
        self.tcpPort = 7788
        self.time = QTime()

        self.tcpClient.readyRead.connect(self.readMessage)
        # 每当新数据可用于从设备的当前读取通道读取时,readyRead信号就会发出一次。

        self.tcpClient.error.connect(self.displayError)
        # 当网络连接出现问题时调用displayError()函数。

    def setHostAddress(self, address):
        """
        设置服务器地址
        """
        self.hostAddress = address
        self.newConnect()
        # 设置服务器地址,同时调用newConnect()函数。

    def setFileName(self, file):
        """
        待接收文件的文件名
        """
        self.localFile = QFile(file)
        # 设置待接收文件的文件名,这个函数是放在主程序里面调用的。

    def closeEvent(self, event):
        """
        关闭事件
        """
        self.on_tcpClientCloseBtn_clicked()

    def newConnect(self):
        """
        连接服务器并开始计时
        """
        self.tcpClient.abort()
        self.tcpClient.connectToHost(self.hostAddress, self.tcpPort)
        self.time.start()
        # abort()中止当前连接并重置套接字。与disconnectFromHost()不同,此函数立即关闭套接字,丢弃写缓冲区中的任何挂起数据。
        # connectToHost()尝试与self.hostAddress的self.tcpPort端口建立连接。

    def readMessage(self):
        """
        读取文件数据
        """
        receiver = QDataStream(self.tcpClient)
        receiver.setVersion(QDataStream.Qt_5_4)

        if self.bytesReceive <= 2:
            if self.tcpClient.bytesAvailable() >= 2 and self.fileNameSize == 0:
                self.TotalBytes = receiver.readInt64()
                self.fileNameSize = receiver.readInt64()
                self.bytesReceive += 2
        # 当接收的字节数小于等2,同时套接字返回等待读取的传入字节数大于2而文件名大小不确定时,传输的总大小receiver.readInt64(),文件名大小是receiver.readInt64()。

            if self.tcpClient.bytesAvailable() >= self.fileNameSize and self.fileNameSize != 0:
                self.fileName = receiver.readQString()
                self.bytesReceive += self.fileNameSize
                # 当我们接收的字节数一定后,我们读取文件名receiver.readQString(),自然收到的字节数要加上文件名大小。
                if not(self.localFile.open(QFile.WriteOnly)):
                    QMessageBox.warning(self, "应用程序", "无法读取文件 {}:\n {}".format(self.fileName, self.localFile.errorString()))
                    return
                    # 要是写文件存在问题就报错。
            else:
                return

        if self.bytesReceive < self.TotalBytes:
            self.bytesReceive += self.tcpClient.bytesAvailable()
            inBlock = self.tcpClient.readAll()
            self.localFile.write(inBlock)
            inBlock.resize(0)

        useTime = self.time.elapsed() / 1000
        
        bytesReceived = self.bytesReceive / (1024*1024)
        speed = bytesReceived / useTime
        total = self.TotalBytes / (1024*1024)
        left = (total - bytesReceived) / speed

        if bytesReceived < 0.01:
            # 要是我们收到的文件太小了,我们设定成KB为单位
            bytesReceived = self.bytesReceive / 1024
            speed = bytesReceived / useTime / 1024
            total = self.TotalBytes / 1024
            if left > 0:
                msg = "已接收 {0:.2f} KB ({1:.2f}KB/s)\n共{2:.2f}KB.已用时:{3:.1f}秒\n估计剩余时间:{4:.1f}秒".format(bytesReceived, speed, total, useTime, left)
            else:
                msg = "已接收 {0:.2f} KB ({1:.2f}KB/s)\n共{2:.2f}KB.已用时:{3:.1f}秒\n".format(bytesReceived, speed, total, useTime)

        else:
            # 要是文件比较大,我们设定成MB为单位
            if left > 0:
                msg = "已接收 {0:.2f} MB ({1:.2f}MB/s)\n共{2:.2f}MB.已用时:{3:.1f}秒\n估计剩余时间:{4:.1f}秒".format(bytesReceived, speed, total, useTime, left)
            else:
                msg = "已接收 {0:.2f} MB ({1:.2f}MB/s)\n共{2:.2f}MB.已用时:{3:.1f}秒\n".format(bytesReceived, speed, total, useTime)

        self.progressBar.setMaximum(total)
        self.progressBar.setValue(bytesReceived)

        self.tcpClientStatuslabel.setText(msg)
        
        if self.bytesReceive == self.TotalBytes:
            self.localFile.close()
            self.tcpClient.close()
            self.tcpClientStatuslabel.setText("接收文件{}完毕".format(self.fileName))
            self.tcpClientBtn.setEnabled(False)
        # 当我们接收的大小和文件总大小一致时,关闭网络连接、文件,提示接收完毕。


    def displayError(self, socketError):
        """
        显示错误
        """
        if socketError == QAbstractSocket.RemoteHostClosedError:
            pass
        else:
            errorMsg = self.tcpClient.errorString()
            QMessageBox.warning(self, "应用程序", errorMsg)
            return
        # 网络错误的处理。

    @pyqtSlot()
    def on_tcpClientBtn_clicked(self):
        """
        取消接收
        """
        self.tcpClient.abort()
        if self.localFile.isOpen():
            self.localFile.close()
        
        self.tcpClientBtn.setEnabled(False)
        # 点击取消时传输终止
    
    @pyqtSlot()
    def on_tcpClientCloseBtn_clicked(self):
        """
        关闭
        """
        self.tcpClient.abort()
        if self.localFile.isOpen():
            self.localFile.close()
        self.close()
        self.tcpClientBtn.setEnabled(True)
        # 关闭网络连接,相关设置复位。
Exemple #17
0
    def openxml(self, file, edit=False):
        self.expr_list = []
        self.current_X = 40
        self.current_Y = 10
        self.lineheight = 0
        # 传入的是地址
        qfile = QFile(file)
        # 找到文件,则设置引擎,否则向xml文件直接添加数据
        if qfile.open(QFile.ReadWrite | QFile.Text):
            self.dom.setContent(QFile)
        else:
            self.dom.setContent(file)
        if self.dom.isNull():
            return False
        # 获得根目录的元素,返回QDomElement    <GMPPaper>
        element = self.dom.documentElement()
        # 获得第一个子元素,返回QDomNode
        n = element.firstChild()
        index = 0
        # linenum = 1
        # self.linenumlabel(linenum)
        # 如果没有读到文档结尾,而且没有出现错误
        while not n.isNull():
            # 把当前的QDomNode转为QDomElement
            e = n.toElement()

            if not e.isNull():
                name = e.tagName()
                # 标题框
                if name == "Title":
                    self.titleBox(e, index, edit)
                # 标题输入框
                elif name == "TextBox":
                    self.inputBox(e, index, edit)
                # 线框
                elif name == "Box":
                    self.wireframe(e, index, edit)
                # 检测框
                elif name == "CheckBox":
                    self.checkBox(e, index, edit)
                # 下拉框
                elif name == "ComboBox":
                    self.comboBox(e, index, edit)
                # 签名框
                elif name == "Signature":
                    self.signBox(e, index, edit)
                # 表达式
                elif name == "Expr":
                    self.exprBox(e, index, edit)
                # 换行
                elif name == "br":
                    self.wrapBox(e, index, edit)
                    # linenum += 1
                    # self.linenumlabel(linenum)
                # 多行输入
                elif name == "Memo":
                    self.textedit(e, index, edit)
            # 空格组成的字符,包括换行
            elif self.dom.isWhitespace():
                pass
            # 纯文本
            elif self.dom.isCharacters():
                pass
            # 获取下一个同级标签
            n = n.nextSibling()
            index += 1
        if qfile.isOpen():
            qfile.close()
        if len(self.expr_list):
            for item in self.expr_list:
                if isinstance(item[0], XmlExprBox):
                    self.setupExpr(item)
                item[0].flush()
        self.scrollAreaWidgetContents.adjustSize()
        self.scrollAreaWidgetContents.setMinimumSize(
            self.scrollAreaWidgetContents.size())