Ejemplo n.º 1
0
class MainWindow(QMainWindow):
    def __init__(self):
        super().__init__()
        self.initUI()


    def initUI(self):
        monospacedFont = QFontDatabase.systemFont(QFontDatabase.FixedFont)

        bottombox = QHBoxLayout()
        self.serialPortEdit = QLineEdit()
        self.serialPortEdit.setPlaceholderText("Enter full path to the serial port")
        self.serialPortEdit.returnPressed.connect(self.on_serialportedit_enter_pressed)
        self.serialPortEdit.setFont(monospacedFont)

        self.baudrateComboBox = QComboBox()
        self.std_baudrates = [50, 75, 110, 134, 150, 200, 300, 600, 1200, 1800, 2400, 4800, 9600, 19200, 38400, 57600, 115200]
        self.baudrateComboBox.addItems(map(lambda x: str(x), self.std_baudrates))
        self.baudrateComboBox.setPlaceholderText("Select Baud rate")
        self.baudrateComboBox.setCurrentIndex(-1)
        

        self.connectBtn = QPushButton("Connect")
        self.connectBtn.clicked.connect(self.on_connect_btn_clicked)
        
        self.disconnectBtn = QPushButton("Disconnect")
        self.disconnectBtn.clicked.connect(self.on_disconnect_btn_clicked)
        self.disconnectBtn.setEnabled(False)
        
        bottombox.addWidget(self.serialPortEdit)
        bottombox.addWidget(self.baudrateComboBox)
        bottombox.addWidget(self.connectBtn)
        bottombox.addWidget(self.disconnectBtn)

        mainvbox = QVBoxLayout()
        
        self.serialOutputEdit = QPlainTextEdit()
        self.serialOutputEdit.setReadOnly(True)
        self.serialOutputEdit.setFont(monospacedFont)
        
        self.serialInputEdit = QLineEdit()
        self.serialInputEdit.setPlaceholderText("Enter your data you want to send to the port")
        self.serialInputEdit.setEnabled(False)
        self.serialInputEdit.setFont(monospacedFont)

        mainvbox.addWidget(self.serialOutputEdit)
        mainvbox.addWidget(self.serialInputEdit)
        mainvbox.addLayout(bottombox)

        centralWidget = QWidget(self)
        centralWidget.setLayout(mainvbox)
        self.setCentralWidget(centralWidget)

        self.statusBar = QStatusBar()        

        connectedImage = QImage.fromData(base64.b64decode(connectedImagebase64), "PNG")
        disonnectedImage = QImage.fromData(base64.b64decode(disconnectedImagebase64), "PNG")

        self.connectedImagePixMap = QPixmap.fromImage(connectedImage)
        self.disconnectedImagePixMap = QPixmap.fromImage(disonnectedImage)

        self.connectionStatusLabelIcon = QLabel()
        self.connectionStatusLabelIcon.setPixmap(self.disconnectedImagePixMap)

        self.connectionStatusLabelText = QLabel("Disconnected")

        self.statusBar.addWidget(self.connectionStatusLabelIcon)
        self.statusBar.addWidget(self.connectionStatusLabelText)

        self.timerPushButton = QPushButton("Enable Timer")
        self.timerPushButton.setCheckable(True)
        self.timerPushButton.toggled.connect(self.on_timerPushButton_toggled)

        self.timerWindowDoubleSpinBox = QDoubleSpinBox()
        self.timerWindowDoubleSpinBox.setMinimum(0)
        self.timerWindowDoubleSpinBox.setMaximum(10)
        self.timerWindowDoubleSpinBox.setDecimals(1)
        self.timerWindowDoubleSpinBox.setValue(1)
        self.timerWindowDoubleSpinBox.setSuffix(" s")

        self.clearConsolePushButton = QPushButton("Clear console")
        self.clearConsolePushButton.clicked.connect(self.on_clearConsolePushButton_clicked)

        self.filterStringCheckBox = QCheckBox("Enable Filter")
        self.filterStringCheckBox.stateChanged.connect(self.on_filterStringCheckBox_stateChanged)
        self.filterEnabled = False
        self.filterString = ""

        self.filterStringEdit = QLineEdit()
        self.filterStringEdit.setPlaceholderText("Filter String")
        self.filterStringEdit.setFont(monospacedFont)
        self.filterStringEdit.textEdited.connect(self.on_filterStringEdit_textEdited)
        self.statusBar.addPermanentWidget(self.filterStringCheckBox)
        self.statusBar.addPermanentWidget(self.filterStringEdit)
        self.statusBar.addPermanentWidget(self.clearConsolePushButton)
        self.statusBar.addPermanentWidget(self.timerPushButton)
        self.statusBar.addPermanentWidget(self.timerWindowDoubleSpinBox)


        self.statusBar.layout().setContentsMargins(8, 0, 0, 0)
        self.setStatusBar(self.statusBar)

        self.setGeometry(300, 300, 800, 495)
        self.setWindowTitle('Attify Serial Console')
        self.show()

    def on_filterStringEdit_textEdited(self, text):
        if self.filterStringCheckBox.isChecked():
            self.filterString = text

    def on_filterStringCheckBox_stateChanged(self, state):
        if self.filterStringCheckBox.isChecked():
            self.filterString = self.filterStringEdit.text().strip()
            self.filterEnabled = True
            
        else:
            self.filterEnabled = False


    def on_clearConsolePushButton_clicked(self):
        self.serialOutputEdit.clear()

    def on_timerPushButton_toggled(self, checked):
        self.timerWindowDoubleSpinBox.setEnabled(not checked)

        if checked:
            Timer.currentTimerWindow = self.timerWindowDoubleSpinBox.value()
        else:
            Timer.currentTimerWindow = -1


    def closeEvent(self,event):
        try:
            self.readMonitorQ.quit()
        except:
            pass
        
        try:            
            self.serialReader.stop()
        except:
            pass

        try:
            self.serialWriter.stop()
        except:
            pass

        try:
            self.serial_port.close()
        except:
            pass

        event.accept()


    def on_serialportedit_enter_pressed(self):
        self.on_connect_btn_clicked()


    def on_serialinput_enter_pressed(self):
        cmd = str(self.serialInputEdit.text()).strip()

        if len(cmd) > 0:
            self.serialOutputEdit.appendPlainText('>> ' + cmd)
            cmd = (cmd + '\r\n').encode()
            if Timer.currentTimerWindow != -1:
                Timer.lastSerialInputTime = time.time()
            self.write_Q.put(cmd)
            self.serialInputEdit.clear()            


    def on_connect_btn_clicked(self):
        serial_port_txt = self.serialPortEdit.text()
        if len(serial_port_txt) > 0:
            index = self.baudrateComboBox.currentIndex()
            if index == -1:
                error_dialog = QErrorMessage(self)
                error_dialog.setModal(True)                
                error_dialog.showMessage("Please select a baud rate")
            else:
                baud_rate = self.std_baudrates[index]
                try:
                    self.serial_port = serial.Serial(serial_port_txt, timeout=1, baudrate=baud_rate)
                except Exception as ex:
                    error_dialog = QErrorMessage(self)
                    error_dialog.setModal(True)                
                    error_dialog.showMessage(str(ex))
                else:
                    self.connectBtn.setEnabled(False)
                    self.disconnectBtn.setEnabled(True)
                    self.serialInputEdit.setEnabled(True)
                    self.connectionStatusLabelText.setText("Connected")
                    self.connectionStatusLabelIcon.setPixmap(self.connectedImagePixMap)
                    self.baudrateComboBox.setEnabled(False)

                    self.start_reader()
                    self.start_writer()


    def write_to_Serial_Output_Edit(self, data):
        cleaned_text = strip_ansi(data.decode('ascii')).strip()
        if (self.filterEnabled and self.filterString not in cleaned_text) or not self.filterEnabled:
            self.serialOutputEdit.appendPlainText(cleaned_text)



    def start_reader(self):
        self.read_Q = queue.Queue()
        self.serialReader = SerialReader(self.serial_port, self.read_Q)
        self.serialReader.start_threaded()

        self.readMonitorQ = MonitorQ(self.read_Q)
        self.readMonitorQ.dataAvailable.connect(self.write_to_Serial_Output_Edit)
        self.readMonitorQ.start()
        

    def start_writer(self):
        self.write_Q = queue.Queue()
        self.serialWriter = SerialWriter(self.serial_port, self.write_Q)
        self.serialWriter.start_threaded()

        self.serialInputEdit.returnPressed.connect(self.on_serialinput_enter_pressed)


    def on_disconnect_btn_clicked(self):
        self.connectBtn.setEnabled(True)
        self.disconnectBtn.setEnabled(False)
        self.serialInputEdit.setEnabled(False)
        self.connectionStatusLabelText.setText("Disconnected")
        self.connectionStatusLabelIcon.setPixmap(self.disconnectedImagePixMap)
        self.serialInputEdit.returnPressed.disconnect(self.on_serialinput_enter_pressed)
        self.baudrateComboBox.setEnabled(True)
        self.readMonitorQ.quit()
        self.serialReader.stop()
        self.serialWriter.stop()
        self.serial_port.close()
