Example #1
0
class SnapshotStatusLog(QWidget):
    """ Command line like logger widget """
    def __init__(self, parent=None):
        QWidget.__init__(self, parent)
        self.sts_log = QPlainTextEdit(self)
        self.sts_log.setReadOnly(True)

        layout = QVBoxLayout()
        layout.setContentsMargins(10, 10, 10, 10)
        layout.addWidget(self.sts_log)
        self.setLayout(layout)

    def log_msgs(self, msgs, msg_times):
        if not isinstance(msgs, list):
            msgs = [msgs]

        if not isinstance(msg_times, list):
            msg_times = [msg_times] * len(msgs)

        msg_times = (datetime.datetime.fromtimestamp(t).strftime('%H:%M:%S.%f')
                     for t in msg_times)
        self.sts_log.insertPlainText("\n".join("[{}] {}".format(*t)
                                               for t in zip(msg_times, msgs)) +
                                     "\n")
        self.sts_log.ensureCursorVisible()
Example #2
0
    def __init__(self):
        super(LicenseDialog, self).__init__()

        self.resize(650, 450)

        license_text = QPlainTextEdit()
        license_text.setReadOnly(True)
        fixed_font = QFontDatabase.systemFont(QFontDatabase.FixedFont)
        license_text.setFont(fixed_font)
        license_text.insertPlainText(gplv3.get_txt())
        license_text.moveCursor(QTextCursor.Start)
        license_text.ensureCursorVisible()


        button_box = QDialogButtonBox(QDialogButtonBox.Ok)
        button_box.accepted.connect(self.accept)

        layout = QVBoxLayout()
        layout.setContentsMargins(10, 10, 10, 10)
        layout.addWidget(license_text)
        layout.addWidget(button_box)
        self.setLayout(layout)
        self.setWindowTitle("License")
Example #3
0
class Example(QMainWindow):

    def __init__(self,author_config="author_config.cfg",aff_config="aff_config.cfg"):
        super().__init__()
        self.initUI()
        self.author=None
        self.abs=None
        self.aff=None
        logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
                            stream=sys.stdout)
        logging.root.setLevel(logging.ERROR)
        logging.getLogger("pdfminer").setLevel(logging.ERROR)
        logging.getLogger("Ilogger").setLevel(logging.INFO)
        self.logger = logging.getLogger("Ilogger")
        self.author_config=author_config
        self.aff_config=aff_config

        au_path = os.path.join(os.path.abspath("."), self.author_config)
        self.au_show=showconfig(au_path, config=CLEAR_DEF)
        aff_path = os.path.join(os.path.abspath("."), self.aff_config)
        self.aff_show=showconfig(aff_path, config=AFFILIATION_SUP_CLEAR_DICT)



    def initUI(self):
        sys.stdout = EmittingStr(textWritten=self.outputWritten)
        sys.stderr = EmittingStr(textWritten=self.outputWritten)
        lbl = QLabel("抽取项目:", self)
        lbl.move(50,50)
        lb2 = QLabel("作者:", self)
        lb2.move(50, 100)


        author=QComboBox(self)
        author.addItems(["True","False"])
        author.setCurrentIndex(1)
        author.move(100,100)


        author.activated[str].connect(self.author_change)
        lb3 = QLabel("摘要:", self)
        lb3.move(50, 150)

        abs = QComboBox(self)
        abs.addItems(["True", "False"])
        abs.setCurrentIndex(1)
        abs.move(100, 150)


        lb4 = QLabel("机构:", self)
        lb4.move(250, 100)

        affs = QComboBox(self)
        affs.addItems(["True", "False"])
        affs.setCurrentIndex(1)
        affs.move(300, 100)

        author.activated[str].connect(self.author_change)
        abs.activated[str].connect(self.abs_change)
        affs.activated[str].connect(self.aff_change)

        lb5 = QLabel("EXCEL路径:", self)
        lb5.move(50, 200)

        self.le = ClickLine(self)
        self.le.resize(200,30)
        self.le.move(150,200)

        btn3 = QPushButton("作者清洗配置", self)
        btn3.move(50, 250)
        btn3.clicked.connect(self.author_clear_show)

        btn4 = QPushButton("机构清洗配置", self)
        btn4.move(200, 250)
        btn4.clicked.connect(self.aff_clear_show)

        btn5 = QPushButton("测试", self)
        btn5.move(250, 250)
        btn5.clicked.connect(self.clear_test)

        btn2 = QPushButton("启动", self)
        btn2.move(50, 300)

        btn2.clicked.connect(self.buttonClicked)

        self.textBrowser=QPlainTextEdit(self)
        self.textBrowser.move(50,350)
        self.textBrowser.resize(400,200)

        self.setGeometry(300, 300, 500, 600)
        self.setWindowTitle('PDF抽取工具')
        self.show()

    def outputWritten(self, text):
        cursor = self.textBrowser.textCursor()
        cursor.movePosition(QtGui.QTextCursor.End)
        cursor.insertText(text)
        self.textBrowser.setTextCursor(cursor)
        self.textBrowser.ensureCursorVisible()

    def buttonClicked(self):
        # print("-----------",os.path.abspath("."))

        find_author=self.author==str(True)
        find_abs=self.abs==str(True)
        find_affs=self.aff==str(True)

        path=self.le.text()
        if not os.path.exists(path):
            self.logger.error("EXCEL路径不正确!")
            return
        # print(find_author,find_abs,(find_author or find_abs))
        if not (find_author or find_abs):
            self.logger.error("作者摘要都不为True!")
            return

        et=excel_thread(path,find_author,find_abs,find_affs,logger=self.logger,use_absnlppath=True)
        et.setDaemon(True)
        et.start()

    def clear_test(self):
        pass


    def author_clear_show(self):
        self.au_show.show()

    def aff_clear_show(self):
        self.aff_show.show()

    def author_change(self, text):
        self.author=text
    def abs_change(self,text):
        self.abs=text

    def aff_change(self,text):
        self.aff=text
Example #4
0
class View(QWidget):

    # Send data to port
    send_data = pyqtSignal(object)
    # Chage baudrate
    baudrate_changed = pyqtSignal(object)
    # Change end of line
    eol_changed = pyqtSignal(object)
    # Change port
    port_changed = pyqtSignal(object)
    # Pause model
    pause_m = pyqtSignal(object)
    # Continue model
    start_m = pyqtSignal(object)

    def __init__(self):
        QWidget.__init__(self)

        self.queue = None
        self.end_cmd = None
        self.autoscroll = False
        self.msg_sent = False

        self.timer = QTimer()
        self.timer.timeout.connect(self.update_gui)
        self.timer.start(100)

        self.__initUI()

    def __initUI(self):
        vbox = QVBoxLayout(self)
        # vbox.setSpacing(0)
        vbox.setContentsMargins(3, 3, 3, 3)

        # Add window's menu bar
        self.menubar = QMenuBar()
        file_menu = self.menubar.addMenu('File')
        file_menu.addAction('Save', self.save_to_file)
        vbox.addWidget(self.menubar)

        # Command box
        cmd_hbox = QHBoxLayout()

        self.cmd_edit = QLineEdit()
        cmd_hbox.addWidget(self.cmd_edit)

        cmd_btn = QPushButton('Send')
        cmd_btn.clicked.connect(self.emit_send_data)
        cmd_hbox.addWidget(cmd_btn)

        cmd_btn = QPushButton('Start')
        cmd_btn.clicked.connect(self.start_m.emit)
        cmd_hbox.addWidget(cmd_btn)

        cmd_btn = QPushButton('Stop')
        cmd_btn.clicked.connect(self.pause_m.emit)
        cmd_hbox.addWidget(cmd_btn)

        vbox.addLayout(cmd_hbox)

        # Editors pair box
        editor_hbox = QHBoxLayout()

        # Text edit area
        self.editer = QPlainTextEdit()
        self.editer.scrollContentsBy = self.ModScrollContentsBy
        editor_hbox.addWidget(self.editer)

        # HEX edit area
        self.editor_hex = QPlainTextEdit()
        self.editor_hex.scrollContentsBy = self.ModScrollContentsBy
        editor_hbox.addWidget(self.editor_hex)

        vbox.addLayout(editor_hbox)

        # Settings area
        stng_hbox = QHBoxLayout()

        # - Autoscroll
        chk_btn = QCheckBox('Autoscroll')
        chk_btn.stateChanged.connect(self.set_autoscroll)
        stng_hbox.addWidget(chk_btn)

        cmd_btn = QPushButton('Clear')
        cmd_btn.clicked.connect(self.editer.clear)
        cmd_btn.clicked.connect(self.editor_hex.clear)
        stng_hbox.addWidget(cmd_btn)

        stng_hbox.addStretch(1)

        # - Ending of line
        self.eol_menu = QComboBox()
        self.eol_menu.addItem('No line ending')
        self.eol_menu.addItem('Newline')
        self.eol_menu.addItem('Carriage return')
        self.eol_menu.addItem('Both NL + CR')
        self.eol_menu.setCurrentIndex(0)
        self.eol_menu.currentIndexChanged.connect(self.emit_eol_changed)
        stng_hbox.addWidget(self.eol_menu)

        # - Baudrate select
        self.br_menu = QComboBox()
        self.br_menu.addItem('300 baud')
        self.br_menu.addItem('1200 baud')
        self.br_menu.addItem('2400 baud')
        self.br_menu.addItem('4800 baud')
        self.br_menu.addItem('9600 baud')
        self.br_menu.addItem('19200 baud')
        self.br_menu.addItem('38400 baud')
        self.br_menu.addItem('57600 baud')
        self.br_menu.addItem('115200 baud')
        self.br_menu.addItem('230400 baud')
        self.br_menu.addItem('460800 baud')
        self.br_menu.currentIndexChanged.connect(self.emit_br_changed)
        # Set default baudrate 9600
        self.br_menu.setCurrentIndex(4)

        stng_hbox.addWidget(self.br_menu)

        vbox.addLayout(stng_hbox)

        # Port editing form
        port_hbox = QHBoxLayout()
        port_lbl = QLabel('Port: ')
        port_hbox.addWidget(port_lbl)

        self.port_edit = QLineEdit()

        self.port_edit.editingFinished.connect(self.changePort)
        port_hbox.addWidget(self.port_edit)

        vbox.addLayout(port_hbox)

        # Status Bar
        self.status_bar = QStatusBar()

        self.status_label = QLabel()
        self.status_label.setAlignment(Qt.AlignRight)

        self.status_bar.addWidget(self.status_label, 1)
        vbox.addWidget(self.status_bar)

        self.setLayout(vbox)

    def show_error(self, value):
        msg = QMessageBox(QMessageBox.NoIcon, 'Error occured.', value,
                          QMessageBox.Ok)
        msg.exec()

#==============================================================================
# Get, set
#==============================================================================

    def set_queue(self, queue):
        self.queue = queue

    def set_end_cmd(self, end_cmd):
        self.end_cmd = end_cmd

    def set_autoscroll(self, value):
        self.autoscroll = value

    def set_port(self, value):
        self.port_edit.insert(value)

    def get_cmd(self):
        return self.cmd_edit.text()

    def set_eol(self, value):
        self.eol_menu.setCurrentIndex(value)

    def update_status_bar(self, data_set):
        '''
        Update GUI status bar.
        Args:
            data_set: Dictionary with port configurations: port, baudrate,
            number of bits, parity, number of stop bits.
        '''
        string = '{} {}-{}-{}'.format(data_set['baudrate'],
                                      data_set['num_of_bits'],
                                      data_set['parity'],
                                      data_set['num_of_stop'])

        self.status_label.setText(string)

    def update_gui(self):
        self.process_incoming()
        self.update()

    def appendText(self, data):
        # pos = QPoint(self.editer.textCursor().position(), 0)
        # self.editer.moveCursor(QTextCursor.End)
        # self.editer.insertPlainText(text)
        self.editer.appendPlainText(data[0])
        # self.editer.cursorForPosition(pos)

        self.editor_hex.appendHtml(data[1])

    def process_incoming(self):
        while self.queue.qsize():
            try:
                msg = self.queue.get(0)
                # Check contents of message and do what it says
                # As a test, we simply print it
                # print(bytes(msg, 'ASCII'), end='')
                # self.editer.appendPlainText(msg)
                self.appendText(msg)
                if self.autoscroll:
                    self.editer.ensureCursorVisible()
                    self.editor_hex.ensureCursorVisible()
                    self.scroll_down()
            except Queue.empty:
                pass

    def scroll_down(self):
        for editor in [self.editer, self.editor_hex]:
            sb = editor.verticalScrollBar()
            sb.setValue(sb.maximum())
            editor.moveCursor(QTextCursor.End)

    def changePort(self):
        if not self.msg_sent:
            self.msg_sent = True
            self.emit_port_changed()
        else:
            self.msg_sent = False
            return None
#==============================================================================
# Utils
#==============================================================================

    def save_to_file(self):
        _file = QFileDialog.getSaveFileName()
        if _file[0]:
            with open(_file[0], 'w+') as fn:
                fn.write(self.editer.toPlainText())

#==============================================================================
# Signals
#==============================================================================

    def emit_send_data(self):
        self.send_data.emit(self.get_cmd())
        self.cmd_edit.clear()

    def emit_br_changed(self, value):
        baudrate = self.br_menu.itemText(value)[:-5]
        self.baudrate_changed.emit(baudrate)

    def emit_eol_changed(self, value):
        self.eol_changed.emit(value)

    def emit_port_changed(self):
        self.port_edit.clearFocus()
        self.port_changed.emit(self.port_edit.text())

#==============================================================================
# Events
#==============================================================================

    def ModScrollContentsBy(self, dx, dy):
        # print('as: {}. dx: {}. dy: {}.'.format(self.autoscroll, dx, dy))
        for editor in [self.editer, self.editor_hex]:
            if self.autoscroll:
                editor.ensureCursorVisible()
            else:
                QPlainTextEdit.scrollContentsBy(editor, dx, dy)

    def closeEvent(self, event):
        self.end_cmd()
        QWidget.closeEvent(self, event)
        print('exit')
Example #5
0
class View(QWidget):

    # Send data to port
    send_data           = pyqtSignal(object)
    # Chage baudrate
    baudrate_changed    = pyqtSignal(object)
    # Change end of line
    eol_changed         = pyqtSignal(object)
    # Change port
    port_changed        = pyqtSignal(object)
    # Pause model
    pause_m             = pyqtSignal(object)
    # Continue model
    start_m             = pyqtSignal(object)

    def __init__(self):
        QWidget.__init__(self)

        self.queue      = None
        self.end_cmd    = None
        self.autoscroll = False
        self.msg_sent   = False

        self.timer = QTimer()
        self.timer.timeout.connect(self.update_gui)
        self.timer.start(100)
                
        self.__initUI()

    def __initUI(self):
        vbox = QVBoxLayout(self)

        # Command box
        cmd_hbox = QHBoxLayout()

        self.cmd_edit = QLineEdit()
        cmd_hbox.addWidget(self.cmd_edit)

        cmd_btn = QPushButton('Send')
        cmd_btn.clicked.connect(self.emit_send_data)
        cmd_hbox.addWidget(cmd_btn)

        cmd_btn = QPushButton('Start')
        cmd_btn.clicked.connect(self.start_m.emit)
        cmd_hbox.addWidget(cmd_btn)

        cmd_btn = QPushButton('Stop')
        cmd_btn.clicked.connect(self.pause_m.emit)
        cmd_hbox.addWidget(cmd_btn)

        vbox.addLayout(cmd_hbox)

        # Text edit area
        self.editer = QPlainTextEdit()
        self.editer.scrollContentsBy = self.ModScrollContentsBy
        vbox.addWidget(self.editer)

        # Settings area
        stng_hbox = QHBoxLayout()

        # - Autoscroll
        chk_btn = QCheckBox('Autoscroll')
        chk_btn.stateChanged.connect(self.set_autoscroll)
        stng_hbox.addWidget(chk_btn)

        cmd_btn = QPushButton('Clear')
        cmd_btn.clicked.connect(self.editer.clear)
        stng_hbox.addWidget(cmd_btn)

        stng_hbox.addStretch(1)

        # - Ending of line
        self.eol_menu = QComboBox()
        self.eol_menu.addItem('No line ending')
        self.eol_menu.addItem('Newline')
        self.eol_menu.addItem('Carriage return')
        self.eol_menu.addItem('Both NL + CR')
        self.eol_menu.setCurrentIndex(0)
        self.eol_menu.currentIndexChanged.connect(self.emit_eol_changed)
        stng_hbox.addWidget(self.eol_menu)

        # - Baudrate select
        self.br_menu = QComboBox()
        self.br_menu.addItem('300 baud')
        self.br_menu.addItem('1200 baud')
        self.br_menu.addItem('2400 baud')
        self.br_menu.addItem('4800 baud')
        self.br_menu.addItem('9600 baud')
        self.br_menu.addItem('19200 baud')
        self.br_menu.addItem('38400 baud')
        self.br_menu.addItem('57600 baud')
        self.br_menu.addItem('115200 baud')
        self.br_menu.addItem('230400 baud')
        self.br_menu.addItem('460800 baud')
        self.br_menu.currentIndexChanged.connect(self.emit_br_changed)
        # Set default baudrate 9600
        self.br_menu.setCurrentIndex(4)

        stng_hbox.addWidget(self.br_menu)

        vbox.addLayout(stng_hbox)

        port_hbox = QHBoxLayout()
        port_lbl = QLabel('Port: ')
        port_hbox.addWidget(port_lbl)

        self.port_edit = QLineEdit()

        self.port_edit.editingFinished.connect(self.changePort)
        port_hbox.addWidget(self.port_edit)

        vbox.addLayout(port_hbox)

        self.setLayout(vbox)

    def show_error(self, value):
        msg = QMessageBox(
                QMessageBox.NoIcon, 'Error occured.', value, QMessageBox.Ok)
        msg.exec()

