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()
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")
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
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')
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__
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()
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
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()
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()
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()
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
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)
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)
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)