Ejemplo n.º 2
0
class BatchSendMailWidget(QMainWindow):
    """
    批处理进行邮件发送处理处理的UI
    """
    _row_config: RowNumConfig

    def __init__(self):
        super().__init__()
        # UI处理的各种成员
        self.setCentralWidget(QWidget())
        self.setWindowIcon(QIcon('./icon/mail.png'))
        ctrl_line = []
        self._ctrl_matrix = []
        self._btn_group = []
        label = QLabel("发件人:")
        ctrl_line.append(label)
        radio1 = QRadioButton("相应EXCEL列号:")
        ctrl_line.append(radio1)
        edit = QLineEdit("1")
        ctrl_line.append(edit)
        radio2 = QRadioButton("使用填写发件人:")
        ctrl_line.append(radio2)
        edit = QLineEdit("")
        edit.setEnabled(False)
        ctrl_line.append(edit)
        group = QButtonGroup()
        group.addButton(radio1)
        group.addButton(radio2)
        radio1.clicked.connect(self.radio_clicked)
        radio2.clicked.connect(self.radio_clicked)
        group.setExclusive(True)
        radio1.setChecked(True)
        self._ctrl_matrix.append(ctrl_line)
        self._btn_group.append(group)
        ctrl_line = []
        label = QLabel("收件人:")
        ctrl_line.append(label)
        radio1 = QRadioButton("相应EXCEL列号:")
        ctrl_line.append(radio1)
        edit = QLineEdit("2")
        ctrl_line.append(edit)
        radio2 = QRadioButton("使用填写收件人:")
        ctrl_line.append(radio2)
        edit = QLineEdit("")
        edit.setEnabled(False)
        ctrl_line.append(edit)
        group = QButtonGroup()
        group.addButton(radio1)
        group.addButton(radio2)
        radio1.clicked.connect(self.radio_clicked)
        radio2.clicked.connect(self.radio_clicked)
        group.setExclusive(True)
        radio1.setChecked(True)
        self._ctrl_matrix.append(ctrl_line)
        self._btn_group.append(group)
        ctrl_line = []
        label = QLabel("抄送:")
        ctrl_line.append(label)
        radio1 = QRadioButton("相应EXCEL列号:")
        ctrl_line.append(radio1)
        edit = QLineEdit("3")
        ctrl_line.append(edit)
        radio2 = QRadioButton("使用填写抄送人:")
        ctrl_line.append(radio2)
        edit = QLineEdit("")
        edit.setEnabled(False)
        ctrl_line.append(edit)
        group = QButtonGroup()
        group.addButton(radio1)
        group.addButton(radio2)
        radio1.clicked.connect(self.radio_clicked)
        radio2.clicked.connect(self.radio_clicked)
        radio1.setChecked(True)
        self._ctrl_matrix.append(ctrl_line)
        self._btn_group.append(group)
        ctrl_line = []
        label = QLabel("邮件标题:")
        ctrl_line.append(label)
        radio1 = QRadioButton("相应EXCEL列号:")
        ctrl_line.append(radio1)
        edit = QLineEdit("4")
        ctrl_line.append(edit)
        radio2 = QRadioButton("使用填写标题:")
        ctrl_line.append(radio2)
        edit = QLineEdit("")
        edit.setEnabled(False)
        ctrl_line.append(edit)
        group = QButtonGroup()
        group.addButton(radio1)
        group.addButton(radio2)
        radio1.clicked.connect(self.radio_clicked)
        radio2.clicked.connect(self.radio_clicked)
        radio1.setChecked(True)
        self._ctrl_matrix.append(ctrl_line)
        self._btn_group.append(group)
        ctrl_line = []
        label = QLabel("邮件正文:")
        ctrl_line.append(label)
        radio1 = QRadioButton("相应EXCEL列号:")
        ctrl_line.append(radio1)
        edit = QLineEdit("5")
        ctrl_line.append(edit)
        radio2 = QRadioButton("使用填写正文:")
        ctrl_line.append(radio2)
        edit = QTextEdit("")
        edit.setEnabled(False)
        ctrl_line.append(edit)
        group = QButtonGroup()
        group.addButton(radio1)
        group.addButton(radio2)
        radio1.clicked.connect(self.radio_clicked)
        radio2.clicked.connect(self.radio_clicked)
        radio1.setChecked(True)
        self._ctrl_matrix.append(ctrl_line)
        self._btn_group.append(group)
        self._edit_open_xls = QLineEdit("")
        self._btn_open_xls = QPushButton("打开")
        self._btn_open_xls.clicked.connect(self.open_xls_clicked)
        self._combo_xls_sheet = QComboBox()
        self._combo_xls_sheet.currentIndexChanged.connect(
            self.combo_sheet_changed)
        self._edit_start_row = QLineEdit("2")
        self._edit_end_row = QLineEdit("5")
        self._btn_send = QPushButton("发送")
        self._btn_exit = QPushButton("退出")
        self._btn_send.clicked.connect(self.send_mail)
        self._btn_exit.clicked.connect(self.exit_app)
        self._status_bar = QStatusBar()
        self._status_bar.layout().setAlignment(Qt.AlignRight)
        # BPS批处理发送处理类
        self._batch_send = bps.BatchProcessSend()
        self._default_mail = outlook.SendMailInfo()
        self._row_config = bps.RowNumConfig()
        self._column_config = bps.ColumnNumConfig()

    def show(self):
        grid = QGridLayout()
        line = 0
        grid.setSpacing(10)
        grid.setColumnStretch(0, 1)
        grid.setColumnStretch(1, 1)
        grid.setColumnStretch(2, 1)
        grid.setColumnStretch(3, 1)
        grid.setColumnStretch(4, 10)
        grid.setColumnStretch(5, 1)
        self.centralWidget().setLayout(grid)
        grid.addWidget(QLabel("打开EXCEL配置文件:"), line, 0)
        grid.addWidget(self._edit_open_xls, line, 1, 1, 5)
        grid.addWidget(self._btn_open_xls, line, 6)
        line += 1
        grid.addWidget(QLabel("EXCEL对应的Sheet:"), line, 0)
        grid.addWidget(self._combo_xls_sheet, line, 1, 1, 5)
        line += 1
        separator = QFrame()
        separator.setFrameShape(QFrame.HLine)
        separator.setFrameShadow(QFrame.Plain)
        grid.addWidget(separator, line, 0, 1, 8)
        line += 1
        for x in self._ctrl_matrix:
            grid.addWidget(x[0], line, 0, 1, 1)
            grid.addWidget(x[1], line, 1, 1, 1)
            grid.addWidget(x[2], line, 2, 1, 1)
            grid.addWidget(x[3], line, 3, 1, 1)
            # 给最后一个TextEdit多留一点空间
            if line == 5:
                grid.addWidget(x[4], line, 4, 3, 5)
                line += 3
            else:
                grid.addWidget(x[4], line, 4, 1, 5)
                line += 1
        separator = QFrame()
        separator.setFrameShape(QFrame.HLine)
        separator.setFrameShadow(QFrame.Plain)
        grid.addWidget(separator, line, 0, 1, 8)
        line += 1
        grid.addWidget(QLabel("EXCEL起始发送行:"), line, 0)
        grid.addWidget(self._edit_start_row, line, 1)
        line += 1
        grid.addWidget(QLabel("EXCEL结束发送行:"), line, 0)
        grid.addWidget(self._edit_end_row, line, 1)
        line += 1
        separator = QFrame()
        separator.setFrameShape(QFrame.HLine)
        separator.setFrameShadow(QFrame.Plain)
        grid.addWidget(separator, line, 0, 1, 8)
        line += 1
        grid.addWidget(self._btn_send, line, 5)
        grid.addWidget(self._btn_exit, line, 6)
        self.move(300, 150)
        self.setWindowTitle('OA Send Mail')
        self.setStatusBar(self._status_bar)
        self._status_bar.showMessage("选择配置的EXCEL文件,进行批量发送")
        QMainWindow.show(self)

    def radio_clicked(self):
        radio = self.sender()
        for x in self._ctrl_matrix:
            if x[1] == radio:
                x[1].setChecked(True)
                x[2].setEnabled(True)
                x[4].setEnabled(False)
            elif x[3] == radio:
                x[3].setChecked(True)
                x[4].setEnabled(True)
                x[2].setEnabled(False)
        pass

    def open_xls_clicked(self):
        """
        打开文件对话框,
        """
        file_name, file_type = QFileDialog.getOpenFileName(
            self, "选取EXCEL文件", "./",
            "Excel Files (*.xls *.xlsx);;All Files (*)")
        if file_name == "":
            self._status_bar.showMessage("必须选择配置的EXCEL文件,才能进行批量发送")
            pass
        self._status_bar.showMessage("已经选择了EXCEL,请选择Sheet")
        self._edit_open_xls.setText(file_name)
        success_open = self._batch_send.open_excel(file_name)
        if not success_open:
            QMessageBox.information(self, "提示", "无法打开对应的EXCEL文件。",
                                    QMessageBox.Ok)
        self._combo_xls_sheet.clear()
        self._combo_xls_sheet.addItems(self._batch_send.sheets_name)
        pass

    def send_mail(self) -> bool:
        """
        发送邮件,
        """
        if self._ctrl_matrix[0][1].isChecked():
            self._column_config.sender = int(self._ctrl_matrix[0][2].text())
            if self._column_config.sender == 0:
                self._status_bar.showMessage("没有填写默认发送人时,发送人列号不能是0")
                return False
        else:
            self._column_config.sender = 0
            self._default_mail.sender = self._ctrl_matrix[0][4].text()
        if self._ctrl_matrix[1][1].isChecked():
            self._column_config.to = int(self._ctrl_matrix[1][2].text())
            if self._column_config.to == 0:
                self._status_bar.showMessage("没有填写默认接收人时,接收人列号不能是0")
                return False
            else:
                if self._column_config.sender == self._column_config.to:
                    self._status_bar.showMessage("不能出现相同的列号")
                    return False
        else:
            self._column_config.to = 0
            self._default_mail.to = self._ctrl_matrix[1][4].text()
        if self._ctrl_matrix[2][1].isChecked():
            self._column_config.cc = int(self._ctrl_matrix[2][2].text())
            if self._column_config.cc == 0:
                self._status_bar.showMessage("没有填写默认抄送人时,抄送人列号不能是0")
                return False
            else:
                if self._column_config.sender == self._column_config.to or \
                        self._column_config.to == self._column_config.cc:
                    self._status_bar.showMessage("不能出现相同的列号")
                    return False
        else:
            self._column_config.cc = 0
            self._default_mail.cc = self._ctrl_matrix[2][4].text()
        if self._ctrl_matrix[3][1].isChecked():
            self._column_config.subject = int(self._ctrl_matrix[3][2].text())
            if self._column_config.subject == 0:
                self._status_bar.showMessage("没有填写默认标题时,标题列号不能是0")
                return False
        else:
            self._column_config.subject = 0
            self._default_mail.subject = self._ctrl_matrix[3][4].text()
        if self._ctrl_matrix[4][1].isChecked():
            self._column_config.body = int(self._ctrl_matrix[4][2].text())
            if self._column_config.body == 0:
                self._status_bar.showMessage("没有填写默认内容时,内容列号不能是0")
                return False
            else:
                if self._column_config.sender == self._column_config.to or \
                        self._column_config.to == self._column_config.cc:
                    self._status_bar.showMessage("不能出现相同的列号")
                    return False
        else:
            self._column_config.body = 0
            self._default_mail.body = self._ctrl_matrix[4][4].text()

        self._row_config.send_start = int(self._edit_start_row.text())
        self._row_config.send_end = int(self._edit_end_row.text())
        if self._row_config.send_start >= self._row_config.send_end:
            self._status_bar.showMessage("起始,结束发送行错误")
            return False
        self._row_config.mail_count = self._row_config.send_end - self._row_config.send_start + 1
        cfg_success = self._batch_send.config(self._column_config,
                                              self._row_config,
                                              self._default_mail)
        if not cfg_success:
            self._status_bar.showMessage("配置存在问题,请检查")
            return False
        else:
            self._status_bar.showMessage("配置正确,准备发送{}封邮件".format(
                self._row_config.mail_count))
        i = 0
        j = self._row_config.send_start
        while j <= self._row_config.send_end:
            send_result = self._batch_send.send_one(j)
            if not send_result:
                self._status_bar.showMessage(
                    str("发送第{}封,第{}行邮件失败").format(i + 1, j))
                return False
            j += 1
            i += 1
            self._status_bar.showMessage(
                str("发送第{}封,第{}行邮件成功").format(i + 1, j))
        self._status_bar.showMessage("全部发送完成")
        return True

    def exit_app(self):
        self._status_bar.showMessage("下次再见")
        QApplication.quit()

    def combo_sheet_changed(self):
        load_ok = self._batch_send.load_sheet_byname(
            self._combo_xls_sheet.currentText())
        if not load_ok:
            self._status_bar.showMessage("加载EXCEL对应的sheet失败,请检查表格")
            return
        out_info = "加载sheet[{}]成功.起始结束行列{}".format(
            self._combo_xls_sheet.currentText(),
            self._batch_send.cur_sheet_info())
        self._status_bar.showMessage(out_info)
        s_r, s_c, e_r, e_c = self._batch_send.cur_sheet_info()
        self._row_config.caption = s_r
        self._row_config.send_start = s_r + 1
        self._row_config.send_end = e_r
        self._row_config.mail_count = e_r - s_r
        self._edit_start_row.setText(str(self._row_config.send_start))
        self._edit_end_row.setText(str(self._row_config.send_end))

    def bps_start(self) -> bool:
        start_ok = self._batch_send.start()
        if not start_ok:
            QMessageBox.information(window, "提示",
                                    "OA Send Mail需要Outlook和Excel,否则无法使用。",
                                    QMessageBox.Ok)
            QApplication.quit()
        return True

    def closeEvent(self, event):
        """
        重写closeEvent方法,实现dialog窗体关闭时执行一些代码
        """
        self._batch_send.close()