#==============================================================================
# Get, set
#==============================================================================

    def set_queue(self, queue):
        self.queue = queue

    def set_end_cmd(self, end_cmd):
        self.end_cmd = end_cmd

    def set_autoscroll(self, value):
        print('Set autoscroll: {}.'.format(value))
        self.autoscroll = value

    def set_port(self, value):
        self.port_edit.insert(value)

    def get_cmd(self):
        return self.cmd_edit.text()

    def set_eol(self, value):
        self.eol_menu.setCurrentIndex(value)

    def closeEvent(self, event):
        self.end_cmd()
        QWidget.closeEvent(self, event)
        print('exit')

    def update_gui(self):
        self.process_incoming()
        self.update()

    def process_incoming(self):
        while self.queue.qsize():
            try:
                msg = self.queue.get(0)
                # Check contents of message and do what it says
                # As a test, we simply print it
                print(str(msg))
                self.editer.appendPlainText(str(msg))
                if self.autoscroll:
                    self.editer.ensureCursorVisible()
                    self.scroll_down()
            except Queue.empty:
                pass

    def scroll_down(self):
        sb = self.editer.verticalScrollBar()
        sb.setValue(sb.maximum())
        self.editer.moveCursor(QTextCursor.End)

    def changePort(self):
        if not self.msg_sent:
            self.msg_sent = True
            self.emit_port_changed()
        else:
            self.msg_sent = False
            return None

#==============================================================================
# Signals
#==============================================================================

    def emit_send_data(self):
        self.send_data.emit(self.get_cmd())
        self.cmd_edit.clear()

    def emit_br_changed(self, value):
        baudrate = self.br_menu.itemText(value)[:-5]
        self.baudrate_changed.emit(baudrate)

    def emit_eol_changed(self, value):
        self.eol_changed.emit(value)

    def emit_port_changed(self):
        self.port_edit.clearFocus()
        self.port_changed.emit(self.port_edit.text())

#==============================================================================
# Events
#==============================================================================
    def ModScrollContentsBy(self, dx, dy):
        if self.autoscroll:
            self.editer.ensureCursorVisible()
        else:
            QPlainTextEdit.scrollContentsBy(self.editer, dx, dy)
class Window(QDialog):
    def __init__(self):
        QDialog.__init__(self)

        self.target_codec = 'hevc'
        self.logIsTerse = True
        self.printProgress = True
        defaultDirectory = "/media/"

        screen1 = QHBoxLayout()

        self.setLayout(screen1)
        self.inputBox = QLineEdit(defaultDirectory)
        browseContainer = QVBoxLayout()
        inputBrowseContainer = QHBoxLayout()
        inputBrowseContainer.addWidget(self.inputBox)

        self.consoleBox = QPlainTextEdit()

        analyzeButton = QPushButton("Analyze")
        analyzeButton.clicked.connect(self.analyze)
        saveLogButton = QPushButton("Save log to directory")
        saveLogButton.clicked.connect(self.saveLog)

        browseContainer.addLayout(inputBrowseContainer)

        browseContainer.addWidget(analyzeButton)
        browseContainer.addWidget(self.consoleBox)
        browseContainer.addWidget(saveLogButton)

        screen1.addLayout(browseContainer)

    def saveLog(self):
        savedir = self.getDirString()
        os.chdir(savedir)

        if self.consoleBox.blockCount() <= 1:
            self.analyze()

        with open("ConversionLog" + str(time.strftime("%Y%m%d")) + ".txt",
                  'w',
                  encoding="utf8") as logFile:
            logFile.write("Generated on: " +
                          str(time.strftime("%b %d %Y, %I:%M %p")) + "\n")
            if self.logIsTerse:
                logFile.write("Log is Terse\n\n")
            logFile.write(str(self.consoleBox.toPlainText()))

    def analyze(self):

        self.consoleBox.clear()
        print("Analyzing")

        rootdir = self.getDirString()
        directoryList = []
        infoTuples = []
        fileExtensionsToAnalyze = [
            '.mp4', '.mkv', '.avi', '.m4v', '.wmv', '.MP4', '.MKV', '.AVI',
            '.M4V', '.wmv'
        ]
        invalidFilesList = []

        # Build list of immediate subdirectories
        for fileNames in os.listdir(rootdir):
            if os.path.isdir(rootdir + fileNames):
                directoryList.append(fileNames)
        directoryList = sorted(directoryList)

        # Scan subdirectories and tally info
        for dirs in directoryList:

            numberOfFiles = 0
            sizeOfFiles = 0

            numberOfInvalidFiles = 0
            sizeOfInvalidFiles = 0

            sizeOfOtherFiles = 0
            if self.printProgress:
                print()
                print(dirs)

            # Build filelist for subdirectories, start tallying by type
            for fileNames in os.listdir(rootdir + dirs):
                filePath = os.path.join(rootdir + dirs, fileNames)

                if os.path.isdir(filePath):
                    sizeOfOtherFiles += get_dir_size_recursive(filePath)

                else:
                    if any(extensions in fileNames
                           for extensions in fileExtensionsToAnalyze):
                        mediaInfo = MediaObject(filePath)
                        mediaInfo.run()

                        if mediaInfo.fileIsValid:
                            codec = mediaInfo.videoCodec

                            if codec != self.target_codec:
                                numberOfFiles += 1
                                sizeOfFiles += os.path.getsize(filePath)
                        else:
                            invalidFilesList.append(filePath)
                            numberOfInvalidFiles += 1
                            sizeOfInvalidFiles += os.path.getsize(filePath)
                    else:
                        sizeOfOtherFiles += os.path.getsize(filePath)

            #  Changes bytes to Megabytes
            sizeOfFiles /= 1000000
            sizeOfInvalidFiles /= 1000000
            sizeOfOtherFiles /= 1000000

            # Don't worry about directories with nothing to convert
            if numberOfFiles > 0:
                infoTuples.append(
                    (sizeOfFiles, numberOfFiles, dirs, sizeOfInvalidFiles,
                     numberOfInvalidFiles, sizeOfOtherFiles))

        # Sorts by file sizes
        printableList = sorted(infoTuples)
        self.printAnalysis(printableList, invalidFilesList)

    def printAnalysis(self, printableList, invalidFilesList):
        # Print the tuples, big numbers first
        for i in range(len(printableList) - 1, -1, -1):
            sys.stdout = EmittingStream(textWritten=self.normalOutputWritten)
            print(printableList[i][2])
            print()
            print("Size of h264 files: " +
                  str(math.floor((printableList[i][0] * 100)) / 100) + " MB")
            print("Number of h264 files: " + str(printableList[i][1]))
            print()

            if self.logIsTerse == False or printableList[i][4] > 0:
                print("Size of invalid files: " +
                      str(math.floor((printableList[i][3] * 100)) / 100) +
                      " MB")
                print("Number of invalid files: " + str(printableList[i][4]))
                print()

            if self.logIsTerse == False or printableList[i][5] > 0:
                print("Size of other files & folders: " +
                      str(math.floor((printableList[i][5] * 100)) / 100) +
                      " MB")
                print()

            print()
            print()

        print("Invalid/malformed files:")
        for i in range(0, len(invalidFilesList) - 1):
            print("     " + invalidFilesList[i])

        # Scrolls back to top of list for reading
        cursor = self.consoleBox.textCursor()
        cursor.setPosition(0)
        self.consoleBox.setTextCursor(cursor)

    def getDirString(self):
        inputText = self.inputBox.text()
        if sys.platform == 'win32':
            if inputText[len(inputText) - 1] is not "\\":
                inputText += "\\"
        return inputText

    def normalOutputWritten(self, text):
        cursor = self.consoleBox.textCursor()
        cursor.movePosition(QTextCursor.End)
        cursor.insertText(text)
        self.consoleBox.setTextCursor(cursor)
        self.consoleBox.ensureCursorVisible()

    def __del__(self):
        sys.stdout = sys.__stdout__
Example #7
0
class HgServeDialog(E5MainWindow):
    """
    Class implementing a dialog for the Mercurial server.
    """
    def __init__(self, vcs, path, parent=None):
        """
        Constructor
        
        @param vcs reference to the vcs object
        @param path path of the repository to serve (string)
        @param parent reference to the parent widget (QWidget)
        """
        super(HgServeDialog, self).__init__(parent)

        self.vcs = vcs
        self.__repoPath = path

        self.__styles = [
            "paper",
            "coal",
            "gitweb",
            "monoblue",
            "spartan",
        ]

        self.setWindowTitle(self.tr("Mercurial Server"))

        self.__startAct = QAction(
            UI.PixmapCache.getIcon(
                os.path.join("VcsPlugins", "vcsMercurial",
                             "icons", "startServer.png")),
            self.tr("Start Server"), self)
        self.__startAct.triggered.connect(self.__startServer)
        self.__stopAct = QAction(
            UI.PixmapCache.getIcon(
                os.path.join("VcsPlugins", "vcsMercurial", "icons",
                             "stopServer.png")), self.tr("Stop Server"), self)
        self.__stopAct.triggered.connect(self.__stopServer)
        self.__browserAct = QAction(UI.PixmapCache.getIcon("home.png"),
                                    self.tr("Start Browser"), self)
        self.__browserAct.triggered.connect(self.__startBrowser)

        self.__portSpin = QSpinBox(self)
        self.__portSpin.setMinimum(2048)
        self.__portSpin.setMaximum(65535)
        self.__portSpin.setToolTip(self.tr("Enter the server port"))
        self.__portSpin.setValue(
            self.vcs.getPlugin().getPreferences("ServerPort"))

        self.__styleCombo = QComboBox(self)
        self.__styleCombo.addItems(self.__styles)
        self.__styleCombo.setToolTip(self.tr("Select the style to use"))
        self.__styleCombo.setCurrentIndex(
            self.__styleCombo.findText(
                self.vcs.getPlugin().getPreferences("ServerStyle")))

        self.__serverToolbar = QToolBar(self.tr("Server"), self)
        self.__serverToolbar.addAction(self.__startAct)
        self.__serverToolbar.addAction(self.__stopAct)
        self.__serverToolbar.addSeparator()
        self.__serverToolbar.addWidget(self.__portSpin)
        self.__serverToolbar.addWidget(self.__styleCombo)

        self.__browserToolbar = QToolBar(self.tr("Browser"), self)
        self.__browserToolbar.addAction(self.__browserAct)

        self.addToolBar(Qt.TopToolBarArea, self.__serverToolbar)
        self.addToolBar(Qt.TopToolBarArea, self.__browserToolbar)

        self.__log = QPlainTextEdit(self)
        self.setCentralWidget(self.__log)

        # polish up the dialog
        self.__startAct.setEnabled(True)
        self.__stopAct.setEnabled(False)
        self.__browserAct.setEnabled(False)
        self.__portSpin.setEnabled(True)
        self.__styleCombo.setEnabled(True)
        self.resize(QSize(800, 600).expandedTo(self.minimumSizeHint()))

        self.process = QProcess()
        self.process.finished.connect(self.__procFinished)
        self.process.readyReadStandardOutput.connect(self.__readStdout)
        self.process.readyReadStandardError.connect(self.__readStderr)

        self.cNormalFormat = self.__log.currentCharFormat()
        self.cErrorFormat = self.__log.currentCharFormat()
        self.cErrorFormat.setForeground(
            QBrush(Preferences.getUI("LogStdErrColour")))

    def __startServer(self):
        """
        Private slot to start the Mercurial server.
        """
        port = self.__portSpin.value()
        style = self.__styleCombo.currentText()

        args = self.vcs.initCommand("serve")
        args.append("-v")
        args.append("--port")
        args.append(str(port))
        args.append("--style")
        args.append(style)

        self.process.setWorkingDirectory(self.__repoPath)

        self.process.start('hg', args)
        procStarted = self.process.waitForStarted(5000)
        if procStarted:
            self.__startAct.setEnabled(False)
            self.__stopAct.setEnabled(True)
            self.__browserAct.setEnabled(True)
            self.__portSpin.setEnabled(False)
            self.__styleCombo.setEnabled(False)
            self.vcs.getPlugin().setPreferences("ServerPort", port)
            self.vcs.getPlugin().setPreferences("ServerStyle", style)
        else:
            E5MessageBox.critical(
                self, self.tr('Process Generation Error'),
                self.tr('The process {0} could not be started. '
                        'Ensure, that it is in the search path.').format('hg'))

    def __stopServer(self):
        """
        Private slot to stop the Mercurial server.
        """
        if self.process is not None and \
           self.process.state() != QProcess.NotRunning:
            self.process.terminate()
            self.process.waitForFinished(5000)
            if self.process.state() != QProcess.NotRunning:
                self.process.kill()

        self.__startAct.setEnabled(True)
        self.__stopAct.setEnabled(False)
        self.__browserAct.setEnabled(False)
        self.__portSpin.setEnabled(True)
        self.__styleCombo.setEnabled(True)

    def __startBrowser(self):
        """
        Private slot to start a browser for the served repository.
        """
        ui = e5App().getObject("UserInterface")
        ui.launchHelpViewer("http://localhost:{0}".format(
            self.__portSpin.value()))

    def closeEvent(self, e):
        """
        Protected slot implementing a close event handler.
        
        @param e close event (QCloseEvent)
        """
        self.__stopServer()

    def __procFinished(self, exitCode, exitStatus):
        """
        Private slot connected to the finished signal.
        
        @param exitCode exit code of the process (integer)
        @param exitStatus exit status of the process (QProcess.ExitStatus)
        """
        self.__stopServer()

    def __readStdout(self):
        """
        Private slot to handle the readyReadStandardOutput signal.
        
        It reads the output of the process and inserts it into the log.
        """
        if self.process is not None:
            s = str(self.process.readAllStandardOutput(),
                    self.vcs.getEncoding(), 'replace')
            self.__appendText(s, False)

    def __readStderr(self):
        """
        Private slot to handle the readyReadStandardError signal.
        
        It reads the error output of the process and inserts it into the log.
        """
        if self.process is not None:
            s = str(self.process.readAllStandardError(),
                    self.vcs.getEncoding(), 'replace')
            self.__appendText(s, True)

    def __appendText(self, txt, error=False):
        """
        Private method to append text to the end.
        
        @param txt text to insert (string)
        @param error flag indicating to insert error text (boolean)
        """
        tc = self.__log.textCursor()
        tc.movePosition(QTextCursor.End)
        self.__log.setTextCursor(tc)
        if error:
            self.__log.setCurrentCharFormat(self.cErrorFormat)
        else:
            self.__log.setCurrentCharFormat(self.cNormalFormat)
        self.__log.insertPlainText(txt)
        self.__log.ensureCursorVisible()
Example #8
0
class QtGUI(QMainWindow):
    def __init__(self):
        super().__init__()

        self.widgets = {
        }  # dictionary of some mutable widgets, for easier manipulation
        self.parse_thread = None  # defined here just to appease PEP
        self.parse_worker = None  # defined here just to appease PEP

        central_widget = QWidget(self)
        central_layout = QGridLayout(central_widget)

        # INPUT OPTIONS
        frame_iops = QGroupBox('Input options', central_widget)
        layout_iops = QGridLayout(frame_iops)

        label_mdir = QLabel(config.config['iopts']['media_dir'][1], frame_iops)
        label_mdir.setAlignment(Qt.AlignRight | Qt.AlignVCenter)
        layout_iops.addWidget(label_mdir, 0, 0)

        label_odir = QLabel(config.config['iopts']['output_dir'][1],
                            frame_iops)
        label_odir.setAlignment(Qt.AlignRight | Qt.AlignVCenter)
        layout_iops.addWidget(label_odir, 1, 0)

        self.widgets['media_dir'] = QLineEdit(frame_iops)
        self.widgets['media_dir'].editingFinished.connect(
            self.update_gui_mopts)
        layout_iops.addWidget(self.widgets['media_dir'], 0, 1)

        self.widgets['output_dir'] = QLineEdit(frame_iops)
        self.widgets['output_dir'].editingFinished.connect(
            self.update_gui_mopts)
        layout_iops.addWidget(self.widgets['output_dir'], 1, 1)

        button_mdir = QPushButton('Browse', frame_iops)
        button_mdir.clicked.connect(lambda event: self.select_dir('media_dir'))
        layout_iops.addWidget(button_mdir, 0, 2)

        button_odir = QPushButton('Browse', frame_iops)
        button_odir.clicked.connect(
            lambda event: self.select_dir('output_dir'))
        layout_iops.addWidget(button_odir, 1, 2)

        self.widgets['recursive'] = QCheckBox(
            config.config['iopts']['recursive'][1], frame_iops)
        self.widgets['recursive'].stateChanged.connect(self.update_gui_oopts)
        self.widgets['recursive'].stateChanged.connect(self.update_gui_mopts)
        layout_iops.addWidget(self.widgets['recursive'], 0, 3)

        self.widgets['parse_zip'] = QCheckBox(
            config.config['iopts']['parse_zip'][1], frame_iops)
        self.widgets['parse_zip'].stateChanged.connect(self.update_gui_oopts)
        layout_iops.addWidget(self.widgets['parse_zip'], 1, 3)

        central_layout.addWidget(frame_iops, 0, 0)

        # TABS
        tabs = QTabWidget(central_widget)

        # OUTPUT OPTIONS
        tab_oopts = QWidget(tabs)
        layout_oopts = QGridLayout(tab_oopts)

        row = 0
        for oopt, values in config.config['oopts'].items():
            self.widgets[oopt] = QCheckBox(values[1], tab_oopts)
            self.widgets[oopt].stateChanged.connect(self.update_gui_oopts)
            layout_oopts.addWidget(self.widgets[oopt], row, 0)

            # separators
            if 'output_table_titles' in oopt or 'output_separators' in oopt or 'suppress_img_warnings' in oopt:
                row += 1
                line = QFrame(tab_oopts)
                line.setFrameShape(QFrame.HLine)
                line.setFrameShadow(QFrame.Sunken)
                layout_oopts.addWidget(line, row, 0)

            # disable/enable the image-list options based on this (and 'recursive')
            if 'output_individual' in oopt:
                self.widgets[oopt].stateChanged.connect(self.update_gui_mopts)

            row += 1

        tabs.addTab(tab_oopts, 'Output options')

        # IMAGE-LIST OPTIONS
        tab_mopts = QWidget(tabs)
        layout_mopts = QGridLayout(tab_mopts)

        note_mopts = QGroupBox('Note', tab_mopts)
        layout_note_mopts = QGridLayout(note_mopts)

        label_mopts = (
            'You do not need to use these options if your image-list files are set correctly (see '
            'documentation), because the script will automatically look for the appropriate .txt files. '
            'But you can manually specify them here if the automatic feature doesn\'t work for you.'
        )
        self.label_mopts = QLabel(label_mopts, note_mopts)
        self.label_mopts.setWordWrap(True)
        layout_note_mopts.addWidget(self.label_mopts)

        label_mopts_disabled = (
            'You are using the option to output each directory as an individual file. '
            'This means you will have to rely on the automated script. It will try to find the correct image-list '
            'files for each directory. Carefully check the output log for potential problems.'
        )
        self.label_mopts_disabled = QLabel(label_mopts_disabled, note_mopts)
        self.label_mopts_disabled.setWordWrap(True)
        self.label_mopts_disabled.setVisible(True)
        layout_note_mopts.addWidget(self.label_mopts_disabled)

        layout_mopts.addWidget(note_mopts, 0, 0, 1, 2)

        self.imagelist_buttons = {}
        row = 1
        for mopt, values in config.config['mopts'].items():
            if 'string' in values[1]:
                label = QLabel(values[2] + ':', tab_mopts)
                layout_mopts.addWidget(label, row, 0)
                row += 1

                self.widgets[mopt] = QLineEdit(tab_mopts)
                layout_mopts.addWidget(self.widgets[mopt], row, 0)

                self.imagelist_buttons[mopt] = QPushButton('Browse', tab_mopts)
                self.imagelist_buttons[mopt].clicked.connect(
                    lambda event, opt=mopt: self.select_file(opt))
                layout_mopts.addWidget(self.imagelist_buttons[mopt], row, 1)

            elif 'bool' in values[1]:
                self.widgets[mopt] = QCheckBox(values[2], tab_mopts)
                self.widgets[mopt].stateChanged.connect(self.update_gui_mopts)
                layout_mopts.addWidget(self.widgets[mopt], row, 0)

            # separators
            if 'imagelist_alternative' in mopt:
                row += 1
                line = QFrame(tab_oopts)
                line.setFrameShape(QFrame.HLine)
                line.setFrameShadow(QFrame.Sunken)
                layout_mopts.addWidget(line, row, 0, 1, 2)

            row += 1

        self.tab_mopts = tab_mopts  # so we can disable the entire tab easily
        tabs.addTab(tab_mopts, 'Image lists')

        # DISPLAY OPTIONS
        tab_dopts = QWidget(tabs)
        layout_dopts = QGridLayout(tab_dopts)

        self.color_buttons = {}
        row = 0
        for dopt, values in config.config['dopts'].items():
            self.widgets[dopt] = QLineEdit(tab_dopts)
            layout_dopts.addWidget(self.widgets[dopt], row, 1)

            label = QLabel(values[2], tab_dopts)
            layout_dopts.addWidget(label, row, 2)

            if values[1] == 'color':
                self.color_buttons[dopt] = QPushButton(tab_dopts)
                self.color_buttons[dopt].clicked.connect(
                    lambda event, opt=dopt: self.pick_color(opt))
                self.widgets[dopt].editingFinished.connect(
                    lambda opt=dopt: self.update_gui_dopts(opt))
                layout_dopts.addWidget(self.color_buttons[dopt], row, 0)

            row += 1

        tabs.addTab(tab_dopts, 'Display options')

        # SAVE/LOAD CONFIG
        tab_config = QWidget(tabs)
        layout_config = QHBoxLayout(tab_config)

        button_save = QPushButton('Save Config', tab_config)
        button_save.clicked.connect(self.save_config)
        button_load = QPushButton('Load Config', tab_config)
        button_load.clicked.connect(self.load_config)
        button_reset = QPushButton('Reset Config', tab_config)
        button_reset.clicked.connect(self.reset_config)

        layout_config.addStretch()
        layout_config.addWidget(button_save)
        layout_config.addWidget(button_load)
        layout_config.addWidget(button_reset)
        layout_config.addStretch()

        tabs.addTab(tab_config, 'Save/Load config')

        # ABOUT
        tab_about = QWidget(tabs)
        layout_about = QGridLayout(tab_about)

        script_display = QLabel(config.script, tab_about)
        script_font = QFont()
        script_font.setPointSize(20)
        script_display.setFont(script_font)
        script_display.setAlignment(Qt.AlignCenter | Qt.AlignVCenter)
        script_display.mousePressEvent = lambda event: self.visit_website(
            config.script_url)
        layout_about.addWidget(script_display, 1, 1, 1, 2)

        author_label = QLabel('author:', tab_about)
        author_label.setAlignment(Qt.AlignRight | Qt.AlignVCenter)
        layout_about.addWidget(author_label, 2, 1)

        author_content = QLabel(config.author, tab_about)
        author_content.mousePressEvent = lambda event: self.visit_website(
            config.author_url)
        layout_about.addWidget(author_content, 2, 2)

        version_label = QLabel('version:', tab_about)
        version_label.setAlignment(Qt.AlignRight | Qt.AlignVCenter)
        layout_about.addWidget(version_label, 3, 1)

        version_content = QLabel(config.version, tab_about)
        layout_about.addWidget(version_content, 3, 2)

        compile_label = QLabel('compile date:', tab_about)
        compile_label.setAlignment(Qt.AlignRight | Qt.AlignVCenter)
        layout_about.addWidget(compile_label, 4, 1)

        compile_content = QLabel(config.compile_date, tab_about)
        layout_about.addWidget(compile_content, 4, 2)

        layout_about.setColumnStretch(0, 10)
        layout_about.setColumnStretch(3, 10)
        layout_about.setRowStretch(0, 5)
        layout_about.setRowStretch(5, 10)
        tabs.addTab(tab_about, 'About')

        # FINISH TABS
        tabs.setCurrentIndex(0)
        tabs.setTabShape(QTabWidget.Rounded)
        central_layout.addWidget(tabs, 1, 0)

        # MASTER BUTTON(S)
        frame_run = QWidget(central_widget)
        layout_run = QHBoxLayout(frame_run)

        self.button_torrent = QPushButton('Create Torrent', frame_run)
        self.button_torrent.clicked.connect(self.create_torrent)

        self.button_run = QPushButton('Run', frame_run)
        self.button_run.clicked.connect(self.run_start)

        layout_run.addStretch()
        layout_run.addWidget(self.button_torrent)
        layout_run.addWidget(self.button_run)
        layout_run.addStretch()
        central_layout.addWidget(frame_run, 2, 0)

        # LOG WINDOW
        self.log_text = QPlainTextEdit()
        log_font = QFont('Monospace', 8)
        log_font.setStyleHint(QFont.TypeWriter)
        self.log_text.setFont(log_font)
        self.log_text.setPlaceholderText('Started GUI.')
        self.log_text.setReadOnly(True)
        # self.log_text.setLineWrapMode(QPlainTextEdit.NoWrap)
        self.log_text.ensureCursorVisible()
        central_layout.addWidget(self.log_text, 3, 0)

        # MAIN GUI OPTIONS
        self.setWindowTitle(config.script)
        self.setWindowIcon(QIcon(resource_path('icon.ico')))
        self.resize(600, 660)
        self.setMinimumSize(500, 600)
        self.setAnimated(False)

        central_layout.setRowStretch(0, 0)
        central_layout.setRowStretch(1, 0)
        central_layout.setRowStretch(2, 0)
        central_layout.setRowStretch(3, 10)
        self.setCentralWidget(central_widget)

        # SET INITIAL STATE
        self.initializing = True  # prevent event emitters from going crazy during GUI initialization
        self.set_gui_values()
        self.initializing = False
        self.update_gui_oopts()
        self.update_gui_mopts()
        self.update_gui_dopts()

        # REDIRECT STDOUT
        sys.stdout = QtGUI.StdoutRedirector(writeSignal=self.log_append)
        sys.stderr = QtGUI.StdoutRedirector(writeSignal=self.log_append)

    def set_gui_values(self):
        for opt, widget in self.widgets.items():
            if isinstance(widget, QLineEdit):
                self.widgets[opt].setText(config.opts[opt])
            elif isinstance(widget, QCheckBox):
                self.widgets[opt].setChecked(config.opts[opt])

    def get_gui_values(self, allow_disabled=False):
        for opt, widget in self.widgets.items():
            if isinstance(widget, QLineEdit):
                if widget.isEnabled() or allow_disabled:
                    config.opts[opt] = widget.text()
                else:
                    config.opts[opt] = ''
            elif isinstance(widget, QCheckBox):
                if widget.isEnabled() or allow_disabled:
                    config.opts[opt] = widget.isChecked()
                else:
                    config.opts[opt] = False

    @pyqtSlot()
    def update_gui_oopts(self):
        if self.initializing:
            return

        if self.widgets['recursive'].isChecked():
            self.widgets['output_individual'].setDisabled(False)
            self.widgets['output_separators'].setDisabled(False)
        else:
            self.widgets['output_individual'].setDisabled(True)
            self.widgets['output_separators'].setDisabled(True)

        if self.widgets['output_individual'].isChecked(
        ) or not self.widgets['recursive'].isChecked():
            self.widgets['output_separators'].setDisabled(True)
        else:
            self.widgets['output_separators'].setDisabled(False)

        if self.widgets['output_as_table'].isChecked():
            self.widgets['output_table_titles'].setDisabled(False)
        else:
            self.widgets['output_table_titles'].setDisabled(True)

        if self.widgets['embed_images'].isChecked():
            self.widgets['output_bbcode_thumb'].setDisabled(False)
        else:
            self.widgets['output_bbcode_thumb'].setDisabled(True)

    @pyqtSlot()
    def update_gui_mopts(self):
        if self.initializing:
            return

        media_dir = self.widgets['media_dir'].text()
        output_dir = self.widgets['output_dir'].text()

        if (self.widgets['recursive'].isChecked()
                and self.widgets['recursive'].isEnabled()
                and self.widgets['output_individual'].isChecked()):

            self.tab_mopts.setDisabled(True)
            self.label_mopts.setVisible(False)
            self.label_mopts_disabled.setVisible(True)
        else:
            self.tab_mopts.setDisabled(False)
            self.label_mopts.setVisible(True)
            self.label_mopts_disabled.setVisible(False)

        if self.widgets['use_imagelist_fullsize'].isChecked():
            self.widgets['use_primary_as_fullsize'].setDisabled(False)
        else:
            self.widgets['use_primary_as_fullsize'].setDisabled(True)

        if (self.widgets['use_imagelist_fullsize'].isChecked()
                and not self.widgets['use_primary_as_fullsize'].isChecked()):

            self.widgets['imagelist_fullsize'].setDisabled(False)
            self.imagelist_buttons['imagelist_fullsize'].setDisabled(False)
        else:
            self.widgets['imagelist_fullsize'].setDisabled(True)
            self.imagelist_buttons['imagelist_fullsize'].setDisabled(True)

        if not output_dir and not media_dir:
            base = ''
        elif not output_dir:
            base = os.path.normpath(
                os.path.join(media_dir, os.path.basename(media_dir)))
        else:
            base = os.path.normpath(
                os.path.join(output_dir, os.path.basename(media_dir)))

        self.widgets['imagelist_primary'].setPlaceholderText(base + '.txt')
        self.widgets['imagelist_alternative'].setPlaceholderText(base +
                                                                 '_alt.txt')
        self.widgets['imagelist_fullsize'].setPlaceholderText(base +
                                                              '_fullsize.txt')

    @pyqtSlot()
    @pyqtSlot(str)
    def update_gui_dopts(self, dopt=None):
        if self.initializing:
            return

        if dopt:
            buttons = {dopt: self.color_buttons[dopt]}
        else:
            buttons = self.color_buttons

        for opt, button in buttons.items():
            value = self.get_color(self.widgets[opt].text())
            if value:
                self.color_buttons[opt].setStyleSheet(
                    'background-color: {}'.format(value['color']))
            else:
                self.color_buttons[opt].setStyleSheet('')

    @pyqtSlot(str)
    def pick_color(self, dopt):
        old_value = self.widgets[dopt].text()
        old_color = QColor()
        the_rest = ''

        if old_value:
            old_value = self.get_color(old_value)
            if old_value:
                old_color.setNamedColor(old_value['color'])
                the_rest = old_value['the_rest'].strip()

        new_color = QColorDialog.getColor(old_color)

        if new_color.isValid():
            self.widgets[dopt].setText(
                (new_color.name().upper() + ' ' + the_rest).strip())
            self.update_gui_dopts(dopt)

    @staticmethod
    def get_color(string):
        match = re.search(r'#(?:[0-9a-fA-F]{1,2}){3}', string)
        if match:
            the_rest = string.replace(match.group(0), '')
            return {'color': match.group(0), 'the_rest': the_rest}
        else:
            return False

    @pyqtSlot(str)
    def visit_website(self, url):
        webbrowser.open(url, new=2)

    @pyqtSlot(str)
    def select_dir(self, opt):
        directory = QFileDialog.getExistingDirectory()

        if directory:
            self.widgets[opt].setText(directory)
            if 'media_dir' in opt or 'output_dir' in opt:
                self.update_gui_mopts()

    @pyqtSlot(str)
    def select_file(self, opt):
        file = QFileDialog.getOpenFileName()[0]

        if file:
            self.widgets[opt].setText(file)

    @pyqtSlot()
    def save_config(self):
        caption = 'Save config file'
        initial_dir = ''
        filters = 'INI Files (*.ini *.conf);;All Files (*.*)'
        selected_filter = 'INI Files (*.ini *.conf)'
        file = QFileDialog.getSaveFileName(self, caption, initial_dir, filters,
                                           selected_filter)[0]

        if file:
            self.get_gui_values()
            config.save_config_file(file)

    @pyqtSlot()
    def load_config(self):
        caption = 'Load config file'
        initial_dir = ''
        filters = 'INI Files (*.ini *.conf);;All Files (*.*)'
        selected_filter = 'INI Files (*.ini *.conf)'
        file = QFileDialog.getOpenFileName(self, caption, initial_dir, filters,
                                           selected_filter)[0]

        if file:
            success = config.load_config_file(file)
            if success:
                self.initializing = True
                self.set_gui_values()
                self.initializing = False
                self.update_gui_oopts()
                self.update_gui_mopts()
                self.update_gui_dopts()

    @pyqtSlot()
    def reset_config(self):
        self.initializing = True
        config.populate_opts()
        self.set_gui_values()
        self.initializing = False
        self.update_gui_oopts()
        self.update_gui_mopts()
        self.update_gui_dopts()

    @pyqtSlot()
    def run_start(self):
        self.get_gui_values()
        self.log_text.clear()
        config.kill_thread = False

        self.parse_thread = QThread()
        self.parse_worker = self.ParseWorker()
        self.parse_worker.moveToThread(self.parse_thread)
        self.parse_worker.finished.connect(self.run_finish)
        self.parse_thread.started.connect(self.parse_worker.run)
        self.parse_thread.finished.connect(self.run_finish)
        self.parse_thread.start()

        self.button_run.setText('Stop')
        self.button_run.clicked.disconnect()
        self.button_run.clicked.connect(self.run_terminate)

    @pyqtSlot()
    def run_finish(self):
        self.parse_thread.quit()

        self.button_run.setText('Run')
        self.button_run.clicked.disconnect()
        self.button_run.clicked.connect(self.run_start)

    @pyqtSlot()
    def run_terminate(self):
        if self.parse_thread.isRunning():
            config.kill_thread = True
            self.parse_thread.terminate()
            print('Thread terminated!')

    @pyqtSlot()
    def create_torrent(self):
        self.get_gui_values()

        # noinspection PyBroadException
        try:
            dott_window = QMainWindow(self)
            ui = dott_gui.DottorrentGUI()
            ui.setupUi(dott_window)
            ui.loadSettings()
            ui.clipboard = QApplication.instance().clipboard
            dott_window.resize(500, 800)

            # manipulate the dottorrent settings to reflect config options
            ui.directoryRadioButton.setChecked(True)
            ui.inputEdit.setText(config.opts['media_dir'])
            if config.opts['recursive'] and config.opts['output_individual']:
                ui.batchModeCheckBox.setChecked(True)
            else:
                ui.batchModeCheckBox.setChecked(False)
            if not ui.excludeEdit.toPlainText():
                ui.excludeEdit.setPlainText('*.txt\n*.ini\n*.torrent')
            ui.initializeTorrent()

            def dott_close_event(event):
                ui.saveSettings()
                event.accept()

            dott_window.closeEvent = dott_close_event
            dott_window.show()
        except:
            (errortype, value, traceback) = sys.exc_info()
            sys.excepthook(errortype, value, traceback)

    @pyqtSlot(str)
    def log_append(self, text):
        self.log_text.moveCursor(QTextCursor.End)
        self.log_text.insertPlainText(text)

    def closeEvent(self, event):
        self.get_gui_values(True)

        if config.opts == config.opts_saved:
            event.accept()
        else:
            title = 'Settings changed'
            question = 'There appear to be unsaved setting changes.\nAre you sure you want to quit?'
            reply = QMessageBox.question(self, title, question,
                                         QMessageBox.Yes, QMessageBox.No)

            if reply == QMessageBox.Yes:
                event.accept()
            else:
                event.ignore()

    class ParseWorker(QObject):
        """
		Note to self: disable "PyQt compatible" in Python debugger settings, or this will break.
		http://stackoverflow.com/a/6789205
		"""
        finished = pyqtSignal()

        @pyqtSlot()
        def run(self):
            # noinspection PyBroadException
            try:
                core.set_paths_and_run()
                self.finished.emit()
            except:
                (errortype, value, traceback) = sys.exc_info()
                sys.excepthook(errortype, value, traceback)
                self.exit()

    # redirect stdout (print) to a widget
    # adapted from http://stackoverflow.com/a/22582213
    class StdoutRedirector(QObject):
        writeSignal = pyqtSignal(str)

        def write(self, text):
            self.writeSignal.emit(str(text))

        def flush(self):
            pass
Example #9
0
class MainWindow(QWidget):
    def __init__(self):
        super(MainWindow, self).__init__()
        self.collecting = False
        self.title = 'Open640'
        self.width = 800
        self.height = 600
        self.setMinimumSize(QSize(320, 240))
        self.settings = SettingsWindow()
        self.batch_reader = BatchWindow()
        self.initMainWindow()

    def initMainWindow(self):
        self.setWindowTitle(self.title)
        layout = QGridLayout()
        layout.setSpacing(10)
        self.setLayout(layout)

        # Widgets
        self.dataArea = QPlainTextEdit()
        self.dataArea.setReadOnly(True)
        self.dataArea.setPlaceholderText(
            "Collected data will appear here for" +
            " review before it is written to" + " disk.")

        self.settingsButton = QPushButton('Serial Settings', self)
        self.settingsButton.setToolTip('Change serial port settings.')

        self.checkSettingsButton = QPushButton('Dump Settings', self)
        self.settingsButton.setToolTip(
            "Print the current settings to the screen.")

        self.writeButton = QPushButton('Write to File', self)
        self.writeButton.setToolTip('Write colected data to the disk.')

        self.clearButton = QPushButton('Clear Output', self)
        self.collectToggle = QPushButton('Start Collection', self)

        self.settingsButton.clicked.connect(
            lambda: self.onSettingsButtonClicked())
        self.checkSettingsButton.clicked.connect(
            lambda: self.onCheckButtonClicked())

        self.repetitionsButton = QPushButton('Batch Collect', self)
        self.repetitionsButton.setToolTip('Collect several samples in a row.')

        self.settings.current_settings.connect(self.showSettings)
        self.batch_reader.next_clicked.connect(
            self.onBatchCollectorStartOrNextClicked())

        self.collectToggle.clicked.connect(lambda: self.onStartButtonClicked())
        self.writeButton.clicked.connect(lambda: self.onWriteButtonClicked())
        self.clearButton.clicked.connect(lambda: self.onClearOutputClicked())
        self.repetitionsButton.clicked.connect(
            lambda: self.onBatchCollectClicked())

        layout.addWidget(self.dataArea, 0, 0, 1, 0)
        layout.addWidget(self.settingsButton, 1, 0)
        layout.addWidget(self.checkSettingsButton, 1, 1)
        layout.addWidget(self.clearButton, 1, 2)
        layout.addWidget(self.repetitionsButton, 1, 3)
        layout.addWidget(self.collectToggle, 1, 4)
        layout.addWidget(self.writeButton, 1, 5)

        self.show()

    def onBatchCollectClicked(self):
        self.batch_reader.show()

    def onBatchCollectorStartOrNextClicked(self):
        # self.onStartButtonClicked()
        pass

    def onStartButtonClicked(self):
        if not self.collecting:
            self.collectToggle.setText('Stop Collection')
            self.collecting = True
            self.dataArea.setPlainText(
                "Waiting for data from the DU-640...\n" +
                "If stopped, the DU-640's send queue will be emptied before" +
                "reading is terminated. Data collected will be trashed.")
            self.warningCleared = False
            self.reader = Reader()
            self.reader.experimental_data.connect(self.onExperimentFinished)
            self.reader.data_live.connect(self.onExperimentUpdate)
            self.reader.success_state.connect(self.onExperimentSuccess)
            self.reader.fail_state.connect(self.onExperimentFailed)
            self.reader.start()
        else:
            # Kill the currently running thread
            alert = QMessageBox()
            alert.setText(
                "Won't start another read thread until current one finishes.")
            alert.exec_()

    def onExperimentFailed(self):
        self.collecting = False
        self.collectToggle.setText('Start Collection')
        alert = QMessageBox()
        alert.setText("Could not open serial port." +
                      "Ensure /dev/ttyAMA0 exists and is available, then try" +
                      " again.")
        alert.exec_()

    def onExperimentUpdate(self, data):
        if not self.warningCleared:
            self.dataArea.setPlainText("")
            self.warningCleared = True
        cursor = self.dataArea.textCursor()
        cursor.movePosition(QTextCursor.End)
        cursor.insertText(data)
        self.dataArea.ensureCursorVisible()

    def onExperimentFinished(self, data):
        self.dataArea.setPlainText(data)
        self.collecting = False
        self.collectToggle.setText('Start Collection')

    def onExperimentSuccess(self):
        self.collecting = False
        self.collectToggle.setText('Start Collection')

    def onClearOutputClicked(self):
        self.dataArea.setPlainText("")

    def onWriteButtonClicked(self):
        options = QFileDialog.Options()
        options |= QFileDialog.DontUseNativeDialog
        filename, _ = QFileDialog.getSaveFileName(
            self,
            "QFileDialog.getSaveFileName()",
            "",
            "Text Files (*.txt)",
            options=options)
        if filename:
            print("Saving to " + filename + ".txt...")
            f = open(filename + '.txt', 'w')
            f.write(self.dataArea.toPlainText() + '\n')
            f.close()

    def showSettings(self, data):
        self.dataArea.setPlainText(data)

    def onSettingsButtonClicked(self):
        self.settings.show()

    def onCheckButtonClicked(self):
        self.settings.emitCurrentSettings()
Example #10
0
class QtRunWindow(QWidget):
    resized = pyqtSignal()

    def __init__(self, master, info, firmware):
        super(QtRunWindow, self).__init__()
        self.master = master
        self.master.globalStop.connect(self.urgentStop)
        self.firmware = firmware
        self.info = info
        self.connection = self.master.connection
        self.firmwareName = self.firmware.getBoardName()
        self.ModuleType = self.firmware.getModuleByIndex(0).getModuleType()
        self.RunNumber = "-1"

        self.GroupBoxSeg = [1, 10, 1]
        self.HorizontalSeg = [3, 5]
        self.VerticalSegCol0 = [1, 3]
        self.VerticalSegCol1 = [2, 2]
        self.DisplayH = self.height() * 3. / 7
        self.DisplayW = self.width() * 3. / 7

        self.processingFlag = False
        self.ProgressBarList = []
        self.input_dir = ''
        self.output_dir = ''
        self.config_file = ''  #os.environ.get('GUI_dir')+ConfigFiles.get(self.calibration, "None")
        self.rd53_file = {}
        self.grade = -1
        self.currentTest = ""
        self.outputFile = ""
        self.errorFile = ""

        self.backSignal = False
        self.haltSignal = False
        self.finishSingal = False
        self.proceedSignal = False

        self.runNext = threading.Event()
        self.testIndexTracker = -1
        self.listWidgetIndex = 0
        self.outputDirQueue = []
        #Fixme: QTimer to be added to update the page automatically
        self.grades = []
        self.modulestatus = []
        self.autoSave = False

        self.mainLayout = QGridLayout()
        self.setLayout(self.mainLayout)

        self.setLoginUI()
        self.initializeRD53Dict()
        self.createHeadLine()
        self.createMain()
        self.createApp()
        self.occupied()

        self.resized.connect(self.rescaleImage)

        self.run_process = QProcess(self)
        self.run_process.readyReadStandardOutput.connect(
            self.on_readyReadStandardOutput)
        self.run_process.finished.connect(self.on_finish)
        self.readingOutput = False
        self.ProgressingMode = "Configure"
        self.ProgressValue = 0

        self.info_process = QProcess(self)
        self.info_process.readyReadStandardOutput.connect(
            self.on_readyReadStandardOutput_info)

    def setLoginUI(self):
        X = self.master.dimension.width() / 10
        Y = self.master.dimension.height() / 10
        Width = self.master.dimension.width() * 8. / 10
        Height = self.master.dimension.height() * 8. / 10
        self.setGeometry(X, Y, Width, Height)
        self.setWindowTitle('Run Control Page')
        self.DisplayH = self.height() * 3. / 7
        self.DisplayW = self.width() * 3. / 7
        self.show()

    def initializeRD53Dict(self):
        self.rd53_file = {}
        for module in self.firmware.getAllModules().values():
            #moduleId = module.getModuleID()
            moduleId = module.getOpticalGroupID()
            moduleType = module.getModuleType()
            for i in range(BoxSize[moduleType]):
                self.rd53_file["{0}_{1}".format(moduleId, i)] = None

    def createHeadLine(self):
        self.HeadBox = QGroupBox()

        self.HeadLayout = QHBoxLayout()

        HeadLabel = QLabel(
            '<font size="4"> Module: {0}  Test: {1} </font>'.format(
                self.info[0], self.info[1]))
        HeadLabel.setMaximumHeight(30)

        statusString, colorString = checkDBConnection(self.connection)
        StatusLabel = QLabel()
        StatusLabel.setText(statusString)
        StatusLabel.setStyleSheet(colorString)

        self.HeadLayout.addWidget(HeadLabel)
        self.HeadLayout.addStretch(1)
        self.HeadLayout.addWidget(StatusLabel)

        self.HeadBox.setLayout(self.HeadLayout)

        self.mainLayout.addWidget(self.HeadBox, 0, 0, self.GroupBoxSeg[0], 1)

    def destroyHeadLine(self):
        self.HeadBox.deleteLater()
        self.mainLayout.removeWidget(self.HeadBox)

    def createMain(self):
        self.testIndexTracker = 0
        self.MainBodyBox = QGroupBox()

        mainbodylayout = QHBoxLayout()

        kMinimumWidth = 120
        kMaximumWidth = 150
        kMinimumHeight = 30
        kMaximumHeight = 80

        # Splitters
        MainSplitter = QSplitter(Qt.Horizontal)
        LeftColSplitter = QSplitter(Qt.Vertical)
        RightColSplitter = QSplitter(Qt.Vertical)

        #Group Box for controller
        ControllerBox = QGroupBox()
        ControllerSP = ControllerBox.sizePolicy()
        ControllerSP.setVerticalStretch(self.VerticalSegCol0[0])
        ControllerBox.setSizePolicy(ControllerSP)

        self.ControlLayout = QGridLayout()

        self.CustomizedButton = QPushButton("&Customize...")
        self.CustomizedButton.clicked.connect(self.customizeTest)
        self.ResetButton = QPushButton("&Reset")
        self.ResetButton.clicked.connect(self.resetConfigTest)
        self.RunButton = QPushButton("&Run")
        self.RunButton.setDefault(True)
        self.RunButton.clicked.connect(self.initialTest)
        self.RunButton.clicked.connect(self.runTest)
        #self.ContinueButton = QPushButton("&Continue")
        #self.ContinueButton.clicked.connect(self.sendProceedSignal)
        self.AbortButton = QPushButton("&Abort")
        self.AbortButton.clicked.connect(self.abortTest)
        #self.SaveButton = QPushButton("&Save")
        #self.SaveButton.clicked.connect(self.saveTest)
        self.saveCheckBox = QCheckBox("&auto-save to DB")
        self.saveCheckBox.setMaximumHeight(30)
        self.saveCheckBox.setChecked(self.autoSave)
        if not isActive(self.connection):
            self.saveCheckBox.setChecked(False)
            self.saveCheckBox.setDisabled(True)
        self.saveCheckBox.clicked.connect(self.setAutoSave)

        self.ControlLayout.addWidget(self.CustomizedButton, 0, 0, 1, 2)
        self.ControlLayout.addWidget(self.ResetButton, 0, 2, 1, 1)
        self.ControlLayout.addWidget(self.RunButton, 1, 0, 1, 1)
        self.ControlLayout.addWidget(self.AbortButton, 1, 1, 1, 1)
        self.ControlLayout.addWidget(self.saveCheckBox, 1, 2, 1, 1)

        ControllerBox.setLayout(self.ControlLayout)

        #Group Box for ternimal display
        TerminalBox = QGroupBox("&Terminal")
        TerminalSP = TerminalBox.sizePolicy()
        TerminalSP.setVerticalStretch(self.VerticalSegCol0[1])
        TerminalBox.setSizePolicy(TerminalSP)
        TerminalBox.setMinimumWidth(400)

        ConsoleLayout = QGridLayout()

        self.ConsoleView = QPlainTextEdit()
        self.ConsoleView.setStyleSheet(
            "QTextEdit { background-color: rgb(10, 10, 10); color : white; }")
        #self.ConsoleView.setCenterOnScroll(True)
        self.ConsoleView.ensureCursorVisible()

        ConsoleLayout.addWidget(self.ConsoleView)
        TerminalBox.setLayout(ConsoleLayout)

        #Group Box for output display
        OutputBox = QGroupBox("&Result")
        OutputBoxSP = OutputBox.sizePolicy()
        OutputBoxSP.setVerticalStretch(self.VerticalSegCol1[0])
        OutputBox.setSizePolicy(OutputBoxSP)

        OutputLayout = QGridLayout()
        self.ResultWidget = ResultTreeWidget(self.info, self.DisplayW,
                                             self.DisplayH, self.master)
        #self.DisplayTitle = QLabel('<font size="6"> Result: </font>')
        #self.DisplayLabel = QLabel()
        #self.DisplayLabel.setScaledContents(True)
        #self.DisplayView = QPixmap('test_plots/test_best1.png').scaled(QSize(self.DisplayW,self.DisplayH), Qt.KeepAspectRatio, Qt.SmoothTransformation)
        #self.DisplayLabel.setPixmap(self.DisplayView)
        #self.ReferTitle = QLabel('<font size="6"> Reference: </font>')
        #self.ReferLabel = QLabel()
        #self.ReferLabel.setScaledContents(True)
        #self.ReferView = QPixmap('test_plots/test_best1.png').scaled(QSize(self.DisplayW,self.DisplayH), Qt.KeepAspectRatio, Qt.SmoothTransformation)
        #self.ReferLabel.setPixmap(self.ReferView)

        #self.ListWidget = QListWidget()
        #self.ListWidget.setMinimumWidth(150)
        #self.ListWidget.clicked.connect(self.clickedOutputItem)
        ##To be removed (END)

        #OutputLayout.addWidget(self.DisplayTitle,0,0,1,2)
        #OutputLayout.addWidget(self.DisplayLabel,1,0,1,2)
        #OutputLayout.addWidget(self.ReferTitle,0,2,1,2)
        #OutputLayout.addWidget(self.ReferLabel,1,2,1,2)
        #OutputLayout.addWidget(self.ListWidget,0,4,2,1)

        OutputLayout.addWidget(self.ResultWidget, 0, 0, 1, 1)
        OutputBox.setLayout(OutputLayout)

        #Group Box for history
        self.HistoryBox = QGroupBox("&History")
        HistoryBoxSP = self.HistoryBox.sizePolicy()
        HistoryBoxSP.setVerticalStretch(self.VerticalSegCol1[1])
        self.HistoryBox.setSizePolicy(HistoryBoxSP)

        self.HistoryLayout = QGridLayout()

        # Display the table for module history
        #self.dataList = getLocalRemoteTests(self.connection, self.info[0])
        #self.proxy = QtTableWidget(self.dataList)
        #self.lineEdit       = QLineEdit()
        #self.lineEdit.textChanged.connect(self.proxy.on_lineEdit_textChanged)
        #self.view           = QTableView()
        #self.view.setSortingEnabled(True)
        #self.comboBox       = QComboBox()
        #self.comboBox.addItems(["{0}".format(x) for x in self.dataList[0]])
        #self.comboBox.currentIndexChanged.connect(self.proxy.on_comboBox_currentIndexChanged)
        #self.label          = QLabel()
        #self.label.setText("Regex Filter")

        #self.view.setModel(self.proxy)
        #self.view.setEditTriggers(QAbstractItemView.NoEditTriggers)

        self.HistoryLayout = QGridLayout()
        #self.HistoryLayout.addWidget(self.lineEdit, 0, 1, 1, 1)
        #self.HistoryLayout.addWidget(self.view, 1, 0, 1, 3)
        #self.HistoryLayout.addWidget(self.comboBox, 0, 2, 1, 1)
        #self.HistoryLayout.addWidget(self.label, 0, 0, 1, 1)

        #self.StatusCanvas = RunStatusCanvas(parent=self,width=5, height=4, dpi=100)
        self.StatusTable = QTableWidget()
        self.header = ["TestName"]
        for key in self.rd53_file.keys():
            ChipName = key.split("_")
            self.header.append("Module{}_Chip{}".format(
                ChipName[0], ChipName[1]))
        self.StatusTable.setColumnCount(len(self.header))
        self.StatusTable.setHorizontalHeaderLabels(self.header)
        self.StatusTable.setEditTriggers(QAbstractItemView.NoEditTriggers)
        self.HistoryLayout.addWidget(self.StatusTable)
        self.HistoryBox.setLayout(self.HistoryLayout)

        LeftColSplitter.addWidget(ControllerBox)
        LeftColSplitter.addWidget(TerminalBox)
        RightColSplitter.addWidget(OutputBox)
        RightColSplitter.addWidget(self.HistoryBox)

        LeftColSplitterSP = LeftColSplitter.sizePolicy()
        LeftColSplitterSP.setHorizontalStretch(self.HorizontalSeg[0])
        LeftColSplitter.setSizePolicy(LeftColSplitterSP)

        RightColSplitterSP = RightColSplitter.sizePolicy()
        RightColSplitterSP.setHorizontalStretch(self.HorizontalSeg[1])
        RightColSplitter.setSizePolicy(RightColSplitterSP)

        MainSplitter.addWidget(LeftColSplitter)
        MainSplitter.addWidget(RightColSplitter)

        mainbodylayout.addWidget(MainSplitter)
        #mainbodylayout.addWidget(ControllerBox, sum(self.VerticalSegCol0[:0]), sum(self.HorizontalSeg[:0]), self.VerticalSegCol0[0], self.HorizontalSeg[0])
        #mainbodylayout.addWidget(TerminalBox, sum(self.VerticalSegCol0[:1]), sum(self.HorizontalSeg[:0]), self.VerticalSegCol0[1], self.HorizontalSeg[0])
        #mainbodylayout.addWidget(OutputBox, sum(self.VerticalSegCol1[:0]), sum(self.HorizontalSeg[:1]), self.VerticalSegCol1[0], self.HorizontalSeg[1])
        #mainbodylayout.addWidget(HistoryBox, sum(self.VerticalSegCol1[:1]), sum(self.HorizontalSeg[:1]), self.VerticalSegCol1[1], self.HorizontalSeg[1])

        self.MainBodyBox.setLayout(mainbodylayout)
        self.mainLayout.addWidget(self.MainBodyBox, sum(self.GroupBoxSeg[0:1]),
                                  0, self.GroupBoxSeg[1], 1)

    def destroyMain(self):
        self.MainBodyBox.deleteLater()
        self.mainLayout.removeWidget(self.MainBodyBox)

    def createApp(self):
        self.AppOption = QGroupBox()
        self.StartLayout = QHBoxLayout()

        self.ConnectButton = QPushButton("&Connect to DB")
        self.ConnectButton.clicked.connect(self.connectDB)

        self.BackButton = QPushButton("&Back")
        self.BackButton.clicked.connect(self.sendBackSignal)
        self.BackButton.clicked.connect(self.closeWindow)
        self.BackButton.clicked.connect(self.creatStartWindow)

        self.FinishButton = QPushButton("&Finish")
        self.FinishButton.setDefault(True)
        self.FinishButton.clicked.connect(self.closeWindow)

        self.StartLayout.addStretch(1)
        self.StartLayout.addWidget(self.ConnectButton)
        self.StartLayout.addWidget(self.BackButton)
        self.StartLayout.addWidget(self.FinishButton)
        self.AppOption.setLayout(self.StartLayout)

        self.mainLayout.addWidget(self.AppOption, sum(self.GroupBoxSeg[0:2]),
                                  0, self.GroupBoxSeg[2], 1)

    def destroyApp(self):
        self.AppOption.deleteLater()
        self.mainLayout.removeWidget(self.AppOption)

    def closeWindow(self):
        self.close()

    def creatStartWindow(self):
        if self.backSignal == True:
            self.master.openNewTest()

    def occupied(self):
        self.master.ProcessingTest = True

    def release(self):
        self.run_process.kill()
        self.master.ProcessingTest = False
        self.master.NewTestButton.setDisabled(False)
        self.master.LogoutButton.setDisabled(False)
        self.master.ExitButton.setDisabled(False)

    def refreshHistory(self):
        #self.dataList = getLocalRemoteTests(self.connection, self.info[0])
        #self.proxy = QtTableWidget(self.dataList)
        #self.view.setModel(self.proxy)
        #self.view.setEditTriggers(QAbstractItemView.NoEditTriggers)
        #self.view.update()
        self.HistoryLayout.removeWidget(self.StatusTable)
        self.StatusTable.setRowCount(0)
        for index, test in enumerate(self.modulestatus):
            row = self.StatusTable.rowCount()
            self.StatusTable.setRowCount(row + 1)
            if isCompositeTest(self.info[1]):
                self.StatusTable.setItem(
                    row, 0,
                    QTableWidgetItem(CompositeList[self.info[1]][index]))
            else:
                self.StatusTable.setItem(row, 0,
                                         QTableWidgetItem(self.info[1]))
            for moduleKey in test.keys():
                for chipKey in test[moduleKey].keys():
                    ChipID = "Module{}_Chip{}".format(moduleKey, chipKey)
                    status = "Pass" if test[moduleKey][
                        chipKey] == True else "Failed"
                    if ChipID in self.header:
                        columnId = self.header.index(ChipID)
                        self.StatusTable.setItem(row, columnId,
                                                 QTableWidgetItem(status))
                        if status == "Pass":
                            self.StatusTable.item(row, columnId).setBackground(
                                QColor(Qt.green))
                        elif status == "Failed":
                            self.StatusTable.item(row, columnId).setBackground(
                                QColor(Qt.red))

        self.HistoryLayout.addWidget(self.StatusTable)

    def sendBackSignal(self):
        self.backSignal = True

    def sendProceedSignal(self):
        self.proceedSignal = True
        #self.runNext.set()

    def connectDB(self):
        if isActive(self.master.connection):
            self.connection = self.master.connection
            self.refresh()
            self.saveCheckBox.setDisabled(False)
            return

        LoginDialog = QtLoginDialog(self.master)
        response = LoginDialog.exec_()
        if response == QDialog.Accepted:
            self.connectDB()
        else:
            return

    def configTest(self):
        try:
            RunNumberFileName = os.environ.get(
                'Ph2_ACF_AREA') + "/test/RunNumber.txt"
            if os.path.isfile(RunNumberFileName):
                runNumberFile = open(RunNumberFileName, "r")
                runNumberText = runNumberFile.readlines()
                self.RunNumber = runNumberText[0].split('\n')[0]
                logger.info("RunNumber: {}".format(self.RunNumber))
        except:
            logger.warning("Failed to retrive RunNumber")

        if self.currentTest == "" and isCompositeTest(self.info[1]):
            testName = CompositeList[self.info[1]][0]
        elif self.currentTest == None:
            testName = self.info[1]
        else:
            testName = self.currentTest

        ModuleIDs = []
        for module in self.firmware.getAllModules().values():
            #ModuleIDs.append(str(module.getModuleID()))
            ModuleIDs.append(str(module.getOpticalGroupID()))

        self.output_dir, self.input_dir = ConfigureTest(
            testName, "_Module".join(ModuleIDs), self.output_dir,
            self.input_dir, self.connection)

        for key in self.rd53_file.keys():
            if self.rd53_file[key] == None:
                self.rd53_file[key] = os.environ.get(
                    'Ph2_ACF_AREA') + "/settings/RD53Files/CMSIT_RD53.txt"
        if self.input_dir == "":
            SetupRD53ConfigfromFile(self.rd53_file, self.output_dir)
        else:
            SetupRD53Config(self.input_dir, self.output_dir, self.rd53_file)

        if self.input_dir == "":
            if self.config_file == "":
                tmpDir = os.environ.get('GUI_dir') + "/Gui/.tmp"
                if not os.path.isdir(tmpDir) and os.environ.get('GUI_dir'):
                    try:
                        os.mkdir(tmpDir)
                        logger.info("Creating " + tmpDir)
                    except:
                        logger.warning("Failed to create " + tmpDir)
                config_file = GenerateXMLConfig(self.firmware,
                                                self.currentTest, tmpDir)
                #config_file = os.environ.get('GUI_dir')+ConfigFiles.get(testName, "None")
                if config_file:
                    SetupXMLConfigfromFile(config_file, self.output_dir,
                                           self.firmwareName, self.rd53_file)
                else:
                    logger.warning("No Valid XML configuration file")
                #QMessageBox.information(None,"Noitce", "Using default XML configuration",QMessageBox.Ok)
            else:
                SetupXMLConfigfromFile(self.config_file, self.output_dir,
                                       self.firmwareName, self.rd53_file)
        else:
            if self.config_file != "":
                SetupXMLConfigfromFile(self.config_file, self.output_dir,
                                       self.firmwareName, self.rd53_file)
            else:
                tmpDir = os.environ.get('GUI_dir') + "/Gui/.tmp"
                if not os.path.isdir(tmpDir) and os.environ.get('GUI_dir'):
                    try:
                        os.mkdir(tmpDir)
                        logger.info("Creating " + tmpDir)
                    except:
                        logger.warning("Failed to create " + tmpDir)
                config_file = GenerateXMLConfig(self.firmware,
                                                self.currentTest, tmpDir)
                #config_file = os.environ.get('GUI_dir')+ConfigFiles.get(testName, "None")
                if config_file:
                    SetupXMLConfigfromFile(config_file, self.output_dir,
                                           self.firmwareName, self.rd53_file)
                else:
                    logger.warning("No Valid XML configuration file")

                # To be remove:
                #config_file = os.environ.get('GUI_dir')+ConfigFiles.get(testName, "None")
                #SetupXMLConfigfromFile(config_file,self.output_dir,self.firmwareName,self.rd53_file)
                #SetupXMLConfig(self.input_dir,self.output_dir)

        self.initializeRD53Dict()
        self.config_file = ""
        return

    def saveConfigs(self):
        for key in self.rd53_file.keys():
            try:
                os.system(
                    "cp {0}/test/CMSIT_RD53_{1}.txt {2}/CMSIT_RD53_{1}_OUT.txt"
                    .format(os.environ.get("Ph2_ACF_AREA"), key,
                            self.output_dir))
            except:
                print(
                    "Failed to copy {0}/test/CMSIT_RD53_{1}.txt {2}/CMSIT_RD53_{1}_OUT.txt"
                    .format(os.environ.get("Ph2_ACF_AREA"), key,
                            self.output_dir))

    def customizeTest(self):
        print("Customize configuration")
        self.CustomizedButton.setDisabled(True)
        self.ResetButton.setDisabled(True)
        self.RunButton.setDisabled(True)
        self.CustomizedWindow = QtCustomizeWindow(self, self.rd53_file)
        self.CustomizedButton.setDisabled(False)
        self.ResetButton.setDisabled(False)
        self.RunButton.setDisabled(False)

    def resetConfigTest(self):
        self.input_dir = ""
        self.output_dir = ""
        self.config_file = ""
        self.initializeRD53Dict()

    def initialTest(self):
        if "Re" in self.RunButton.text():
            self.grades = []
            for index in range(len(CompositeList[self.info[1]])):
                self.ResultWidget.ProgressBar[index].setValue(0)

    def runTest(self):
        self.ResetButton.setDisabled(True)
        #self.ControlLayout.removeWidget(self.RunButton)
        #self.RunButton.deleteLater()
        #self.ControlLayout.addWidget(self.ContinueButton,1,0,1,1)
        testName = self.info[1]

        self.input_dir = self.output_dir
        self.output_dir = ""

        #self.StatusCanvas.renew()
        #self.StatusCanvas.update()
        #self.HistoryLayout.removeWidget(self.StatusCanvas)
        #self.HistoryLayout.addWidget(self.StatusCanvas)

        if isCompositeTest(testName):
            self.runCompositeTest(testName)
        elif isSingleTest(testName):
            self.runSingleTest(testName)
        else:
            QMessageBox.information(None, "Warning", "Not a valid test",
                                    QMessageBox.Ok)
            return

    def runCompositeTest(self, testName):
        if self.haltSignal:
            return
        if self.testIndexTracker == len(CompositeList[self.info[1]]):
            self.testIndexTracker = 0
            return
        testName = CompositeList[self.info[1]][self.testIndexTracker]
        self.runSingleTest(testName)

    def runSingleTest(self, testName):
        self.currentTest = testName
        self.configTest()
        self.outputFile = self.output_dir + "/output.txt"
        self.errorFile = self.output_dir + "/error.txt"
        #self.ContinueButton.setDisabled(True)
        #self.run_process.setProgram()
        self.info_process.setProcessChannelMode(QtCore.QProcess.MergedChannels)
        self.info_process.setWorkingDirectory(
            os.environ.get("Ph2_ACF_AREA") + "/test/")
        self.info_process.start("echo", [
            "Running COMMAND: CMSITminiDAQ  -f  CMSIT.xml  -c  {}".format(
                Test[self.currentTest])
        ])
        self.info_process.waitForFinished()

        self.run_process.setProcessChannelMode(QtCore.QProcess.MergedChannels)
        self.run_process.setWorkingDirectory(
            os.environ.get("Ph2_ACF_AREA") + "/test/")
        #self.run_process.setStandardOutputFile(self.outputFile)
        #self.run_process.setStandardErrorFile(self.errorFile)

        #self.run_process.start("python", ["signal_generator.py"])
        #self.run_process.start("tail" , ["-n","6000", "/Users/czkaiweb/Research/Ph2_ACF_GUI/Gui/forKai.txt"])
        #self.run_process.start("./SignalGenerator")

        if Test[self.currentTest] in [
                "pixelalive", "noise", "latency", "injdelay", "clockdelay",
                "threqu", "thrmin", "scurve"
        ]:
            self.run_process.start(
                "CMSITminiDAQ",
                ["-f", "CMSIT.xml", "-c", "{}".format(Test[self.currentTest])])
        else:
            self.info_process.start("echo", [
                "test {} not runnable, quitting...".format(
                    Test[self.currentTest])
            ])

        #self.run_process.start("ping", ["-c","5","www.google.com"])
        #self.run_process.waitForFinished()
        self.displayResult()

        #Question = QMessageBox()
        #Question.setIcon(QMessageBox.Question)
        #Question.setWindowTitle('SingleTest Finished')
        #Question.setText('Save current result and proceed?')
        #Question.setStandardButtons(QMessageBox.No| QMessageBox.Save | QMessageBox.Yes)
        #Question.setDefaultButton(QMessageBox.Yes)
        #customizedButton = Question.button(QMessageBox.Save)
        #customizedButton.setText('Save Only')
        #reply  = Question.exec_()

        #if reply == QMessageBox.Yes or reply == QMessageBox.Save:
        #	self.saveTest()
        #if reply == QMessageBox.No or reply == QMessageBox.Save:
        #	self.haltSignal = True
        #self.refreshHistory()
        #self.finishSingal = False

    def abortTest(self):
        reply = QMessageBox.question(None, "Abort", "Are you sure to abort?",
                                     QMessageBox.No | QMessageBox.Yes,
                                     QMessageBox.No)

        if reply == QMessageBox.Yes:
            self.run_process.kill()
            self.haltSignal = True
            self.sendProceedSignal()
        else:
            return
        self.RunButton.setText("Re-run")
        self.RunButton.setDisabled(False)

    def urgentStop(self):
        self.run_process.kill()
        self.haltSignal = True
        self.sendProceedSignal()

        self.RunButton.setText("Re-run")
        self.RunButton.setDisabled(True)

    def validateTest(self):
        # Fixme: the grading for test results
        grade, passmodule = ResultGrader(self.output_dir, self.currentTest,
                                         self.RunNumber)
        self.grades.append(grade)
        self.modulestatus.append(passmodule)

        self.ResultWidget.StatusLabel[self.testIndexTracker -
                                      1].setText("Pass")
        self.ResultWidget.StatusLabel[self.testIndexTracker -
                                      1].setStyleSheet("color: green")
        for module in passmodule.values():
            if False in module.values():
                self.ResultWidget.StatusLabel[self.testIndexTracker -
                                              1].setText("Failed")
                self.ResultWidget.StatusLabel[self.testIndexTracker -
                                              1].setStyleSheet("color: red")

        time.sleep(0.5)
        #self.StatusCanvas.renew()
        #self.StatusCanvas.update()
        #self.HistoryLayout.removeWidget(self.StatusCanvas)
        #self.HistoryLayout.addWidget(self.StatusCanvas)

    def saveTest(self):
        #if self.parent.current_test_grade < 0:
        if self.run_process.state() == QProcess.Running:
            QMessageBox.critical(self, "Error", "Process not finished",
                                 QMessageBox.Ok)
            return

        try:
            os.system("cp {0}/test/Results/Run{1}*.root {2}/".format(
                os.environ.get("Ph2_ACF_AREA"), self.RunNumber,
                self.output_dir))
        except:
            print("Failed to copy file to output directory")

    def saveTestToDB(self):
        if isActive(self.connection) and self.autoSave:
            try:
                localDir = self.output_dir
                getFiles = subprocess.run(
                    'find {0} -mindepth 1  -maxdepth 1 -type f -name "*.root"  '
                    .format(localDir),
                    shell=True,
                    stdout=subprocess.PIPE)
                fileList = getFiles.stdout.decode('utf-8').rstrip('\n').split(
                    '\n')
                moduleList = [
                    module for module in localDir.split('_')
                    if "Module" in module
                ]

                if fileList == [""]:
                    logger.warning(
                        "No ROOT file found in the local folder, skipping...")
                    return

                ## Submit all files
                for submitFile in fileList:
                    data_id = hashlib.md5(
                        '{}'.format(submitFile).encode()).hexdigest()
                    if not self.checkRemoteFile(data_id):
                        self.uploadFile(submitFile, data_id)

                    ## Submit records for all modules
                    for module in moduleList:
                        getConfigInFiles = subprocess.run(
                            'find {0} -mindepth 1  -maxdepth 1 -type f -name "CMSIT_RD53_{1}_*_IN.txt"  '
                            .format(localDir, module_id),
                            shell=True,
                            stdout=subprocess.PIPE)
                        configInFileList = getConfigInFiles.stdout.decode(
                            'utf-8').rstrip('\n').split('\n')
                        getConfigOutFiles = subprocess.run(
                            'find {0} -mindepth 1  -maxdepth 1 -type f -name "CMSIT_RD53_{1}_*_OUT.txt"  '
                            .format(localDir, module_id),
                            shell=True,
                            stdout=subprocess.PIPE)
                        configOutFileList = getConfigOutFiles.stdout.decode(
                            'utf-8').rstrip('\n').split('\n')

                        configcolumns = []
                        configdata = []
                        for configInFile in configInFileList:
                            if configInFile != [""]:
                                configcolumns.append("Chip{}InConfig".format(
                                    configInFile.split('_')[-2]))
                                configInBuffer = open(configInFile, 'rb')
                                configInBin = configInBuffer.read()
                                configdata.append(configInBin)
                        for configOutFile in configOutFileList:
                            if configOutFile != [""]:
                                configcolumns.append("Chip{}OutConfig".format(
                                    configOutFile.split('_')[-2]))
                                configOutBuffer = open(configOutFile, 'rb')
                                configOutBin = configOutBuffer.read()
                                configdata.append(configOutBin)

                        Columns = [
                            "part_id", "date", "testname", "description",
                            "grade", "data_id", "username"
                        ]
                        SubmitArgs = []
                        Value = []

                        record = formatter(localDir, Columns, part_id=module)
                        for column in ['part_id']:
                            if column == "part_id":
                                SubmitArgs.append(column)
                                Value.append(module)
                            if column == "date":
                                SubmitArgs.append(column)
                                Value.append(record[Columns.index(column)])
                            if column == "testname":
                                SubmitArgs.append(column)
                                Value.append(record[Columns.index(column)])
                            if column == "description":
                                SubmitArgs.append(column)
                                Value.append("No Comment")
                            if column == "grade":
                                SubmitArgs.append(column)
                                Value.append(-1)
                            if column == "data_id":
                                SubmitArgs.append(column)
                                Value.append(data_id)
                            if column == "username":
                                SubmitArgs.append(column)
                                Value.append(self.master.TryUsername)

                        SubmitArgs = SubmitArgs + configcolumns
                        Value = Value + configdata

                        try:
                            insertGenericTable(self.connection, "tests",
                                               SubmitArgs, Value)
                        except:
                            print("Failed to insert")
            except Exception as err:
                QMessageBox.information(self, "Error", "Unable to save to DB",
                                        QMessageBox.Ok)
                print("Error: {}".format(repr(err)))
                return

    def checkRemoteFile(self, file_id):
        remoteRecords = retrieveWithConstraint(self.connection,
                                               "result_files",
                                               file_id=file_id,
                                               columns=["file_id"])
        return remoteRecords != []

    def uploadFile(self, fileName, file_id):
        fileBuffer = open(fileName, 'rb')
        data = fileBuffer.read()
        insertGenericTable(self.connection, "result_files",
                           ["file_id", "file_content"], [file_id, data])

    #######################################################################
    ##  For result display
    #######################################################################
    def displayResult(self):
        #Fixme: remake the list
        #updatePixmap = QPixmap("test_plots/pixelalive_ex.png").scaled(QSize(self.DisplayW,self.DisplayH), Qt.KeepAspectRatio, Qt.SmoothTransformation)
        #self.DisplayLabel.setPixmap(updatePixmap)
        pass

    def clickedOutputItem(self, qmodelindex):
        #Fixme: Extract the info from ROOT file
        item = self.ListWidget.currentItem()
        referName = item.text().split("_")[0]
        if referName in [
                "GainScan", "Latency", "NoiseScan", "PixelAlive", "SCurveScan",
                "ThresholdEqualization"
        ]:
            self.ReferView = QPixmap(
                os.environ.get('GUI_dir') +
                '/Gui/test_plots/{0}.png'.format(referName)).scaled(
                    QSize(self.DisplayW, self.DisplayH), Qt.KeepAspectRatio,
                    Qt.SmoothTransformation)
            self.ReferLabel.setPixmap(self.ReferView)

    #######################################################################
    ##  For real-time terminal display
    #######################################################################

    @QtCore.pyqtSlot()
    def on_readyReadStandardOutput(self):
        if self.readingOutput == True:
            print("Thread competition detected")
            return
        self.readingOutput = True
        if os.path.exists(self.outputFile):
            outputfile = open(self.outputFile, "a")
        else:
            outputfile = open(self.outputFile, "w")

        alltext = self.run_process.readAllStandardOutput().data().decode()
        outputfile.write(alltext)
        outputfile.close()
        textline = alltext.split('\n')
        #fileLines = open(self.outputFile,"r")
        #textline = fileLines.readlines()

        for textStr in textline:
            if "@@@ Initializing the Hardware @@@" in textStr:
                self.ProgressingMode = "Configure"
            if "@@@ Performing" in textStr:
                self.ProgressingMode = "Perform"
                self.ConsoleView.appendHtml(
                    '<b><span style="color:#ff0000;"> Performing the {} test </span></b>'
                    .format(self.currentTest))
            if "Readout chip error report" in textStr:
                self.ProgressingMode = "Summary"
            if self.ProgressingMode == "Perform":
                if ">>>> Progress :" in textStr:
                    try:
                        index = textStr.split().index("Progress") + 2
                        self.ProgressValue = float(
                            textStr.split()[index].rstrip("%"))
                        self.ResultWidget.ProgressBar[
                            self.testIndexTracker].setValue(self.ProgressValue)
                    except:
                        pass
                continue
            text = textStr.encode('ascii')
            numUpAnchor, text = parseANSI(text)
            #if numUpAnchor > 0:
            #	textCursor = self.ConsoleView.textCursor()
            #	textCursor.beginEditBlock()
            #	textCursor.movePosition(QTextCursor.End, QTextCursor.MoveAnchor)
            #	textCursor.movePosition(QTextCursor.StartOfLine, QTextCursor.KeepAnchor)
            #	for numUp in range(numUpAnchor):
            #		textCursor.movePosition(QTextCursor.Up, QTextCursor.KeepAnchor)
            #	textCursor.removeSelectedText()
            #	textCursor.deletePreviousChar()
            #	textCursor.endEditBlock()
            #	self.ConsoleView.setTextCursor(textCursor)
            textCursor = self.ConsoleView.textCursor()
            self.ConsoleView.setTextCursor(textCursor)
            self.ConsoleView.appendHtml(text.decode("utf-8"))
        self.readingOutput = False

    @QtCore.pyqtSlot()
    def on_readyReadStandardOutput_info(self):
        if os.path.exists(self.outputFile):
            outputfile = open(self.outputFile, "a")
        else:
            outputfile = open(self.outputFile, "w")

        alltext = self.info_process.readAllStandardOutput().data().decode()
        outputfile.write(alltext)
        outputfile.close()
        textline = alltext.split('\n')

        for textStr in textline:
            self.ConsoleView.appendHtml(textStr)

    @QtCore.pyqtSlot()
    def on_finish(self):
        self.RunButton.setDisabled(True)
        self.RunButton.setText("&Continue")
        self.finishSingal = True

        #To be removed
        #if isCompositeTest(self.info[1]):
        #	self.ListWidget.insertItem(self.listWidgetIndex, "{}_Module_0_Chip_0".format(CompositeList[self.info[1]][self.testIndexTracker-1]))
        #if isSingleTest(self.info[1]):
        #	self.ListWidget.insertItem(self.listWidgetIndex, "{}_Module_0_Chip_0".format(self.info[1]))

        self.testIndexTracker += 1
        self.saveConfigs()

        if isCompositeTest(self.info[1]):
            if self.testIndexTracker == len(CompositeList[self.info[1]]):
                self.RunButton.setText("&Re-run")
                self.RunButton.setDisabled(False)
        if isSingleTest(self.info[1]):
            #self.RunButton.setText("&Finish")
            #self.RunButton.setDisabled(True)
            self.RunButton.setText("&Re-run")
            self.RunButton.setDisabled(False)

        # Save the output ROOT file to output_dir
        self.saveTest()

        # validate the results
        self.validateTest()

        # show the score of test
        self.refreshHistory()

        # For test
        # self.ResultWidget.updateResult("/Users/czkaiweb/Research/data")
        self.ResultWidget.updateResult(self.output_dir)

        if self.autoSave:
            self.saveTestToDB()
        self.update()

        if isCompositeTest(self.info[1]):
            self.runTest()

    #######################################################################
    ##  For real-time terminal display
    #######################################################################

    def refresh(self):
        self.destroyHeadLine()
        self.createHeadLine()
        self.destroyApp()
        self.createApp()

    def resizeEvent(self, event):
        self.resized.emit()
        return super(QtRunWindow, self).resizeEvent(event)

    def rescaleImage(self):
        self.DisplayH = self.height() * 3. / 7
        self.DisplayW = self.width() * 3. / 7
        self.ResultWidget.resizeImage(self.DisplayW, self.DisplayH)

    def setAutoSave(self):
        if self.autoSave:
            self.autoSave = False
        else:
            self.autoSave = True
        self.saveCheckBox.setChecked(self.autoSave)

    def closeEvent(self, event):
        if self.processingFlag == True:
            event.ignore()

        else:
            reply = QMessageBox.question(
                self, 'Window Close',
                'Are you sure you want to quit the test?',
                QMessageBox.No | QMessageBox.Yes, QMessageBox.No)

            if reply == QMessageBox.Yes:
                self.release()
                self.master.powersupply.TurnOff()
                event.accept()
            else:
                self.backSignal = False
                event.ignore()
Example #11
0
class HgServeDialog(E5MainWindow):
    """
    Class implementing a dialog for the Mercurial server.
    """
    def __init__(self, vcs, path, parent=None):
        """
        Constructor
        
        @param vcs reference to the vcs object
        @param path path of the repository to serve (string)
        @param parent reference to the parent widget (QWidget)
        """
        super(HgServeDialog, self).__init__(parent)
        
        self.vcs = vcs
        self.__repoPath = path
        
        self.__styles = ["paper", "coal", "gitweb", "monoblue", "spartan", ]
        
        self.setWindowTitle(self.tr("Mercurial Server"))
        
        self.__startAct = QAction(
            UI.PixmapCache.getIcon(
                os.path.join("VcsPlugins", "vcsMercurial", "icons",
                             "startServer.png")),
            self.tr("Start Server"), self)
        self.__startAct.triggered.connect(self.__startServer)
        self.__stopAct = QAction(
            UI.PixmapCache.getIcon(
                os.path.join("VcsPlugins", "vcsMercurial", "icons",
                             "stopServer.png")),
            self.tr("Stop Server"), self)
        self.__stopAct.triggered.connect(self.__stopServer)
        self.__browserAct = QAction(
            UI.PixmapCache.getIcon("home.png"),
            self.tr("Start Browser"), self)
        self.__browserAct.triggered.connect(self.__startBrowser)
        
        self.__portSpin = QSpinBox(self)
        self.__portSpin.setMinimum(2048)
        self.__portSpin.setMaximum(65535)
        self.__portSpin.setToolTip(self.tr("Enter the server port"))
        self.__portSpin.setValue(
            self.vcs.getPlugin().getPreferences("ServerPort"))
        
        self.__styleCombo = QComboBox(self)
        self.__styleCombo.addItems(self.__styles)
        self.__styleCombo.setToolTip(self.tr("Select the style to use"))
        self.__styleCombo.setCurrentIndex(self.__styleCombo.findText(
            self.vcs.getPlugin().getPreferences("ServerStyle")))
        
        self.__serverToolbar = QToolBar(self.tr("Server"), self)
        self.__serverToolbar.addAction(self.__startAct)
        self.__serverToolbar.addAction(self.__stopAct)
        self.__serverToolbar.addSeparator()
        self.__serverToolbar.addWidget(self.__portSpin)
        self.__serverToolbar.addWidget(self.__styleCombo)
        
        self.__browserToolbar = QToolBar(self.tr("Browser"), self)
        self.__browserToolbar.addAction(self.__browserAct)
        
        self.addToolBar(Qt.TopToolBarArea, self.__serverToolbar)
        self.addToolBar(Qt.TopToolBarArea, self.__browserToolbar)
        
        self.__log = QPlainTextEdit(self)
        self.setCentralWidget(self.__log)
        
        # polish up the dialog
        self.__startAct.setEnabled(True)
        self.__stopAct.setEnabled(False)
        self.__browserAct.setEnabled(False)
        self.__portSpin.setEnabled(True)
        self.__styleCombo.setEnabled(True)
        self.resize(QSize(800, 600).expandedTo(self.minimumSizeHint()))
        
        self.process = QProcess()
        self.process.finished.connect(self.__procFinished)
        self.process.readyReadStandardOutput.connect(self.__readStdout)
        self.process.readyReadStandardError.connect(self.__readStderr)
        
        self.cNormalFormat = self.__log.currentCharFormat()
        self.cErrorFormat = self.__log.currentCharFormat()
        self.cErrorFormat.setForeground(
            QBrush(Preferences.getUI("LogStdErrColour")))
    
    def __startServer(self):
        """
        Private slot to start the Mercurial server.
        """
        port = self.__portSpin.value()
        style = self.__styleCombo.currentText()
        
        args = self.vcs.initCommand("serve")
        args.append("-v")
        args.append("--port")
        args.append(str(port))
        args.append("--style")
        args.append(style)
        
        self.process.setWorkingDirectory(self.__repoPath)
        
        self.process.start('hg', args)
        procStarted = self.process.waitForStarted(5000)
        if procStarted:
            self.__startAct.setEnabled(False)
            self.__stopAct.setEnabled(True)
            self.__browserAct.setEnabled(True)
            self.__portSpin.setEnabled(False)
            self.__styleCombo.setEnabled(False)
            self.vcs.getPlugin().setPreferences("ServerPort", port)
            self.vcs.getPlugin().setPreferences("ServerStyle", style)
        else:
            E5MessageBox.critical(
                self,
                self.tr('Process Generation Error'),
                self.tr(
                    'The process {0} could not be started. '
                    'Ensure, that it is in the search path.'
                ).format('hg'))
    
    def __stopServer(self):
        """
        Private slot to stop the Mercurial server.
        """
        if self.process is not None and \
           self.process.state() != QProcess.NotRunning:
            self.process.terminate()
            self.process.waitForFinished(5000)
            if self.process.state() != QProcess.NotRunning:
                self.process.kill()
        
        self.__startAct.setEnabled(True)
        self.__stopAct.setEnabled(False)
        self.__browserAct.setEnabled(False)
        self.__portSpin.setEnabled(True)
        self.__styleCombo.setEnabled(True)
    
    def __startBrowser(self):
        """
        Private slot to start a browser for the served repository.
        """
        ui = e5App().getObject("UserInterface")
        ui.launchHelpViewer(
            "http://localhost:{0}".format(self.__portSpin.value()))
    
    def closeEvent(self, e):
        """
        Protected slot implementing a close event handler.
        
        @param e close event (QCloseEvent)
        """
        self.__stopServer()
    
    def __procFinished(self, exitCode, exitStatus):
        """
        Private slot connected to the finished signal.
        
        @param exitCode exit code of the process (integer)
        @param exitStatus exit status of the process (QProcess.ExitStatus)
        """
        self.__stopServer()
    
    def __readStdout(self):
        """
        Private slot to handle the readyReadStandardOutput signal.
        
        It reads the output of the process and inserts it into the log.
        """
        if self.process is not None:
            s = str(self.process.readAllStandardOutput(),
                    self.vcs.getEncoding(), 'replace')
            self.__appendText(s, False)
    
    def __readStderr(self):
        """
        Private slot to handle the readyReadStandardError signal.
        
        It reads the error output of the process and inserts it into the log.
        """
        if self.process is not None:
            s = str(self.process.readAllStandardError(),
                    self.vcs.getEncoding(), 'replace')
            self.__appendText(s, True)
    
    def __appendText(self, txt, error=False):
        """
        Private method to append text to the end.
        
        @param txt text to insert (string)
        @param error flag indicating to insert error text (boolean)
        """
        tc = self.__log.textCursor()
        tc.movePosition(QTextCursor.End)
        self.__log.setTextCursor(tc)
        if error:
            self.__log.setCurrentCharFormat(self.cErrorFormat)
        else:
            self.__log.setCurrentCharFormat(self.cNormalFormat)
        self.__log.insertPlainText(txt)
        self.__log.ensureCursorVisible()
Example #12
0
class Example(QMainWindow):

    def __init__(self):
        super().__init__()

        self.use_ocr="False"
        self.initUI()
        #
        logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
                            stream=sys.stdout)
        logging.root.setLevel(logging.ERROR)
        logging.getLogger("pdfminer").setLevel(logging.ERROR)
        logging.getLogger("Ilogger").setLevel(logging.INFO)
        self.logger = logging.getLogger("Ilogger")
        #



    def initUI(self):
        sys.stdout = EmittingStr(textWritten=self.outputWritten)
        sys.stderr = EmittingStr(textWritten=self.outputWritten)
        lbl = QLabel("PDF文件夹路径:", self)
        lbl.resize(200,30)
        lbl.move(50,50)

        self.pdf_path = QLineEdit(self)
        self.pdf_path.resize(200, 30)
        self.pdf_path.move(50, 85)

        lb2= QLabel("TXT文件夹路径:", self)
        lb2.resize(200,30)
        lb2.move(50,135)

        self.txt_path = QLineEdit(self)
        self.txt_path.resize(200, 30)
        self.txt_path.move(50, 170)

        lb3 = QLabel("使用OCR识别:", self)
        lb3.move(50, 220)


        ocr=QComboBox(self)
        ocr.addItems(["True","False"])
        ocr.setCurrentIndex(1)
        ocr.move(50,255)

        ocr.activated[str].connect(self.ocr_change)

        btn2 = QPushButton("启动", self)
        btn2.move(50, 320)

        btn2.clicked.connect(self.buttonClicked)

        self.textBrowser=QPlainTextEdit(self)
        self.textBrowser.move(50,370)
        self.textBrowser.resize(400,200)

        self.setGeometry(300, 300, 500, 600)
        self.setWindowTitle('PDF转TXT工具')
        self.show()

    def outputWritten(self, text):
        cursor = self.textBrowser.textCursor()
        cursor.movePosition(QtGui.QTextCursor.End)
        cursor.insertText(text)
        self.textBrowser.setTextCursor(cursor)
        self.textBrowser.ensureCursorVisible()

    def buttonClicked(self):
        # print(self.use_ocr)
        o= self.use_ocr==str(True)
        # print("--------")
        path=os.path.join(os.path.abspath("."),"temp_png")
        if not os.path.exists( path):
            os.mkdir(path)


        if not os.path.exists( self.pdf_path.text()):
            self.logger.error("PDF路径不正确!")
            return
        if not os.path.exists( self.txt_path.text()):
            self.logger.error("TXT路径不正确!")
            return

        # run(pdf_dir=self.pdf_path.text(),txt_dir=self.txt_path.text(),ocr=o,temp_dir=path)
        r=Run_thread(self.logger,pdf_dir=self.pdf_path.text(),txt_dir=self.txt_path.text(),ocr=o,temp_dir=path)
        r.setDaemon(True)
        r.start()



    def ocr_change(self, text):
        self.use_ocr=text
Example #13
0
class View(QWidget):

    send_data           = pyqtSignal(object)
    baudrate_src_changed    = pyqtSignal(object)
    baudrate_pump_changed    = pyqtSignal(object)
    baudrate_temp_changed    = pyqtSignal(object)
    #eol_changed         = pyqtSignal(object)
    port_changed        = pyqtSignal(object)
    seedPulseChanged = pyqtSignal(object)
    seedFreValueChanged = pyqtSignal(object)
    seedPulseFreChanged = pyqtSignal(object)
    firstPumpChanged = pyqtSignal(object)
    secondPumpChanged = pyqtSignal(object)
    startSrcModel = pyqtSignal(object)
    startPumpModel = pyqtSignal(object)
    startTempModel = pyqtSignal(object)
    beginTime = pyqtSignal(object)
    emitUsername = pyqtSignal(object)

    def __init__(self):
        super(QWidget,self).__init__()
        QWidget.__init__(self)


        self.queue      = Queue()
        self.end_cmd    = None
        self.autoscroll = True
        self.msg_sent   = False

        self.timer = QTimer()
        self.timer.timeout.connect(self.update_gui)
        self.timer.start(100)
        self.srcModelstarted = False
        self.pumpModelstarted = False
        self.tempModelstarted = False
        self.currentValueList =list()
        self.currentTimeList = list()
        self.buttonMinimumWidth = 100
        # self.topSeedCurrent = 700
        # self.topPumpCurrent = 1000
        self.canClosePort = True

        self.initSeedPulse = 0
        self.initSeedFre = 0
        self.init1stCurrent = 0
        self.init2stCurrent = 0
        self.initSeedCurrent =0
        # get the lastsave record
        self.last = LastLog()
        self.lastpick = self.last.loadLast()
        uslast = self.lastpick.get('user',False)
        print('uslast',uslast)
        if uslast is False:
            self.user = User()
        else:
            self.user = uslast
        #init down machine status
        self.__init__slaveStatus()
        self.__initUI()


    def __init__slaveStatus(self):
        self.isSeedOpen = False
        self.seedcurrentre = False
        self.seedpulsere = False
        self.seedfrequecere = False
        self.seedcurrent = 0
        self.seedpulse = 0
        self.seedfrequece = 0
        self.firstcurrent = 0
        self.secondcurrent = 0
        self.isFirstPumpOpen = False
        self.isSecondPumpOpen = False
        self.isLEDOpen = False


    def __initUI(self):
        '''main window box'''

        self.mainBox = QVBoxLayout(self)#使用垂直布局类
        self.showBox = QHBoxLayout()
        self.setWindowState(Qt.WindowMaximized)
###
#command area: push button, plain text edit and line edit
###
        cmd_btn = QPushButton('Send Command (ctrl+Q)')
        cmd_btn.setMinimumWidth(self.buttonMinimumWidth)
        cmd_btn.clicked.connect(self.emit_send_data)
        #import cmd strl+enter
        cmdEnterAction = QAction(self)
        cmdEnterAction.setShortcut('ctrl+Q')
        cmdEnterAction.setStatusTip(' press ctrl+Q to send command')
        cmdEnterAction.triggered.connect(self.emit_send_data)
        self.cmd_edit = QLineEdit()
        self.cmd_edit.addAction(cmdEnterAction)
        cmdBox = QVBoxLayout()


#message box
        self.editer = QPlainTextEdit()
        self.editer.setReadOnly(True)
# <<<<<<< HEAD
        self.editer.setMaximumSize(300,2000)
# =======
        cmdBox = QVBoxLayout()
        # cmdBox.addWidget(self.cmd_edit)
        # cmdBox.addWidget(cmd_btn)
        self.powerShow = PowerShow()
        cmdBox.addWidget(self.powerShow)
# >>>>>>> a45e80ec77a4a8729fa4205165faae001fd09cab
        cmdBox.addWidget(self.editer)
        # cmd_btn.setMaximumSize(300,400)
        # self.cmd_edit.setMaximumSize(300,100)

###
#paint area use matplotlib
###
        self.paintwidget = QWidget(self)
        self.painter = MyDynamicMplCanvas(self.paintwidget, width=5, height=4, dpi=100)
        # self.showBox.addLayout(self.powerShowUI())
        self.showBox.addLayout(cmdBox)
        self.showBox.addWidget(self.painter)
        self.toolBoxUI()
        self.mainBox.addWidget(self.toolBox)
        self.mainBox.addLayout(self.showBox)


        self.setLayout(self.mainBox)
        self.setWindowTitle("光子暗化平台软件")

    def toolBoxUI(self):
        '''use a tab widget to organize set area
        '''
###
#QTabWidget() layout
###
        gbox1 = QGroupBox()
        gbox1.setStyleSheet("QGroupBox{border:None;}")
        self.useBox = QHBoxLayout(gbox1)
        self.useBox.setGeometry(QRect( 0, 0, 300,100))
        gbox2 = QGroupBox()
        gbox2.setStyleSheet("QGroupBox{border:None;}")
        self.portUI = PortGBUI()
        self.portUI.setupUi(gbox2)
        # self.portUI.widget.setGeometry(QRect( 0, 0, 450,200))
        gbox3 = QGroupBox()
        gbox3.setStyleSheet("QGroupBox{border:None;}")
        self.pumpUI = PumpUI()
        self.pumpUI.setupUi(gbox3)
        self.pumpUI.groupBox.setTitle(' ')
        # self.pumpUI.widget.setGeometry(QRect( 0, 0, 400,200))
        gbox4 = QGroupBox()
        gbox4.setStyleSheet("QGroupBox{border:None;}")
        gbox5 = QGroupBox()
        gbox5.setStyleSheet("QGroupBox{border:None;}")
        #self.menuBox = QHBoxLayout()

        # self.setBox = QHBoxLayout(gbox2)
        self.pumpBox = QGridLayout(gbox3)
        self.powerRecordBox = QHBoxLayout(gbox4)
        self.toolBox = QTabWidget()
        # self.toolBox.setStyleSheet("QTabWidget.pane{background: transparent;}\
        #     ")
        self.toolBox.addTab(gbox1,'用户登录')
        self.toolBox.addTab(gbox2,'串口设置')
        self.toolBox.addTab(gbox3,'泵浦开关')
        self.toolBox.addTab(gbox4,'功率计')
        self.toolBox.addTab(gbox5,'帮助')
        # self.toolBox.
        self.toolBox.setTabEnabled(1,False)
        self.toolBox.setTabEnabled(2,False)
        self.toolBox.setTabEnabled(3,False)
        self.toolBox.setMaximumSize(10000,200)
        # self.toolBox.resize(1200,200)
        userbox = UserView()
        userbox.usersignal.connect(self.setUser)
        self.useBox.addWidget(userbox)
        # self.useBox.addStretch()
        self.powerRecord = PowerRecord()
        self.powerRecord.getNowFig(self.painter)
        self.powerRecord.timeStateSignal.connect(self.painter.getLogTimeState)
        self.powerRecord.logStateSignal.connect(self.painter.getStartLog)
        self.powerRecord.plotlist.connect(self.painter.XYaxitList)
        self.powerRecordBox.addWidget(self.powerRecord)
#
#port set
#
        menuItem = ['300 baud','1200 baud',
            '2400 baud','4800 baud','9600 baud',
            '19200 baud','38400 baud','57600 baud',
            '115200 baud','230400 baud','250000 baud']
        self.portUI.baundrateSource.addItems(menuItem)
        self.portUI.baundratePump.addItems(menuItem)
        # self.portUI.baundrateTemp.addItems(menuItem)
#source port set
        #source
        portItem = ['com1','com2','com3','com4',
            'com5','com6','com7','com8','com9',
            'com10','com11','com12','com13',
            'com14','com15','com16','com17',
            'com18','com19','com20']
        self.portUI.portSource.addItems(portItem)
        self.portUI.portPump.addItems(portItem)
        self.setPortButton = self.portUI.openportSource
        self.closePortButton = self.portUI.closeportSource
        self.baundrateMenu = self.portUI.baundrateSource
        self.portEdit = self.portUI.portSource
        self.baundrateMenu.currentIndexChanged.connect(self.emit_br_src_changed)
        baudindex = self.lastpick.get('srcBaud',False)
        if baudindex is not False :
            self.baundrateMenu.setCurrentIndex(baudindex)
        else:
            self.baundrateMenu.setCurrentIndex(4)
        portindex = self.lastpick.get('srcPort',False)
        if baudindex is not False :
            self.portEdit.setCurrentIndex(portindex)
        else:
            self.portEdit.setCurrentIndex(1)

        baudindex = self.lastpick.get('pumpBaud',False)
        if baudindex is not False :
            self.portUI.baundratePump.setCurrentIndex(baudindex)
        else:
            self.portUI.baundratePump.setCurrentIndex(4)
        portindex = self.lastpick.get('pumpPort',False)
        if baudindex is not False :
            self.portUI.portPump.setCurrentIndex(portindex)
        else:
            self.portUI.portPump.setCurrentIndex(2)

###
#pump set
###
        self.openSeedButton = self.pumpUI.sourceSet
        self.setSeedPulse = self.pumpUI.pulseSpin
        self.openSeedButton.clicked.connect(self.emitSeedPulseAndFre)
        self.setSeedPulse.setValue(self.initSeedPulse)
        self.setSeedFreValue = self.pumpUI.frequencySpin
        self.setSeedCurrent = self.pumpUI.currentSpin
        self.setSeedCurrent.setValue(self.initSeedCurrent)
        self.openAll = self.pumpUI.sourceOpen
        self.sendfirst = self.pumpUI.firstPumpSet
        self.sendfirst.clicked.connect(self.emitFirstPumpCurrent)
        self.sendsecond = self.pumpUI.secondPumpSet
        self.sendsecond.clicked.connect(self.emitSecondPumpCurrent)
        self.setFirstpump = self.pumpUI.firstpumpSpin
        self.setFirstpump.setValue(self.init1stCurrent)
        self.setSecondpump = self.pumpUI.secondpumpSpin
        self.setSecondpump.setValue(self.init2stCurrent)
        self.closeAll = self.pumpUI.sourceClose
        self.pumpUI.firstpumpSpin.setMaximum(1000)
        self.pumpUI.secondpumpSpin.setMaximum(10000)
        self.pumpUI.secondpumpSpin.setSingleStep(500)




    def enableClosePort(self):
        if self.setSeedPulse.text()[:-2] > self.initSeedPulse :
            self.canClosePort = False
        print(self.canClosePort)
        if self.setSeedFreValue.texttext()[:-3] > self.initSeedFre :
            self.canClosePort = False
        print(self.canClosePort)
        if self.setSeedCurrent.text()[:-2] > self.initSeedCurrent:
            self.canClosePort = False
        print(self.canClosePort)
        if self.setFirstpump.text()[:-2] > self.init1stCurrent :
            self.canClosePort = False
        print(self.canClosePort)
        if self.setSecondpump.text()[:-2] > self.init2stCurrent :
            self.canClosePort = False
        print(self.canClosePort)

    def seedSignalSet(self, seedcurrent, seedpulse, seedfrequece):
        self.seedcurrent = seedcurrent
        self.setSeedCurrent.setValue(self.seedcurrent)
        self.seedpulse = seedpulse
        self.setSeedPulse.setValue(self.seedpulse)
        self.seedfrequece = seedfrequece
        self.setSeedFreValue.setValue(self.seedfrequece)

    def firstCurrentSet(self,value):
        self.firstcurrent = value
        self.setFirstpump.setValue(self.firstcurrent)

    def secondCurrentSet(self,value):
        self.secondcurrent = value
        self.setSecondpump.setValue(self.secondcurrent)

#==============================================================================
# Get, set
#==============================================================================

    def setPowerShowList(self,lst):
        self.powerShow.powerList = lst
        self.powerShow.updateFigure()

    def set_queue(self, queue):
        self.queue = queue

    def set_end_cmd(self, end_cmd):
        self.end_cmd = end_cmd

    # def set_autoscroll(self, value):
    #     self.autoscroll = value

    def set_port(self, value):
        self.portEdit.clear()
        self.portEdit.insert(value)

    def getSrcPort(self):
        self.lastpick['srcPort'] = self.portEdit.currentIndex()
        return self.portEdit.currentText()

    def getSrcBaudrate(self):
        self.lastpick['srcBaud'] = self.baundrateMenu.currentIndex()
        return self.baundrateMenu.currentText()[:-5]

    def getPumpPort(self):
        self.lastpick['pumpPort'] = self.portUI.portPump.currentIndex()
        return self.portUI.portPump.currentText()

    def getPumpBaudrate(self):
        self.lastpick['pumpBaud'] = self.portUI.baundratePump.currentIndex()
        return self.portUI.baundratePump.currentText()[:-5]

    def get_cmd(self):
        return self.cmd_edit.text()


    def setCurrentValue(self, currentValue,timeValue):
        if currentValue is not None:
            self.currentValueList = currentValue
            self.currentTimeList = timeValue


    def Button2Plot(self):
        self.painter.update_figure()

    def closeEvent(self, event):
        self.last.saveLast(self.lastpick)
        self.end_cmd()
        QWidget.closeEvent(self, event)
        print('exit')

    def beginGui(self):
        self.update()

    def update_gui(self):
        self.process_incoming()
        self.update()

    def updataFigure(self,newtime,power):
        # self.setCurrentValue(currentValue, timeValue)
        self.painter.XYaxit(newtime,power)
        self.painter.update_figure()

        # print('update?')
        # self.update()

    def process_incoming(self):
        while self.queue.qsize():
            try:
                msg = self.queue.get(0)
                self.editer.appendPlainText(str(msg))
                #show to the textplain?
                #if self.autoscroll:
                self.editer.ensureCursorVisible()
                self.scroll_down()
            except Queue.empty:
                print('=== empty queue ===')

    def scroll_down(self):
        sb = self.editer.verticalScrollBar()
        sb.setValue(sb.maximum())


    def changePort(self):
        if not self.msg_sent:
            self.msg_sent = True
            self.emit_port_changed()
        else:
            self.msg_sent = False
            return None

#==============================================================================
# Signals
#==============================================================================

    def emit_send_data(self):
        self.send_data.emit(self.get_cmd())
        self.cmd_edit.clear()

    def emit_send_command(self,command):
        self.send_data.emit(command)
        self.cmd_edit.clear()

    def emit_br_src_changed(self, value):
        baudrate = self.baundrateMenu.itemText(value)[:-5]
        self.baudrate_src_changed.emit(baudrate)

    def emit_br_pump_changed(self, value):
        baudrate = self.baundrateMenu.itemText(value)[:-5]
        self.baudrate_pump_changed.emit(baudrate)

    # def emit_br_temp_changed(self, value):
    #     baudrate = self.baundrateMenu.itemText(value)[:-5]
    #     self.baudrate_temp_changed.emit(baudrate)

    def emit_port_changed(self):
        self.port_changed.emit(self.portEdit.text())
        self.portEdit.clear()

    def emitWriteSeedPulse(self):
        self.seedPulseChanged.emit(self.setSeedPulse.text()[:-2])

    def emitWriteSeedFre(self):
        self.seedFreValueChanged.emit(self.setSeedFreValue.text()[:-3])

    def emitFirstPumpCurrent(self):
        self.firstPumpChanged.emit(self.setFirstpump.text()[:-2])

    def emitSecondPumpCurrent(self):
        self.secondPumpChanged.emit(self.setSecondpump.text()[:-2])

    def emitSeedPulseAndFre(self):
        seedPulseAndFre = [self.setSeedPulse.text()[:-2],
            self.setSeedFreValue.text()[:-3],self.setSeedCurrent.text()[:-2]]
        # print(self.setSeedPulse.text()[:-2],
        #     self.setSeedFreValue.text()[:-2],self.setSeedCurrent.text()[:-2])
        self.seedPulseFreChanged.emit(seedPulseAndFre)

    def setUser(self,value):
        self.user = value
        if value.getName() is not False:
            self.toolBox.setTabEnabled(1,True)
            self.toolBox.setTabEnabled(2,True)
            self.toolBox.setTabEnabled(3,True)
            self.powerRecord.setUserID(self.user.getName())
            self.startSrcModel.emit(self.srcModelstarted)
            self.srcModelstarted = True
            self.startPumpModel.emit(self.pumpModelstarted)
            self.pumpModelstarted = True
            # self.startTempModel.emit(self.tempModelstarted)
            # self.tempModelstarted = True
            self.emitUsername.emit(self.user.getName())
            print('emit username:'******'NoneUser')
        print('use in view:',self.user.getName())

    def lastLogSave(self):
        self.last.saveLast(self.lastpick)
Example #14
0
class LogWindow(QFrame):
    """
    Simple log window based on QPlainTextEdit using ExtraSelection to
    highlight input/output sections with different backgrounds, see:
    http://doc.qt.io/qt-5/qtwidgets-widgets-codeeditor-example.html
    """
    def __init__(self, *args):
        super().__init__(*args)
        self.setFont(monospace())
        self.textctrl = QPlainTextEdit()
        self.textctrl.setFont(monospace())  # not inherited on windows
        self.textctrl.setReadOnly(True)
        self.textctrl.setUndoRedoEnabled(False)
        self.infobar = RecordInfoBar(self.textctrl)
        self.linumbar = LineNumberBar(self.textctrl)
        self.setLayout(
            HBoxLayout([self.infobar, self.linumbar, self.textctrl],
                       tight=True))
        self.records = []
        self.formats = {}
        self._enabled = {}
        self._domains = set()
        self.loglevel = 'INFO'
        self._maxlen = 0
        self._rec_lines = deque()
        self.default_format = QTextCharFormat()

    @property
    def maxlen(self) -> int:
        """Maximum number of displayed log records. Default is ``0`` which
        means infinite."""
        return self._maxlen

    @maxlen.setter
    def maxlen(self, maxlen: int):
        maxlen = maxlen or 0
        if self._maxlen != maxlen:
            self._maxlen = maxlen
            self._rec_lines = deque(maxlen=maxlen)
            self.rebuild_log()

    def highlight(self, domain: str, color: QColor):
        """Configure log records with the given *domain* to be colorized in
        the given color."""
        format = QTextCharFormat()
        format.setProperty(QTextFormat.FullWidthSelection, True)
        format.setBackground(color)
        self.formats[domain] = format

    def setup_logging(self, level: str = 'INFO', fmt: str = '%(message)s'):
        """Redirect exceptions and :mod:`logging` to this widget."""
        level = (logging.getLevelName(level)
                 if isinstance(level, int) else level.upper())
        self.loglevel = level
        self.logging_enabled = True
        root = logging.getLogger('')
        formatter = logging.Formatter(fmt)
        handler = RecordHandler(self)
        handler.setFormatter(formatter)
        root.addHandler(handler)
        root.setLevel(level)
        sys.excepthook = self.excepthook

    def enable_logging(self, enable: bool):
        """Turn on/off display of :mod:`logging` log events."""
        self.logging_enabled = enable
        self.set_loglevel(self.loglevel)

    def set_loglevel(self, loglevel: str):
        """Set minimum log level of displayed log events."""
        self.loglevel = loglevel = loglevel.upper()
        index = LOGLEVELS.index(loglevel)
        if any([
                self._enable(level, i <= index and self.logging_enabled)
                for i, level in enumerate(LOGLEVELS)
        ]):
            self.rebuild_log()

    def enable(self, domain: str, enable: bool):
        """Turn on/off log records with the given domain."""
        if self._enable(domain, enable):
            self.rebuild_log()

    def _enable(self, domain: str, enable: bool) -> bool:
        """Internal method to turn on/off display of log records with the
        given domain.

        Returns whether calling :meth:`rebuild_log` is necessary."""
        if self.enabled(domain) != enable:
            self._enabled[domain] = enable
            return self.has_entries(domain)
        return False

    def enabled(self, domain: str) -> bool:
        """Return if the given domain is configured to be displayed."""
        return self._enabled.get(domain, True)

    def has_entries(self, domain: str) -> bool:
        """Return if any log records with the given domain have been
        emitted."""
        return domain in self._domains

    def append_from_binary_stream(self, domain, text, encoding='utf-8'):
        """Append a log record from a binary utf-8 text stream."""
        text = text.strip().decode(encoding, 'replace')
        if text:
            self.append(LogRecord(time.time(), domain, text))

    def excepthook(self, *args, **kwargs):
        """Exception handler that prints exceptions and appends a log record
        instead of exiting."""
        traceback.print_exception(*args, **kwargs)
        logging.error("".join(traceback.format_exception(*args, **kwargs)))

    def rebuild_log(self):
        """Clear and reinsert all configured log records into the text
        control.

        This is used internally if the configuration has changed such that
        previously invisible log entries become visible or vice versa."""
        self.textctrl.clear()
        self.infobar.clear()
        shown_records = [r for r in self.records if self.enabled(r.domain)]
        for record in shown_records[-self.maxlen:]:
            self._append_log(record)

    def append(self, record):
        """Add a :class:`LogRecord`. This can be called by users!"""
        self.records.append(record)
        self._domains.add(record.domain)
        if self.enabled(record.domain):
            self._append_log(record)

    def _append_log(self, record):
        """Internal method to insert a displayed record into the underlying
        :class:`QPlainTextEdit`."""
        self.infobar.add_record(record)
        self._rec_lines.append(record.text.count('\n') + 1)

        # NOTE: For some reason, we must use `setPosition` in order to
        # guarantee a absolute, fixed selection (at least on linux). It seems
        # almost if `movePosition(End)` will be re-evaluated at any time the
        # cursor/selection is used and therefore always point to the end of
        # the document.

        cursor = QTextCursor(self.textctrl.document())
        cursor.movePosition(QTextCursor.End)
        pos0 = cursor.position()
        cursor.insertText(record.text + '\n')
        pos1 = cursor.position()

        cursor = QTextCursor(self.textctrl.document())
        cursor.setPosition(pos0)
        cursor.setPosition(pos1, QTextCursor.KeepAnchor)

        selection = QTextEdit.ExtraSelection()
        selection.format = self.formats.get(record.domain, self.default_format)
        selection.cursor = cursor

        selections = self.textctrl.extraSelections()
        if selections:
            # Force the previous selection to end at the current block.
            # Without this, all previous selections are be updated to span
            # over the rest of the document, which dramatically impacts
            # performance because it means that all selections need to be
            # considered even if showing only the end of the document.
            selections[-1].cursor.setPosition(pos0, QTextCursor.KeepAnchor)
        selections.append(selection)
        self.textctrl.setExtraSelections(selections[-self.maxlen:])
        self.textctrl.ensureCursorVisible()

        if self.maxlen:
            # setMaximumBlockCount() must *not* be in effect while inserting
            # the text, because it will mess with the cursor positions and
            # make it nearly impossible to create a proper ExtraSelection!
            num_lines = sum(self._rec_lines)
            self.textctrl.setMaximumBlockCount(num_lines + 1)
            self.textctrl.setMaximumBlockCount(0)
Example #15
0
class App(QMainWindow, MeasureDeviceConnect):
    START_CURRENT = 0
    STOP_CURRENT = 0
    POINTS_TO_MEASURE = 0

    def __init__(self):
        super(App, self).__init__()
        self.left = 10
        self.top = 10
        self.title = 'Measure Laser'
        self.width = 1340
        self.height = 900
        self.initUI()

    def initUI(self):
        self.setWindowTitle(self.title)
        self.setGeometry(self.left, self.top, self.width, self.height)

        self.plot_canvas = PlotCanvas(self, width=10, height=6)
        self.plot_canvas.move(0, 0)
        self.matplotlib_toolbar = NavigationToolbar(self.plot_canvas, self)
        self.matplotlib_toolbar.move(300, 0)
        self.matplotlib_toolbar.resize(500, 50)

        self.open_ldc_settings_window = QPushButton(self)
        self.open_ldc_settings_window.setText("Ldc settings")
        self.open_ldc_settings_window.move(1150, 750)
        self.open_ldc_settings_window.resize(120, 80)
        self.open_ldc_settings_window.clicked.connect(
            self.click_to_open_ldc_settings_window)
        self.ldc_settings_window = LdcSettingsWindow(self)

        button_to_start_measure = QPushButton('Start', self)
        button_to_start_measure.setStyleSheet(
            'QPushButton {background-color: #A3C1DA; color: red;}')
        button_to_start_measure.move(1020, 10)
        button_to_start_measure.resize(140, 50)
        button_to_start_measure.clicked.connect(self.click_to_start_measure)

        button_to_stop_measure = QPushButton('Stop', self)
        button_to_stop_measure.setStyleSheet(
            'QPushButton {background-color: #A3C1DA; color: red;}')
        button_to_stop_measure.move(1180, 10)
        button_to_stop_measure.resize(140, 50)
        button_to_stop_measure.clicked.connect(self.click_to_stop_measure)

        buton_to_save_data = QPushButton("Save data", self)
        buton_to_save_data.setStyleSheet(
            'QPushButton {background-color: #A3C1DA; color: red;}')
        buton_to_save_data.clicked.connect(self.save_data)
        buton_to_save_data.move(1020, 100)
        buton_to_save_data.resize(140, 50)

        self.label_with_current_wavelength = QLabel(
            'Current wavelength: ' + str(self.WAVELENGTH) + " nm", self)
        self.label_with_current_wavelength.move(1020, 180)
        self.label_with_current_wavelength.resize(200, 80)
        button_to_set_wavelength = QPushButton('Set wavelength [nm]', self)
        button_to_set_wavelength.move(1020, 250)
        button_to_set_wavelength.resize(150, 30)
        button_to_set_wavelength.setStyleSheet(
            'QPushButton {background-color: #6dad49; color: red;}')
        button_to_set_wavelength.clicked.connect(self.set_wavelength)
        self.line_to_set_wavelength = QLineEdit(self)
        self.line_to_set_wavelength.setText(str(self.WAVELENGTH))
        self.line_to_set_wavelength.move(1180, 250)

        button_to_set_start_current = QPushButton('Set start current [mA]',
                                                  self)
        button_to_set_start_current.move(30, 650)
        button_to_set_start_current.resize(150, 30)
        button_to_set_start_current.clicked.connect(self.set_start_current)
        self.line_to_enter_start_current = QLineEdit(self)
        self.line_to_enter_start_current.setText("0")
        self.line_to_enter_start_current.move(200, 650)

        button_to_set_stop_current = QPushButton('Set stop current [mA]', self)
        button_to_set_stop_current.move(30, 700)
        button_to_set_stop_current.resize(150, 30)
        button_to_set_stop_current.clicked.connect(self.set_stop_current)
        self.line_to_enter_stop_current = QLineEdit(self)
        self.line_to_enter_stop_current.setText("0")
        self.line_to_enter_stop_current.move(200, 700)

        button_to_set_numer_of_points_to_measure = QPushButton(
            'Set points to measure', self)
        button_to_set_numer_of_points_to_measure.move(350, 650)
        button_to_set_numer_of_points_to_measure.resize(220, 30)
        button_to_set_numer_of_points_to_measure.clicked.connect(
            self.set_points_to_measure)
        self.POINTS_TO_MEASURE = 0
        self.line_to_enter_points_to_measure = QLineEdit(self)
        self.line_to_enter_points_to_measure.setText("0")
        self.line_to_enter_points_to_measure.move(600, 650)

        button_to_set_timeout_measure = QPushButton('Set timeout in seconds',
                                                    self)
        button_to_set_timeout_measure.move(350, 700)
        button_to_set_timeout_measure.resize(220, 30)
        button_to_set_timeout_measure.clicked.connect(self.set_timeout)
        self.TIMEOUT_SECONDS_MEASURE = 0
        self.line_to_enter_timeout = QLineEdit(self)
        self.line_to_enter_timeout.setText("0")
        self.line_to_enter_timeout.move(600, 700)

        self.label_info = QPlainTextEdit(self)
        self.label_info.setReadOnly(True)
        self.label_info.move(100, 750)
        self.label_info.resize(500, 100)
        self.OUT_MSG += "\nPlease set parameters to measure"
        self.label_info.setPlainText(self.OUT_MSG)
        self.label_info.moveCursor(QTextCursor.End)
        self.label_info.ensureCursorVisible()
        self.show()

    @pyqtSlot()
    def click_to_open_ldc_settings_window(self):
        self.ldc_settings_window.exec_()

    def click_to_start_measure(self):
        try:
            measure_instance = Measure()
            measure_thread = threading.Thread(
                target=measure_instance.do_measure,
                args=(
                    float(self.START_CURRENT) * 1e-3,
                    float(self.STOP_CURRENT) * 1e-3,
                    float(self.POINTS_TO_MEASURE),
                    float(self.TIMEOUT_SECONDS_MEASURE),
                ))
            measure_thread.start()
            data_now = datetime.datetime.now()
            self.OUT_MSG += "\n"
            self.OUT_MSG += data_now.strftime("%Y-%m-%d %H:%M:%S")
            self.OUT_MSG += "  Start new measure"
            self.label_info.setPlainText(self.OUT_MSG)
        except Exception as err:
            print(err)
            print("Error, unable to start thread")
        time.sleep(4)
        self.plot_canvas.real_time_plot()

    def click_to_stop_measure(self):
        MeasureDeviceConnect.ldc.off()

    def save_data(self):
        file_name_to_save = QFileDialog.getSaveFileName(
            self, "Open file", "", "Image files (*.txt )")
        current_working_directory = os.getcwd()
        shutil.copy(os.path.join(current_working_directory, "data.txt"),
                    str(file_name_to_save[0]))

    def set_wavelength(self):
        self.WAVELENGTH = self.line_to_set_wavelength.text()
        MeasureDeviceConnect.pm100.set_wavelength_in_nm(self.WAVELENGTH)
        self.WAVELENGTH = MeasureDeviceConnect.pm100.get_current_wavelength_in_nm(
        )
        self.label_with_current_wavelength.setText("Current wavelength: " +
                                                   str(self.WAVELENGTH) +
                                                   " nm")

    def set_start_current(self):
        self.START_CURRENT = self.line_to_enter_start_current.text()
        self.OUT_MSG = self.OUT_MSG + "\nstart current set to " + str(
            self.START_CURRENT) + " mA"
        self.label_info.setPlainText(self.OUT_MSG)

    def set_stop_current(self):
        self.STOP_CURRENT = self.line_to_enter_stop_current.text()
        self.OUT_MSG = self.OUT_MSG + "\nstop current set to " + str(
            self.STOP_CURRENT) + " mA"
        self.label_info.setPlainText(self.OUT_MSG)

    def set_points_to_measure(self):
        self.POINTS_TO_MEASURE = self.line_to_enter_points_to_measure.text()
        self.OUT_MSG = self.OUT_MSG + "\nnumbers of points to measure set to " + self.POINTS_TO_MEASURE
        self.label_info.setPlainText(self.OUT_MSG)

    def set_timeout(self):
        self.TIMEOUT_SECONDS_MEASURE = self.line_to_enter_timeout.text()
        self.OUT_MSG = self.OUT_MSG + "\ntimeout set to " + self.TIMEOUT_SECONDS_MEASURE + " s"
        self.label_info.setPlainText(self.OUT_MSG)