class SerialTerminalWidget(QWidget): def __init__(self, parent): super(QWidget, self).__init__(parent) self.initUI() def initUI(self): self.bundle_dir = os.path.dirname(os.path.abspath(__file__)) self.layout = QVBoxLayout() self.layout.setSpacing(0) self.layout.setContentsMargins(0, 0, 0, 0) self.cliTextEdit = QPlainTextEdit( "CLI mode, type 'exit' to return, or 'help'\n\n") self.cliTextEdit.setStyleSheet( "QPlainTextEdit {background-color:gray; color:white; min-height:590; max-height:600}" ) self.cliInputLine = QLineEdit() self.cliInputLine.returnPressed.connect(self.newInputReceived) self.layout.addWidget(self.cliTextEdit) self.layout.addWidget(self.cliInputLine) self.layout.addStretch(1) # Set Main Layout of this page self.setLayout(self.layout) def newInputReceived(self): waitingText = self.cliInputLine.text() if len(waitingText) > 0: self.cliTextEdit.appendPlainText("$" + waitingText) self.cliInputLine.setText("")
class Example(QWidget): def __init__(self): super().__init__() self.menu = ["Чизбургер", "Гамбургер", "Кока-кола", "Нагетсы"] self.initUI() def initUI(self): self.setGeometry(400, 300, 300, 400) self.setWindowTitle('Заказ в Макдональдсе') self.check_b = [QCheckBox(self) for i in self.menu] self.btn = QPushButton('Заказать', self) self.btn.clicked.connect(self.run) self.btn.move(10, 20 * (len(self.check_b) + 1)) for i in range(len(self.check_b)): self.check_b[i].setText(self.menu[i]) self.check_b[i].move(10, 20 * i) self.result = QPlainTextEdit(self) self.result.setEnabled(False) self.result.move(10, 20 * (len(self.check_b) + 3)) def run(self): self.result.clear() result = [i.text() for i in self.check_b if i.isChecked()] result.insert(0, "Ваш заказ\n") self.result.appendPlainText("\n".join(result))
def slot_edit_palette_data(self): dialog = QDialog(self) tabWidget = QTabWidget() dialog.setWindowTitle(i18n("Edit Palette Data")) dialog.setLayout(QVBoxLayout()) dialog.layout().addWidget(tabWidget) paletteWidget = QWidget() paletteWidget.setLayout(QVBoxLayout()) tabWidget.addTab(paletteWidget, i18n("Palette Data")) paletteName = QLineEdit() paletteName.setText(self.cmb_palettes.currentText()) paletteWidget.layout().addWidget(paletteName) paletteColumns = QSpinBox() paletteColumns.setValue(self.currentPalette.columnCount()) paletteWidget.layout().addWidget(paletteColumns) paletteComment = QPlainTextEdit() paletteComment.appendPlainText(self.currentPalette.comment()) paletteWidget.layout().addWidget(paletteComment) buttons = QDialogButtonBox(QDialogButtonBox.Ok) dialog.layout().addWidget(buttons) buttons.accepted.connect(dialog.accept) # buttons.rejected.connect(dialog.reject()) if dialog.exec_() == QDialog.Accepted: Resource = Application.resources("palette")[ self.cmb_palettes.currentText()] Resource.setName(paletteName.text()) self.currentPalette = Palette(Resource) self.currentPalette.setColumnCount(paletteColumns.value()) self.paletteView.setPalette(self.currentPalette) self.slot_fill_combobox() self.currentPalette.setComment(paletteComment.toPlainText()) self.currentPalette.save()
class UpdateDialog(QDialog): """The dialog for update.""" def __init__(self): super(UpdateDialog, self).__init__() vbox = QVBoxLayout(self) self.closed = False self.setModal(True) self.resize(500, 250) vbox.addWidget(QLabel("Actualización de la lista de episodios:")) self.text = QPlainTextEdit() self.text.setReadOnly(True) vbox.addWidget(self.text) bbox = QDialogButtonBox(QDialogButtonBox.Cancel) bbox.rejected.connect(self.reject) vbox.addWidget(bbox) def append(self, text): """Append some text in the dialog.""" self.text.appendPlainText(text.strip()) def closeEvent(self, event): """It was closed.""" self.closed = True
class InfoScreenWidget(QDialog): # Defines and pulls up a notepad type widget, the text of which is saved # to .db. def __init__(self, mw, db, tribe): try: QDialog.__init__(self, mw) self.db = db self.mw = mw self.tribe = tribe self.setWindowTitle('Info for ' + tribe) self.setGeometry(100, 150, 400, 350) self.setModal(True) self.grid = QGridLayout() self.textArea = QPlainTextEdit() self.currentInfo = self.db.get_info(tribe) self.textArea.appendPlainText(self.currentInfo) self.grid.addWidget(self.textArea, 0, 0) ok_btn = QPushButton('Ok') ok_btn.pressed.connect(self.save_info) self.grid.addWidget(ok_btn, 1, 0) self.setLayout(self.grid) self.show() except Exception: logger.exception('infoScreen fail') def save_info(self): logger.debug('Ok clicked on info widget') # Once Ok is clicked take text in widget and save to .db new_info = self.textArea.toPlainText() if self.currentInfo != new_info: # Only save if changes made self.db.update_info(self.tribe, new_info) logger.info('new text saved to info') self.close()
class Widget(QWidget): def __init__(self, parent=None): super(Widget, self).__init__(parent) self._lineedit = QLineEdit(textChanged=self.onTextChanged) regex_validator = QRegExpValidator(QRegExp(r"[0-9 ]+")) self._lineedit.setValidator(regex_validator) self._plaintextedit = QPlainTextEdit() self._highlighter = SyntaxHighlighter(self._plaintextedit.document()) lay = QVBoxLayout(self) lay.addWidget(self._lineedit) lay.addWidget(self._plaintextedit) for i in range(10): self._plaintextedit.appendPlainText("line %d" % i) self.resize(720, 720) @pyqtSlot(str) def onTextChanged(self, text): fmt = QTextCharFormat() fmt.setBackground(QColor("yellow")) self._highlighter.clear_highlight() for e in text.split(): line = int(e) self._highlighter.highlight_line(line, fmt)
class TextEditDialog(QDialog): """Text edit dialog with line numbers.""" def __init__(self, text, apply_callback): super().__init__() self.apply_callback = apply_callback self.textbox = QPlainTextEdit() self.textbox.setFont(monospace()) self.linenos = LineNumberBar(self.textbox) buttons = QDialogButtonBox() buttons.addButton(buttons.Ok).clicked.connect(self.accept) self.setLayout( VBoxLayout([ HBoxLayout([self.linenos, self.textbox], tight=True), buttons, ])) self.setSizeGripEnabled(True) self.resize(QSize(600, 400)) self.textbox.appendPlainText(text) def accept(self): if self.apply(): super().accept() def apply(self): text = self.textbox.toPlainText() return self.apply_callback(text)
class WorkerMessagesDialog(QDialog): """ A dialog to show messages from a parallel worker.""" def __init__(self, parent=None, window_title="Messages"): super(WorkerMessagesDialog, self).__init__(parent) self.setWindowTitle(window_title) self.setWindowModality(Qt.ApplicationModal) layout = QVBoxLayout(self) # text edit self.textedit = QPlainTextEdit() layout.addWidget(self.textedit) # buttons buttons = QDialogButtonBox( QDialogButtonBox.Ok | QDialogButtonBox.Cancel, Qt.Horizontal, self ) buttons.accepted.connect(self.accept) buttons.rejected.connect(self.reject) layout.addWidget(buttons) def acceptNewMessage(self, message): self.textedit.appendPlainText(message) @staticmethod def show(parent=None, window_title="Messages"): dialog = WorkerMessagesDialog(parent, window_title) result = dialog.exec_()
class TestWindow(QWidget): def __init__(self, *args, **kwargs): super(TestWindow, self).__init__(*args, **kwargs) layout = QHBoxLayout(self) # 左侧原始 left_group = QGroupBox('原始QSlider', self) left_layout = QVBoxLayout(left_group) self.leftLabel = QPlainTextEdit(self) left_layout.addWidget(self.leftLabel) self.leftSlider = QSlider(Qt.Horizontal, self) self.leftSlider.valueChanged.connect(self.onLeftChanged) left_layout.addWidget(self.leftSlider) layout.addWidget(left_group) # 右侧低频率变化 right_group = QGroupBox('LfSlider', self) right_layout = QVBoxLayout(right_group) self.rightLabel = QPlainTextEdit(self) right_layout.addWidget(self.rightLabel) self.rightSlider = LfSlider(Qt.Horizontal, self) self.rightSlider.valueChanged.connect(self.onRightChanged) right_layout.addWidget(self.rightSlider) layout.addWidget(right_group) def onLeftChanged(self, value): self.leftLabel.appendPlainText(datetime.now().strftime("[%H:%M:%S.%f] ") + str(value)) def onRightChanged(self, value): self.rightLabel.appendPlainText(datetime.now().strftime("[%H:%M:%S.%f] ") + str(value))
class MainWindow(QMainWindow): def __init__(self): super().__init__() # Some buttons layout = QVBoxLayout() self.text = QPlainTextEdit() layout.addWidget(self.text) btn_run = QPushButton("Execute") btn_run.clicked.connect(self.start) layout.addWidget(btn_run) w = QWidget() w.setLayout(layout) self.setCentralWidget(w) # Thread runner self.threadpool = QThreadPool() def start(self): # Create a runner self.runner = SubProcessWorker("python ~/dumy.py") self.runner.signals.result.connect(self.result) self.threadpool.start(self.runner) def result(self, s): self.text.appendPlainText(s)
class Example(QWidget): def __init__(self): super().__init__() self.menu = ["Бургер", "Молочный коктель", "Картофель фри", "Нагецы", "Кока-кола", "Бигмак", "Чизбургер"] self.initUI() def initUI(self): self.setGeometry(400, 300, 300, 400) self.setWindowTitle('15_3') self.check_b = [QCheckBox(self) for i in self.menu] self.btn = QPushButton('Заказать', self) self.btn.clicked.connect(self.run) self.btn.move(10, 20 * (len(self.check_b) + 1)) for i in range(len(self.check_b)): self.check_b[i].setText(self.menu[i]) self.check_b[i].move(10,20*i) self.result = QPlainTextEdit(self) self.result.setEnabled(True) self.result.move(10,20*(len(self.check_b)+3)) def run(self): self.result.clear() result = [i.text() for i in self.check_b if i.isChecked()] self.result.appendPlainText("\n".join(result))
class Widget(QWidget): def __init__(self): super().__init__() self.initUI() def initUI(self): self.textArea = QPlainTextEdit() self.textArea.setFocusPolicy(Qt.NoFocus) self.message = QLineEdit() self.message.returnPressed.connect(self.sendMessage) layout = QVBoxLayout() layout.addWidget(self.textArea) layout.addWidget(self.message) self.timer = QTimer() self.timer.timeout.connect(self.displayNewMessage) self.timer.start(1000) self.setLayout(layout) self.show() def sendMessage(self): server.post(chatUrl, {"name": name, "message": self.message.text()}) self.message.clear() def displayNewMessage(self): newMessage = server.get(chatUrl).text if newMessage: self.textArea.appendPlainText(newMessage)
class QTextEditLogger(logging.Handler): #Log 창 만드는 class def __init__(self, parent): super().__init__() self.widget = QPlainTextEdit(parent) def emit(self, record): msg = self.format(record) self.widget.appendPlainText(msg)
class MainWindow(QMainWindow): def __init__(self): super().__init__() self.btn = QPushButton("Execute") self.btn.pressed.connect(self.start_process) self.text = QPlainTextEdit() self.text.setReadOnly(True) self.p = None l = QVBoxLayout() l.addWidget(self.btn) l.addWidget(self.text) w = QWidget() w.setLayout(l) self.setCentralWidget(w) def start_process(self): if self.p is None: self.message("Executing process.") self.p = QProcess() # Keep a reference to the QProcess (e.g. on self) while it's running. self.p.readyReadStandardOutput.connect(self.handle_stdout) self.p.readyReadStandardError.connect(self.handle_stderr) self.p.stateChanged.connect(self.handle_state) # self.p.finished.connect(self.cleanup) self.p.finished.connect(self.process_finished) self.p.start("python3", ['external.py']) def message(self, s): self.text.appendPlainText(s) def process_finished(self): self.message('Process finished') self.p = None def handle_stderr(self): data = self.p.readAllStandardError() stderr = bytes(data).decode("utf8") self.message(stderr) def handle_stdout(self): data = self.p.readAllStandardOutput() stdout = bytes(data).decode("utf8") self.message(stdout) def handle_state(self, state): states = { QProcess.NotRunning: 'Not running', QProcess.Starting: 'Starting', QProcess.Running: 'Running', } state_name = states[state] self.message(f"State changed: {state_name}")
class QPlainTextEditLogger(logging.Handler): def __init__(self, parent): super().__init__() self.widget = QPlainTextEdit(parent) self.widget.setReadOnly(True) def emit(self, record): msg = self.format(record) self.widget.appendPlainText(msg)
class DocumentSearch(QWidget): def __init__(self): super().__init__() self.font = QFont() self.font.setFamily("Iosevka") self.font.setPointSize(12) self.setWindowTitle("Find a document") self.initUI() def initUI(self): self.layout = QVBoxLayout(self) self.vbox = QHBoxLayout() self.label = QLabel("Enter a file name to search:") self.searchButton = QPushButton("Search") self.cancelButton = QPushButton("Cancel") self.searchResults = QPlainTextEdit() self.infoLabel = QLabel("Results will be displayed below") self.searchResults.setReadOnly(True) self.searchDocumentField = QLineEdit() self.searchButton.clicked.connect(self.trigger) self.cancelButton.clicked.connect(lambda: self.hide()) self.searchButton.setAutoDefault(True) self.label.setFont(self.font) self.infoLabel.setFont(self.font) self.searchResults.setFont(self.font) self.layout.addWidget(self.label) self.layout.addWidget(self.searchDocumentField) self.layout.addWidget(self.infoLabel) self.layout.addWidget(self.searchResults) self.vbox.addWidget(self.searchButton) self.vbox.addWidget(self.cancelButton) self.layout.addLayout(self.vbox) self.setLayout(self.layout) def trigger(self): file = self.searchDocumentField.text() self.thread = grabFiles(file) self.thread.start() self.thread.fileSignal.connect(self.showPath) def showPath(self, path): self.searchResults.appendPlainText("\n") self.searchResults.appendPlainText(path) def run(self): self.show()
class SerialTerminalWidget(QWidget): serTerSignal = pyqtSignal() def __init__(self, parent): super(QWidget, self).__init__(parent) self.initUI() self.setUpdateTimer() def initUI(self): self.bundle_dir = os.path.dirname(os.path.abspath(__file__)) self.layout = QVBoxLayout() self.layout.setSpacing(0) self.layout.setContentsMargins(0, 0, 0, 0) self.cliTextEdit = QPlainTextEdit( "Serial Terminal mode, type 'exit' to return, or 'help'\n\n") self.cliTextEdit.setStyleSheet( "QPlainTextEdit {background-color:gray; color:white; min-height:590; max-height:800}" ) self.cliInputLine = QLineEdit() self.cliInputLine.returnPressed.connect(self.newInputReceived) self.layout.addWidget(self.cliTextEdit) self.layout.addWidget(self.cliInputLine) # self.layout.addStretch(1) # Set Main Layout of this page self.setLayout(self.layout) # Use QTimer def setUpdateTimer(self): ## Start a timer to rapidly update the plot self.sched = QTimer() self.sched.timeout.connect(self.checkDataBuffer) def checkDataBuffer(self): self.serTerSignal.emit() def processFeedback(self, feedbackStr): date_time = str(datetime.datetime.now()).split() (date, time) = date_time preStr1 = "[ " + time + " ] " preStr2 = "[ " + str(len(feedbackStr)) + " ] " self.cliTextEdit.appendPlainText(preStr1 + preStr2 + feedbackStr) def start(self): self.sched.start(1000) def stop(self): self.sched.stop() def newInputReceived(self): waitingText = self.cliInputLine.text() if len(waitingText) > 0: self.cliTextEdit.appendPlainText("$" + waitingText) self.cliInputLine.setText("")
def log_window(self): widget = QPlainTextEdit(self) widget.setReadOnly(True) widget.appendPlainText('Simple Test') widget.appendHtml(alertHtml + 'Alert Test') widget.appendHtml(notifyHtml + 'Notify Test') widget.appendHtml(infoHtml + 'Info Test') widget.appendHtml(endHtml + 'Endhtml') widget.show()
class QPlainTextEditLogger(logging.Handler): def __init__(self): super().__init__() self.widget = QPlainTextEdit() self.widget.setReadOnly(True) def emit(self, record): msg = "{} {}".format(datetime.datetime.now().strftime("[%H:%M:%S]"), self.format(record)) self.widget.appendPlainText(msg)
class InfoDialog(QDialog): def __init__(self, title, parent=None): super(InfoDialog, self).__init__(parent) self.resize(800, 400) self.setWindowTitle(title) btn = QDialogButtonBox.Ok self.btnbox = QDialogButtonBox(btn, self) self.btnbox.setDisabled(True) self.plainText = QPlainTextEdit(self) vbox = QVBoxLayout() vbox.addWidget(self.plainText) vbox.addWidget(self.btnbox) self.btnbox.accepted.connect(self.accept) self.done = False self.plainText.setReadOnly(True) self.thread_cnt = 0 self.setLayout(vbox) # self.plainText.textChanged.connect(self.test) def upload_text(self, text): self.plainText.appendPlainText(text) self.highlihgter() def progress_done(self): self.btnbox.setDisabled(False) def highlihgter(self): highlight_rules = [('INFO', Qt.darkGreen), ('Warning', Qt.darkYellow), ('Error', Qt.darkRed)] cursor = self.plainText.textCursor() text = self.plainText.toPlainText() for keyword, color in highlight_rules: regex = QRegExp(keyword) index = regex.indexIn(text) fmt = QTextCharFormat() fmt.setForeground(color) while index != -1: cursor.setPosition(index) cursor.movePosition(QTextCursor.EndOfWord, 1) cursor.mergeCharFormat(fmt) # Move to the next match pos = index + regex.matchedLength() index = regex.indexIn(text, pos) def accept(self): self.plainText.setPlainText('') self.btnbox.setDisabled(True) super(InfoDialog, self).accept() def reject(self): self.plainText.setPlainText('') self.btnbox.setDisabled(True) super(InfoDialog, self).reject()
class QLogger(logging.Handler): def __init__(self, parent): super().__init__() self.widget = QPlainTextEdit(parent) self.widget.setReadOnly(True) self.setFormatter(logging.Formatter('%(asctime)s - %(levelname)s - %(message)s')) def emit(self, record): msg = self.format(record) self.widget.appendPlainText(msg)
class TextLogElement(object): def __init__(self, maximum_block_count: int = 1000, font_size_pt: int = 10, font_family: str = "Courier", title: str = "Log") -> None: # For nested layouts: (1) create everything, (2) lay out self.log_group = StyledQGroupBox(title) log_layout_1 = QVBoxLayout() log_layout_2 = QHBoxLayout() self.log = QPlainTextEdit() self.log.setReadOnly(True) self.log.setLineWrapMode(QPlainTextEdit.NoWrap) self.log.setMaximumBlockCount(maximum_block_count) font = self.log.font() font.setFamily(font_family) font.setPointSize(font_size_pt) log_clear_button = QPushButton('Clear log') log_clear_button.clicked.connect(self.log.clear) log_copy_button = QPushButton('Copy to clipboard') log_copy_button.clicked.connect(self.copy_whole_log) log_layout_2.addWidget(log_clear_button) log_layout_2.addWidget(log_copy_button) log_layout_2.addStretch(1) log_layout_1.addWidget(self.log) log_layout_1.addLayout(log_layout_2) self.log_group.setLayout(log_layout_1) def get_widget(self) -> QWidget: return self.log_group def add(self, msg: str) -> None: # http://stackoverflow.com/questions/16568451 # self.log.moveCursor(QTextCursor.End) self.log.appendPlainText(msg) # ... will append it as a *paragraph*, i.e. no need to add a newline # self.scroll_to_end_of_log() def copy_whole_log(self) -> None: # Ctrl-C will copy the selected parts. # log.copy() will copy the selected parts. self.log.selectAll() self.log.copy() self.log.moveCursor(QTextCursor.End) self.scroll_to_end_of_log() def scroll_to_end_of_log(self) -> None: vsb = self.log.verticalScrollBar() vsb.setValue(vsb.maximum()) hsb = self.log.horizontalScrollBar() hsb.setValue(0)
class newTextBox(): def __init__(self, parent, size, pos, init_text=""): #self.textBox = QLineEdit(parent) self.textBox = QPlainTextEdit(parent) self.textBox.appendPlainText(init_text) self.textBox.setReadOnly(True) if size and pos: self.textBox.setGeometry(pos[0], pos[1], size[0], size[1]) #self.textBox.resize(size[0], size[1]) #self.textBox.setMaximumHeight(size[1]) def showText(self, text): self.textBox.appendPlainText(text)
def __init__(self): super().__init__() uic.loadUi('menu.ui', self) # подгружаем файл из designer # подключаем кнопки self.play.clicked.connect(self.Show_lvl) self.rules.clicked.connect(self.Show_rules) print_text = QPlainTextEdit(self) print_text.resize(181, 51) print_text.move(730, 189) print_text.appendPlainText(str(max(best_score)))
class QTextEditLogger(logging.Handler, QObject): sigAppendLog = pyqtSignal(str) MAX_LENGTH = 300 def __init__(self, parent): super().__init__() QObject.__init__(self) self._init_ui(parent) # self.cursor = QTextCursor(self.text_widget.document()) self.sigAppendLog.connect(self.append_log) self.setFormatter( logging.Formatter( '%(levelname)s %(module)s:%(funcName)s %(message)s')) logging.getLogger().addHandler(self) self.setLevel(logging.DEBUG) def _init_ui(self, parent): self.widget = QWidget(parent) self.level_box = QComboBox(self.widget) self.level_box.addItems('DEBUG INFO WARNING ERROR'.split()) self.level_box.currentIndexChanged.connect(self.level_changed) self.text_widget = QPlainTextEdit(self.widget) self.text_widget.setReadOnly(True) layout = QGridLayout(self.widget) layout.addWidget(self.level_box, 0, 0) layout.addWidget(self.text_widget, 1, 0) @pyqtSlot(int, name='levelBoxIndexChanged') def level_changed(self, idx): text = self.level_box.currentText() self.setLevel(_LEVEL_DICT[text]) @pyqtSlot(str, name='appendLog') def append_log(self, log: str): level, *message = log.split() message = _set_html_color(' '.join(message), level) if len(message) > self.MAX_LENGTH: self.text_widget.appendPlainText('') self.text_widget.appendHtml(message) if len(message) > self.MAX_LENGTH: self.text_widget.appendPlainText('') def emit(self, record): msg = self.format(record) try: self.sigAppendLog.emit(msg) except RuntimeError: pass
class RunWidget(QWidget): finish_signal = pyqtSignal() control_mouse_and_keyboard_start_signal = pyqtSignal() control_mouse_and_keyboard_end_signal = pyqtSignal() def __init__(self, parent=None): super(RunWidget, self).__init__(parent) self.initUI() def initUI(self): self.go_button = QPushButton('下载') self.go_button.setMinimumHeight(35) self.state_show = QPlainTextEdit() self.state_show.setReadOnly(True) self.run_box = QVBoxLayout(self) self.run_box.addWidget(self.go_button) self.run_box.addWidget(self.state_show) self.run_box.setAlignment(Qt.AlignHCenter | Qt.AlignTop) self.state_show.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) self.setLayout(self.run_box) def appendText(self, text): if text.strip(): self.state_show.appendPlainText(text.strip()) def setGoButtonEnabeld(self, bool): self.go_button.setEnabled(bool) def download(self, read_mode, get_links_from_wechat_mode, write, write_mode, link=''): self.dl = Download(read_mode, get_links_from_wechat_mode, write, write_mode, link) self.dl.print_signal.connect(self.appendText) self.dl.finish_signal.connect( lambda b=True: self.setGoButtonEnabeld(b)) self.dl.finish_signal.connect(self.finish_signal.emit) self.dl.control_mouse_and_keyboard_start_signal.connect( self.control_mouse_and_keyboard_start_signal.emit) self.dl.control_mouse_and_keyboard_end_signal.connect( self.control_mouse_and_keyboard_end_signal.emit) self.setGoButtonEnabeld(False) self.dl.start()
class QPlainTextEditLogger(logging.Handler): def __init__(self, parent): super().__init__() self.widget = QPlainTextEdit(parent) self.widget.setReadOnly(True) self.widget.setStyleSheet("Color:white;" "background-color:rgba(0, 0, 0, 150);") self.widget.verticalScrollBar().setValue(0) def emit(self, record): msg = self.format(record) self.widget.appendPlainText(msg) self.widget.verticalScrollBar().setValue( self.widget.verticalScrollBar().maximum())
class Example(QWidget): lst = [] def __init__(self): super().__init__() self.initUI() def initUI(self): self.setGeometry(480, 370, 480, 370) self.setWindowTitle('Заказ в Макдональдсе') self.te = QPlainTextEdit(self) self.te.move(200, 20) self.te.resize(250, 350) self.btn = QPushButton('Создать новый', self) self.btn.resize(160, 20) self.btn.move(20, 60) self.btn.clicked.connect(self.create_file) self.btn1 = QPushButton('Сохранить файл', self) self.btn1.resize(160, 20) self.btn1.move(20, 100) self.btn1.clicked.connect(self.end_work) self.btn2 = QPushButton('Открыть файл', self) self.btn2.resize(160, 20) self.btn2.move(20, 140) self.btn2.clicked.connect(self.open_file) self.le = QLineEdit(self) self.le.resize(160, 20) self.le.move(20, 20) def create_file(self): self.f = open(self.le.text(), 'w') def open_file(self): with open(self.le.text(), 'r') as f: text = f.read() self.te.appendPlainText(text) self.f = open(self.le.text(), 'w') def end_work(self): self.f.write(self.te.toPlainText()) self.f.close() self.te.clear()
class TextSubTab(QWidget): def __init__(self, sending=True): super(QWidget, self).__init__() layout = QHBoxLayout() self.text_message = QPlainTextEdit() self.text_message.setDisabled(not sending) layout.addWidget(self.text_message) self.setLayout(layout) def append_text_message(self, message): self.text_message.appendPlainText(message) def clear_text_message(self): self.text_message.clear()
def InitWindow(self): self.setWindowIcon(QtGui.QIcon("transistor.jpg")) self.setWindowTitle(self.title) self.setGeometry(self.top, self.width, self.height, self.width) vbox = QVBoxLayout() plainTextEdit = QPlainTextEdit() vbox.addWidget(plainTextEdit) plainTextEdit.setPlaceholderText( "This is the placeholder for the plain") #plainTextEdit.setReadOnly(True) text = "Please suck my c**k" plainTextEdit.appendPlainText(text) #plainTextEdit.setUndoRedoEnabled(False) self.setLayout(vbox)
class Assembler(QMainWindow): def __init__(self, parent=None): super(Assembler, self).__init__(parent) self.resize(800, 600) self.filename = None self.filetuple = None self.dirty = False # Refers to Data Page only. self.nb = None centralwidget = QWidget(self) gridLayout = QGridLayout(centralwidget) self.tabWidget = QTabWidget(centralwidget) # textbox self.tab = QWidget() font = QFont() font.setFamily("Inconsolata") font.setPointSize(14) self.tab.setFont(font) gridLayout_3 = QGridLayout(self.tab) self.plainTextEdit = QPlainTextEdit(self.tab) self.plainTextEdit.installEventFilter(self) self.plainTextEdit.setAcceptDrops(True) gridLayout_3.addWidget(self.plainTextEdit, 0, 0, 1, 1) self.tabWidget.addTab(self.tab, "") self.tab_2 = QWidget() self.tab_2.setFont(font) gridLayout_2 = QGridLayout(self.tab_2) self.plainTextEdit_2 = QPlainTextEdit(self.tab_2) gridLayout_2.addWidget(self.plainTextEdit_2, 0, 0, 1, 1) self.tabWidget.addTab(self.tab_2, "") self.tab_3 = QWidget() self.tab_3.setFont(font) gridLayout_3 = QGridLayout(self.tab_3) self.checkbox = QCheckBox("Cloning genes by tailed primers (no pYPKa_A vectors constructed)") self.checkbox.setChecked(True) gridLayout_3.addWidget(self.checkbox, 0, 0, 0, 0) self.tabWidget.addTab(self.tab_3, "") gridLayout.addWidget(self.tabWidget, 0, 0, 1, 1) self.setCentralWidget(centralwidget) menubar = QMenuBar(self) menubar.setGeometry(QRect(0, 0, 800, 29)) menu_File = QMenu(menubar) self.menu_Solve = QMenu(menubar) self.menu_Help = QMenu(menubar) self.setMenuBar(menubar) self.statusbar = QStatusBar(self) self.setStatusBar(self.statusbar) self.action_New = QAction(self) self.actionSave_As = QAction(self) self.action_Save = QAction(self) self.action_Open = QAction(self) self.action_Quit = QAction(self) self.action_About = QAction(self) self.actionShow_CCPL = QAction(self) self.action_Solve = QAction(self) self.action_OpenNB = QAction(self) self.action_CCPL = QAction(self) self.action_Help = QAction(self) menu_File.addAction(self.action_New) menu_File.addAction(self.action_Open) menu_File.addAction(self.actionSave_As) menu_File.addAction(self.action_Save) menu_File.addSeparator() menu_File.addAction(self.action_Quit) self.menu_Solve.addAction(self.action_Solve) self.menu_Solve.addAction(self.action_OpenNB) self.menu_Help.addAction(self.action_About) #self.menu_Help.addAction(self.action_CCPL) #self.menu_Help.addAction(self.action_Help) menubar.addAction(menu_File.menuAction()) menubar.addAction(self.menu_Solve.menuAction()) menubar.addAction(self.menu_Help.menuAction()) self.tabWidget.setTabText(self.tabWidget.indexOf(self.tab),\ "Data Page") self.tabWidget.setTabText(self.tabWidget.indexOf(self.tab_2),\ "Assembly log") self.tabWidget.setTabText(self.tabWidget.indexOf(self.tab_3),\ "Settings") menu_File.setTitle("&File") self.menu_Solve.setTitle("&Assemble") self.menu_Help.setTitle("&About") self.tabWidget.setCurrentIndex(0) self.action_New.setText("&New") self.action_Open.setText("&Open") self.actionSave_As.setText("Save &As") self.action_Save.setText("&Save") self.action_Quit.setText("&Quit") self.action_Solve.setText("&Assemble") self.action_OpenNB.setText("&Open &pathway") self.action_About.setText("&About") #self.action_CCPL.setText("&CCPL") #self.action_Help.setText("&Help") self.action_Quit.triggered.connect(self.close) allToolBar = self.addToolBar("AllToolBar") allToolBar.setObjectName("AllToolBar") self.addActions(allToolBar, (self.action_Open, self.actionSave_As, self.action_Save, self.action_Solve, self.action_OpenNB, self.action_Quit )) self.action_New.triggered.connect(self.fileNew) self.action_Open.triggered.connect(self.fileOpen) self.actionSave_As.triggered.connect(self.fileSaveAs) self.action_Save.triggered.connect(self.fileSave) self.action_Solve.triggered.connect(self.solveAssembly) self.action_OpenNB.triggered.connect(self.openNB) self.action_About.triggered.connect(self.aboutBox) #self.action_CCPL.triggered.connect(self.displayCCPL) #self.action_Help.triggered.connect(self.help) self.plainTextEdit.textChanged.connect(self.setDirty) self.action_New = self.editAction(self.action_New, None,\ 'ctrl+N', 'filenew', 'New File.') self.action_Open = self.editAction(self.action_Open, None, 'ctrl+O', 'fileopen', 'Open File.') self.actionSave_As = self.editAction(self.actionSave_As,\ None, 'ctrl+A', 'filesaveas',\ 'Save and Name File.') self.action_Save = self.editAction(self.action_Save, None, 'ctrl+S', 'filesave', 'Save File.') self.action_Solve = self.editAction(self.action_Solve, None, '', 'solve', 'Assemble.') self.action_OpenNB = self.editAction(self.action_OpenNB, None, '', 'ipynb', 'Open pathway.') self.action_About = self.editAction(self.action_About, None, 'ctrl+B', 'about','Pop About Box.') self.action_CCPL = self.editAction(self.action_CCPL, None, 'ctrl+G', 'licence', 'Show Licence') self.action_Help = self.editAction(self.action_Help, None, 'ctrl+H', 'help', 'Show Help Page.') self.action_Quit = self.editAction(self.action_Quit, None, 'ctrl+Q', 'quit', 'Quit the program.') self.plainTextEdit_2.setReadOnly(True) self.setWindowTitle("ypkpathway") self.setWindowIcon(QIcon( resource_filename("ypkpathway","icons/ypkpathway.png"))) self.plainTextEdit.setFocus() def eventFilter(self, object, event): #print(event.type(), QEvent.DragEnter, object, self.plainTextEdit) if (object is self.plainTextEdit): if (event.type() == QEvent.DragEnter): if event.mimeData().hasUrls(): event.accept() # must accept the dragEnterEvent or else the dropEvent can't occur !!! print("accept") else: event.ignore() print("ignore") if (event.type() == QEvent.Drop): if event.mimeData().hasUrls(): # if file or link is dropped urlcount = len(event.mimeData().urls()) # count number of drops url = event.mimeData().urls()[0] # get first url object.setPlainText('abc') # assign first url to editline event.accept() # doesnt appear to be needed print(456) return True return False # lets the event continue to the edit return False def setDirty(self): '''On change of text in textEdit window, set the flag "dirty" to True''' index = self.tabWidget.currentIndex() if index is not 0: return if self.dirty: return True self.dirty = True self.updateStatus('self.dirty set to True') def clearDirty(self): 'Clear dirty flag' self.dirty = False def fileNew(self): '''Clear both Data Page and Solution Page.''' self.plainTextEdit.setPlainText(' ') self.plainTextEdit_2.setPlainText(' ') self.clearDirty() self.filename = None def okToContinue(self): if self.dirty: reply = QMessageBox.question(self, "Data Loader - Unsaved Changes", "Save unsaved changes?", QMessageBox.Yes|QMessageBox.No|QMessageBox.Cancel) if reply == QMessageBox.Cancel: return False elif reply == QMessageBox.Yes: self.clearDirty() return self.fileSave() return True def okRead(self): 'Pop-up a warning message.' reply = QMessageBox.warning(self, "Warning", '''\nFile Open and Save only in Data Page \n\(Use SaveAs for the Assembly log)''', QMessageBox.Ok) return True def fileOpen(self): '''Open a file in Data Page (with index == 0)''' if self.tabWidget.currentIndex(): self.okRead() return if not self.okToContinue(): return dir_ = (os.path.dirname(str(self.filename)) if self.filename is not None else ".") filetuple = QFileDialog.getOpenFileName(self,"Open File", dir_,) self.filename = filetuple[0] # QFileDialog returns a tuple x with x[0] = file name and # x[1] = type of filter. if self.filename: self.loadFile(self.filename) self.updateStatus('New file opened.') def loadFile(self, fname=None): fl = open(fname, "r") text = fl.read() self.plainTextEdit.setPlainText(text) self.dirty = False def fileSave(self): '''Save file with current file name.''' if self.tabWidget.currentIndex(): self.okRead() return if self.filename is None: return self.fileSaveAs() else: flname = self.filename if flname: tempText = self.plainTextEdit.toPlainText() with open(flname, 'w') as fl: fl.write(tempText) self.dirty = False self.updateStatus('File saved.') return True else: self.updateStatus('Failed to save... ') return False self.filename = None self.dirty = False def fileSaveAs(self): '''Save file with a new name.''' qpr = self.qprintline fname = self.filename or "NoName.txt" self.filename = str(QFileDialog.getSaveFileName(self,"ypkpathway - Save File", fname)) flname = self.filename or "NoName.txt" self.filename = flname fl = open(flname, 'w') tempText = str(self.plainTextEdit.toPlainText()) fl.write(tempText) fl.close() self.dirty = False self.updateStatus('File saved.') def solveAssembly(self): printline = self.qprintline self.plainTextEdit_2.clear() self.tabWidget.setCurrentIndex(1) flbase = os.path.basename(str(self.filename)) title = 'Assembly log for ' + flbase printline('='*len(title)) printline(title) printline('='*len(title)) #print(type(self.plainTextEdit.toPlainText())) #qstringobj = self.plainTextEdit.toPlainText().encode('utf-8') #print(type(qstringobj)) #<class 'PyQt4.QtCore.QString'> #print(qstringobj.toUtf8()[3268:3279]) #print(str(qstringobj.toUtf8()[3268:3279])) #print(type(rawtext), "rawtext") #codec0 = .QTextCodec.codecForName("UTF-16"); #rawtext = unicode(codec0.fromUnicode(tmp), 'UTF-16') #unicode(qstringobj.toUtf8(), encoding="UTF-8").decode() qstringobj = self.plainTextEdit.toPlainText() #import sys;sys.exit(42) pth = parse( qstringobj ) #import sys;sys.exit(42) if len(pth)==0: printline("No of sequences found in Data window") return if self.filename is None: self.fileSaveAs() dir_, ext = os.path.splitext( str(self.filename)) fl, log = ypkpathway.pathway( pth, dir_, pYPKa_A = not self.checkbox.isChecked(), print = printline) if not fl: return with open(os.path.join(dir_, "log.txt"),"w") as f: f.write(log) shutil.copy2( str(self.filename), os.path.join(dir_, "INDATA_"+os.path.basename(str(self.filename)))) printline('') printline('\n\nAssembly finished.') printline('click on the Open pathway button above to open the pathway in the default web browser') self.nb = fl.path def qprintline(self, line): '''Append one line to Solution Page.''' self.plainTextEdit_2.appendPlainText(line.rstrip()) #.decode("utf8")) QApplication.processEvents() def openNB(self): if self.nb: subprocess.Popen(["ipython", "notebook", self.nb]) def aboutBox(self): from PyQt5.QtCore import QT_VERSION_STR from PyQt5.Qt import PYQT_VERSION_STR from sip import SIP_VERSION_STR from ._version import get_versions __version__ = get_versions()["version"][:5] del get_versions from IPython import __version__ as IPython_version QMessageBox.about(self, "About ypkpathway", """<b>Planning of yeast pathway kit constructions.</b> <p>version: {}<br> Copyright 2015-2017 Björn Johansson. This software is released under a BSD style license. This software comes with no warranties expressed or implied.<br><br> Python version: {}<br><br> IPython version: {}<br> Qt version: {}<br> SIP version: {}<br> PyQt version: {}<br> pydna version: {}<br></p> """.format(__version__, sys.version, IPython_version, QT_VERSION_STR, SIP_VERSION_STR, PYQT_VERSION_STR, pydna.__version__[:5])) def displayCCPL(self): '''Read and display CCPL licence.''' self.plainTextEdit.setPlainText(open('CCPL.txt').read()) self.dirty = False self.filename = 'COPYING.txt' self.updateStatus('CCPL displayed.') def help(self): '''Read and display a help file- currently the README.txt.''' self.plainTextEdit.setPlainText(open('README.md').read()) self.dirty = False self.filename = 'README.txt' self.updateStatus('README displayed.') def addActions(self, target, actions): '''Actions are added to Tool Bar.''' for action in actions: if action is None: target.addSeparator() else: target.addAction(action) def editAction(self, action, slot=None, shortcut=None, icon=None, tip=None): '''This method adds to action: icon, shortcut, ToolTip,\ StatusTip and can connect triggered action to slot ''' if icon is not None: action.setIcon(QIcon(":/%s.png" % (icon))) if shortcut is not None: action.setShortcut(shortcut) if tip is not None: action.setToolTip(tip) action.setStatusTip(tip) if slot is not None: action.triggered.connect(slot) return action def qreadline(self, lineNo): '''Read one line from Data Page (lineNo starts with 0)''' return str(self.plainTextEdit.document().\ findBlockByLineNumber(lineNo).text()).rstrip() def updateStatus(self, message): '''Keep status current.''' if self.filename is not None: flbase = os.path.basename(str(self.filename)) self.setWindowTitle(str("ypkpathway - " +\ flbase + "[*]") ) self.statusBar().showMessage(message, 5000) self.setWindowModified(self.dirty)
class Window(QWidget): def __init__(self, parent=None): super(Window, self).__init__(parent) grid = QGridLayout() grid.addWidget(self.create_top_group(), 0, 0) grid.addLayout(self.create_mid_group(), 1, 0) grid.addWidget(self.create_bottom_group(), 2, 0) self.setLayout(grid) self.setWindowTitle("UJ Editor") self.resize(1280, 640) # self.create_actions() # def __wiggets_to_layout(self, layout, *widgets): # for widget in widgets: # layout.addWidget(widget) def __mix_to_layout(self, layout, *mix): for item in mix: if isinstance(item, QWidget): layout.addWidget(item) if isinstance(item, QLayout): layout.addLayout(item) def create_top_group(self): group_box = QGroupBox() self.import_button = QPushButton('&Import UJ') self.import_button.clicked.connect(self.import_uj) export_button = QPushButton('&Export UJ') export_button.clicked.connect(self.export_uj) self.uj_name = LabelLineEdit('UJ Name') hbox = QHBoxLayout() hbox.setContentsMargins(0,0,0,0) self.__mix_to_layout(hbox, self.import_button, export_button, self.uj_name.layout) group_box.setLayout(hbox) group_box.setMaximumHeight(60) return group_box def create_mid_group(self): self.ddi_tree = QTreeWidget() self.ddi_tree.itemSelectionChanged.connect(self.show_ddi_details) ddi_details = QGroupBox() ddi_details_layout = QGridLayout() ddi_details_layout.setContentsMargins(0,0,0,0) ddi_details_layout.addWidget(self.create_common_ddi_details(), 0, 0, 1, 1) ddi_details_layout.addWidget(self.create_specific_ddi_details(), 1, 0, 3, 1) ddi_details.setLayout(ddi_details_layout) self.step_tree = QTreeWidget() self.step_tree.itemSelectionChanged.connect(self.show_step_details) step_details = QGroupBox() step_details_layout = QGridLayout() step_details_layout.setContentsMargins(0,0,0,0) step_details_layout.addWidget(self.create_common_step_details(), 0, 0, 1, 1) # step_details_layout.addWidget(self.create_specific_step_details(), 1, 0, 3, 1) step_details.setLayout(step_details_layout) splitter = QSplitter(self) splitter.addWidget(self.ddi_tree) splitter.addWidget(ddi_details) splitter.addWidget(self.step_tree) splitter.addWidget(step_details) hbox = QHBoxLayout() hbox.setContentsMargins(0,0,0,0) # self.__mix_to_layout(hbox, self.ddi_tree, ddi_details, self.step_tree, step_details) hbox.addWidget(splitter) # group_box.setLayout(hbox) return hbox def create_bottom_group(self): group_box = QGroupBox() group_box.setMaximumHeight(200) self.debug_edit = QPlainTextEdit() self.debug_edit.setMaximumHeight(160) hbox = QHBoxLayout() hbox.setContentsMargins(0,0,0,0) # hbox.setSizeConstraint(200) hbox.addWidget(self.debug_edit) group_box.setLayout(hbox) return group_box def create_common_ddi_details(self): group_box = QGroupBox() vbox = QVBoxLayout() self.ddi_description = LabelLineEdit('Description') type_name_layout = QHBoxLayout() type_name_layout.setContentsMargins(0,0,0,0) self.ddi_name = LabelLineEdit('DDI Name') self.ddi_type = LabelComboBox('Type', DDI_TYPES) self.__mix_to_layout(type_name_layout, self.ddi_type.layout, self.ddi_name.layout) self.ddi_sharing = LabelButtonGroup('State Sharing', {'SCRIPT ': '&Single User', 'THREAD ': '&All Run Users'}) self.ddi_refresh = LabelButtonGroup('Refresh Condition', {'C': 'Every Cycle', 'R': 'Once per Run', 'T': 'Every Time', 'U': 'Once per User'}) vbox.setContentsMargins(0,0,0,0) self.__mix_to_layout(vbox, type_name_layout, self.ddi_description.layout, self.ddi_sharing.layout, self.ddi_refresh.layout) group_box.setLayout(vbox) return group_box # ()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()() def create_specific_ddi_details(self): group_box = QGroupBox() self.ddi_specific_layout = QVBoxLayout() self.ddi_specific_layout.setContentsMargins(0,0,0,0) # self.value_layout = self.create_ddi_value() self.ddi_value_widget = LabelLineEdit('Value') self.ddi_selector_widget = LabelComboBox('Selector', SELECTOR_TYPES) # self.ddi_specific_layout.addWidget(self.ddi_value_widget) self.ddi_specific_layout.addLayout(self.ddi_value_widget.layout) self.ddi_specific_layout.addLayout(self.ddi_selector_widget.layout) self.ddi_date = DateFieldsGroup() self.ddi_specific_layout.addLayout(self.ddi_date.layout) self.ddi_delimiter_character_widget = LabelLineEdit('Delimiter:') self.ddi_delimiter_character_widget.line_edit.setMaxLength(1) self.ddi_delimited_filename_widget = LabelLineEdit('File Name:') self.ddi_delimited_file_picker_button = QPushButton('&Load Data File') self.ddi_delimited_file_picker_button.clicked.connect(self.load_data_file) delimited_layout = QHBoxLayout() delimited_layout.setContentsMargins(0,0,0,0) delimited_layout.addLayout(self.ddi_delimiter_character_widget.layout, stretch = 0) delimited_layout.addLayout(self.ddi_delimited_filename_widget.layout, stretch = 2) delimited_layout.addWidget(self.ddi_delimited_file_picker_button, stretch = 1) self.ddi_specific_layout.addLayout(delimited_layout) self.ddi_column_index_widget = LabelLineEdit('Column Index:') self.ddi_column_index_widget.line_edit.setInputMask('999') self.ddi_specific_layout.addLayout(self.ddi_column_index_widget.layout) self.ddi_list_table = MyTableWidget() self.ddi_specific_layout.addLayout(self.ddi_list_table.layout) self.ddi_related_ddi = LabelComboBox('Related to:') self.ddi_specific_layout.addLayout(self.ddi_related_ddi.layout) self.ddi_response_source_step = LabelComboBox('Source Step:') self.ddi_specific_layout.addLayout(self.ddi_response_source_step.layout) self.ddi_siphon_table = RowControlTableWidget([('type', list(SIPHON_TYPES.values())), ('start', ''), ('end', ''), ('index', '')]) self.ddi_specific_layout.addLayout(self.ddi_siphon_table.layout) self.ddi_auto_correlate_type = LabelComboBox('Field Type:', { z:z for z in ['Repeated Fields', 'Known Fields'] }) self.ddi_specific_layout.addLayout(self.ddi_auto_correlate_type.layout) self.ddi_auto_correlate_name = LabelComboBox('Field Name:') self.ddi_specific_layout.addLayout(self.ddi_auto_correlate_name.layout) self.ddi_auto_correlate_appears_in = LabelCheckboxesGroup('Appears In:', ['URL', 'Post', 'Headers']) self.ddi_specific_layout.addLayout(self.ddi_auto_correlate_appears_in.layout) hbox = QHBoxLayout() hbox.setContentsMargins(0,0,0,0) self.ddi_auto_increment_starting_value = LabelLineEdit('Starting Value:') hbox.addLayout(self.ddi_auto_increment_starting_value.layout) self.ddi_auto_increment_increment = LabelLineEdit('Increment:') hbox.addLayout(self.ddi_auto_increment_increment.layout) self.ddi_auto_increment_prefix = LabelLineEdit('Prefix:') hbox.addLayout(self.ddi_auto_increment_prefix.layout) self.ddi_auto_increment_suffix = LabelLineEdit('Suffix:') hbox.addLayout(self.ddi_auto_increment_suffix.layout) self.ddi_auto_increment_min_lenght = LabelLineEdit('Minimum Length:') hbox.addLayout(self.ddi_auto_increment_min_lenght.layout) self.ddi_specific_layout.addLayout(hbox) group_box.setLayout(self.ddi_specific_layout) return group_box # ()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()() def create_common_step_details(self): group_box = QGroupBox() vbox = QVBoxLayout() vbox.setContentsMargins(0,0,0,0) vbox.setAlignment(Qt.AlignTop) name_sleep_layout = QHBoxLayout() name_sleep_layout.setContentsMargins(0,0,0,0) self.step_name = LabelLineEdit('Name') name_sleep_layout.addLayout(self.step_name.layout) self.step_pre_time = LabelLineEdit('Sleep Time (sec)') name_sleep_layout.addLayout(self.step_pre_time.layout) vbox.addLayout(name_sleep_layout) self.step_description = LabelLineEdit('Description') vbox.addLayout(self.step_description.layout) self.step_checkboxes = LabelCheckboxesGroup('', ['Run First Cycle Only', 'Run Last Cycle Only', 'Count as Transaction', 'Process Response', 'Execute Separately']) vbox.addLayout(self.step_checkboxes.layout) request_type_content_type_layout = QHBoxLayout() self.request_type = LabelComboBox('Type', { z:z for z in STEP_REQUEST_TYPES }) request_type_content_type_layout.addLayout(self.request_type.layout) self.content_type = LabelComboBox('Content-Type', { z:z for z in STEP_CONTENT_TYPES }) request_type_content_type_layout.addLayout(self.content_type.layout) # self.content_type.combo_box.currentIndexChanged[str].connect(self.update_content_subtypes) # # what's the point of having type and subtypes? the one sent with headers is the subtype - it should be the only selection # self.content_subtype = LabelComboBox('', { z:z for z in STEP_CONTENT_TYPES['form'] }) # request_type_content_type_layout.addLayout(self.content_subtype.layout) vbox.addLayout(request_type_content_type_layout) self.step_url = LabelLineEdit('URL') vbox.addLayout(self.step_url.layout) self.step_url_params_table = RowControlTableWidget([('Parameter', ''), ('Value', '')]) vbox.addLayout(self.step_url_params_table.layout) self.step_post_params_table = RowControlTableWidget([('Parameter', ''), ('Value', '')]) vbox.addLayout(self.step_post_params_table.layout) self.step_post_block = QPlainTextEdit() vbox.addWidget(self.step_post_block) success_validation_layout = QHBoxLayout() success_validation_layout.setContentsMargins(0,0,0,0) self.step_validation_type = LabelComboBox('Success Validation', {'PLAIN': 'Plain Text','REGEX': 'Regular Expression'}) success_validation_layout.addLayout(self.step_validation_type.layout) self.step_validation_text = LabelLineEdit('') success_validation_layout.addLayout(self.step_validation_text.layout) self.max_response = LabelLineEdit('Max acceptable response time') success_validation_layout.addLayout(self.max_response.layout) vbox.addLayout(success_validation_layout) self.step_dynamic_content = LabelCheckboxesGroup('Select content types to be handled automatically', ['images', 'css', 'javaScript']) vbox.addLayout(self.step_dynamic_content.layout) flow_control_line1_layout = QHBoxLayout() self.step_flow_control_type = LabelComboBox('Flow Control', {'': 'GoTo', 'RESPONSE': 'Response Based', 'CONDTITIONAL': 'Conditional', 'PERCENTAGE': 'Percentage Based', 'DDLOOP': 'Dynamic Data Loop', 'VARIABLELOOP': 'Variable Loop', 'FIXEDLOOP': 'Fixed Loop'}) flow_control_line1_layout.addLayout(self.step_flow_control_type.layout) self.step_flow_target_plus = LabelComboBox('Step', {'NEXT_STEP': 'Next Step', 'END_CYCLE': 'End Cycle', 'END_USER': '******'}) flow_control_line1_layout.addLayout(self.step_flow_target_plus.layout) self.step_flow_sleep = LabelLineEdit('Sleep Time (sec)') flow_control_line1_layout.addLayout(self.step_flow_sleep.layout) vbox.addLayout(flow_control_line1_layout) flow_control_line2_layout = QHBoxLayout() self.step_flow_ddl_ddi = LabelComboBox('Dynamic Data Item', {}) flow_control_line2_layout.addLayout(self.step_flow_ddl_ddi.layout) self.step_flow_varloop_start = LabelLineEdit('Minimum Iterations') flow_control_line2_layout.addLayout(self.step_flow_varloop_start.layout) self.step_flow_varloop_end = LabelLineEdit('Maximum Iterations') flow_control_line2_layout.addLayout(self.step_flow_varloop_end.layout) self.step_flow_fixloop = LabelLineEdit('Iterations') flow_control_line2_layout.addLayout(self.step_flow_fixloop.layout) self.step_flow_conditional_true = LabelComboBox('If true, go to', {'NEXT_STEP': 'Next Step', 'END_CYCLE': 'End Cycle', 'END_USER': '******'}) flow_control_line2_layout.addLayout(self.step_flow_conditional_true.layout) self.step_flow_conditional_false = LabelComboBox('otherwise, go to', {'NEXT_STEP': 'Next Step', 'END_CYCLE': 'End Cycle', 'END_USER': '******'}) flow_control_line2_layout.addLayout(self.step_flow_conditional_false.layout) vbox.addLayout(flow_control_line2_layout) self.step_flow_response_table = RowControlTableWidget([('Response Step', []), ('Match Criteria', ''), ('Step', []), ('Sleep Time', '0.0')]) vbox.addLayout(self.step_flow_response_table.layout) self.step_flow_percentage_table = RowControlTableWidget([('Percentage', ''), ('Step', []), ('Sleep Time', '0.0')]) self.step_flow_percentage_table.set_text([['100', {'Next Step': ['Next Step', 'End Cycle', 'End User']}, '0.0']]) vbox.addLayout(self.step_flow_percentage_table.layout) self.step_flow_conditional_table = RowControlTableWidget([('Phrase 1', ''), ('Conditional', ['<', '<=', '=', '=>', '>', '!=', 'in', 'not in']), ('Phrase 2', ''), ('Operator', ['AND', 'OR'])]) vbox.addLayout(self.step_flow_conditional_table.layout) group_box.setLayout(vbox) return group_box def create_specific_step_details(self): pass # ------------------------------------------------------ end of creations ---------------------------------------------------------- # def create_actions(self): # self.import_act = QAction("&Import...", self, shortcut="Ctrl+I", triggered=self.import_uj) # self.export_act = QAction("&Export...", self, shortcut="Ctrl+E", triggered=self.export_uj) # def update_content_subtypes(self, item): # # item is supposed to be the text value of the combobox selection # print('reached function update_content_subtypes with item=', item) def debug__(self, message): self.debug_edit.appendPlainText(message) def load_data_file(self): filename = QFileDialog.getOpenFileName(self, 'Open File', os.getenv('HOME')) self.ddi_delimited_filename_widget.set_text(filename[0]) self.selected_ddi.file_name = filename def import_uj(self, filename=[]): if not filename: filename = QFileDialog.getOpenFileName(self, 'Open File', os.getenv('HOME')) self.uj = UserJourney('') self.uj.import_uj(filename[0]) self.uj_name.set_text(self.uj.name) ddi_nodes = [] for ddi in self.uj.dditems: new_ddi_node = QTreeWidgetItem() new_ddi_node.setText(0, ddi.name) ddi_nodes.append(new_ddi_node) self.ddi_tree.addTopLevelItems(ddi_nodes) date_type_ddis = self.uj.find_ddis_by_attribute('type', 'DATE ') if date_type_ddis: self.ddi_date.related_ddi_box.reset_items({z.name:z.name for z in date_type_ddis}) relatable_type_ddis = [] for type_ in ['FLATFILE', 'LIST ', 'RESPONSE']: relatable_type_ddis.extend(self.uj.find_ddis_by_attribute('type', type_)) if relatable_type_ddis: self.ddi_related_ddi.reset_items({z.name:z.name for z in relatable_type_ddis}) sourceable_step_names = [] sourceable_steps = self.uj.find_steps_by_attribute('name_user_defined', True) if sourceable_steps: self.ddi_response_source_step.reset_items({ str(z.id):z.name for z in sourceable_steps }) sourceable_step_names = [ z.name for z in sourceable_steps ] self.correlated_names = { z.field_name:z.field_name for z in self.uj.find_ddis_by_attribute('type', 'AUTOCORR') } # if z.field_type == 'Repeated Fields' } self.ddi_auto_correlate_name.reset_items(self.correlated_names) groupnodes = [] for stepgroup in self.uj.stepgroups: new_group_node = QTreeWidgetItem() new_group_node.setText(0, stepgroup.name) stepnodes = [] for step in stepgroup.steps: new_step_node = QTreeWidgetItem(new_group_node) new_step_node.setText(0, step.name) stepnodes.append(new_step_node) groupnodes.append(new_group_node) self.step_tree.addTopLevelItems(groupnodes) self.step_flow_response_table.reset_row_template([('Response Step', sourceable_step_names), ('Match Criteria', ''), ('Step', ['Next Step'] + sourceable_step_names + ['End Cycle', 'End User']), ('Sleep Time', '0.0')]) self.step_flow_percentage_table.reset_row_template([('Percentage', ''), ('Step', ['Next Step'] + sourceable_step_names + ['End Cycle', 'End User']), ('Sleep Time', '0.0')]) # self.step_flow_percentage_table.set_text([['100', {'Next Step': ['Next Step', 'End Cycle', 'End User']}, '0.0']]) def export_uj(self): pass # convert SIPHON_TYPES from full text to code before passing them to self.uj... def show_ddi_details(self): selected_ddi_name = self.ddi_tree.selectedItems()[0].text(0) self.selected_ddi = self.uj.find_ddi_by_name(selected_ddi_name) # Common self.ddi_name.set_text(selected_ddi_name) self.ddi_description.set_text(self.selected_ddi.description) self.ddi_type.set_text(DDI_TYPES[self.selected_ddi.type]) self.ddi_sharing.set_text(self.selected_ddi.scope) self.ddi_refresh.set_text(self.selected_ddi.lifecycle) # Specific ddi_specific_fields = [ self.ddi_value_widget, self.ddi_selector_widget, self.ddi_delimiter_character_widget, self.ddi_delimited_filename_widget, self.ddi_delimited_file_picker_button, self.ddi_column_index_widget, self.ddi_date, self.ddi_list_table, self.ddi_related_ddi, self.ddi_response_source_step, self.ddi_siphon_table, self.ddi_auto_correlate_type, self.ddi_auto_correlate_name, self.ddi_auto_correlate_appears_in, self.ddi_auto_increment_starting_value, self.ddi_auto_increment_increment, self.ddi_auto_increment_prefix, self.ddi_auto_increment_suffix, self.ddi_auto_increment_min_lenght, ] ddi_type_mappings = { ConstantDDI: {self.ddi_value_widget: 'value'}, DateDDI: { self.ddi_date: [ 'starting_point', 'starting_value', 'starting_value', 'offset_type', 'format', 'first_offset_sign', 'first_offset_value', 'first_offset_unit', 'second_offset_sign', 'second_offset_value', 'second_offset_unit', ] }, DelimitedFileDDI: { self.ddi_delimiter_character_widget: 'delimiter', self.ddi_delimited_filename_widget: 'file_name', self.ddi_delimited_file_picker_button: '', self.ddi_column_index_widget: 'column', self.ddi_selector_widget: 'selection_type', }, ListDDI: {self.ddi_selector_widget: 'selection_type', self.ddi_column_index_widget: 'column', self.ddi_list_table: ['table']}, VariableDDI: {self.ddi_value_widget: 'value'}, RelatedDDI: {self.ddi_column_index_widget: 'column', self.ddi_related_ddi: 'associated'}, ResponseDDI: {self.ddi_selector_widget: 'selection_type', self.ddi_column_index_widget: 'column', self.ddi_response_source_step: 'source_step_id', self.ddi_siphon_table: 'dict_siphons'}, AutoCorrelatedDDI: {self.ddi_auto_correlate_type: 'field_type', self.ddi_auto_correlate_name: 'field_name', self.ddi_auto_correlate_appears_in: ['find_in_url', 'find_in_post', 'find_in_headers']}, AutoIncrementDDI: {self.ddi_auto_increment_starting_value: 'starting_value', self.ddi_auto_increment_increment: 'increment', self.ddi_auto_increment_prefix: 'prefix', self.ddi_auto_increment_suffix: 'suffix', self.ddi_auto_increment_min_lenght: 'minimum_length'}, } object_attribute_pairs = ddi_type_mappings[type(self.selected_ddi)] # print('obj', object_attribute_pairs ) # print('selected type', type(self.selected_ddi) ,'selected item expected attributes', object_attribute_pairs.values() ) for field in ddi_specific_fields: debug_message = '' # print('field', field, 'values', object_attribute_pairs.values()) if field in object_attribute_pairs.keys(): field.show() target_attribute_name = object_attribute_pairs[field] # print('target attribute', target_attribute_name) if isinstance(target_attribute_name, str): if target_attribute_name != '': # print('ttt', type(getattr(self.selected_ddi, object_attribute_pairs[field]))) value = getattr(self.selected_ddi, object_attribute_pairs[field]) if callable(value): value = value() else: value = str(value) field.set_text(value) # print('target attribute value', value) # --- debug --- if field == self.ddi_value_widget: debug_message += 'field: '+str(field)+'; uj object value: '+ str(value) + '\n' else: # currently this section covers for Date group & table widget values =[] for attribute in target_attribute_name: try: # values.append(str(getattr(self.selected_ddi, attribute))) values.append(getattr(self.selected_ddi, attribute)) except AttributeError: pass # print('values', values) field.set_values(*values) # where set_values(self, starting_point, starting_fixed_edit, starting_related_ddi, offset, sign1='', amount1=0, unit1='', sign2='', amount2=0, unit2=''): # i.e. the attributes that may be missing are set as optional arguments else: field.hide() # --- debug --- if field == self.ddi_response_source_step: debug_message += 'ui object value: ' + self.ddi_response_source_step.text() + '; visibility: ' + str(self.ddi_response_source_step.combo_box.isVisible()) + '\n' self.debug__(debug_message) def show_step_details(self): selected_step_name = self.step_tree.selectedItems()[0].text(0) self.selected_step = self.uj.find_step_by_name(selected_step_name) # self.ddi_name.set_text(selected_ddi_name) # self.ddi_description.set_text(self.selected_ddi.description) # self.ddi_type.set_text(DDI_TYPES[self.selected_ddi.type]) # self.ddi_sharing.set_text(self.selected_ddi.scope) # self.ddi_refresh.set_text(self.selected_ddi.lifecycle) self.step_name.set_text(selected_step_name) self.step_pre_time.set_text(self.selected_step.sleeptime) self.step_description.set_text(self.selected_step.description) # print(self.selected_step.first_cycle_only, self.selected_step.last_cycle_only, self.selected_step.count_as_transaction, self.selected_step.processresponse, self.selected_step.execute_separately) self.step_checkboxes.set_values(self.selected_step.first_cycle_only, self.selected_step.last_cycle_only, self.selected_step.count_as_transaction, self.selected_step.processresponse, self.selected_step.execute_separately) # ['Run First Cycle Only', 'Run Last Cycle Only', 'Count as Transaction', 'Process Response', 'Execute Separately']) self.request_type.set_text(self.selected_step.type) selected_step_content_type = '' for header in self.selected_step.headers: if header['name'] == 'Content-Type': selected_step_content_type = header['value'] self.content_type.set_text(selected_step_content_type) self.step_url.set_text(self.selected_step.request) if self.selected_step.get_itmes == []: self.step_url_params_table.hide() else: self.step_url_params_table.show() get_params = [] for item in self.selected_step.get_itmes: get_params.append([item['name'], item['value']]) self.step_url_params_table.set_text(get_params) if self.selected_step.post_items == []: self.step_post_params_table.hide() self.step_post_block.hide() else: if self.selected_step.post_items[0]['name'] == '': self.step_post_params_table.hide() self.step_post_block.show() self.step_post_block.appendPlainText(self.selected_step.post_items[0]['value']) else: self.step_post_block.hide() self.step_post_params_table.show() self.step_post_params_table.set_text([ [z['name'], z['value']] for z in self.selected_step.post_items]) selected_step_validation_type = '' for item in self.selected_step.items: if item['name'] == 'ValidationType': selected_step_validation_type = item['value'] self.step_validation_type.set_text(selected_step_validation_type) self.step_validation_text.set_text(self.selected_step.success) selected_step_max_response = '' for item in self.selected_step.items: if item['name'] == 'MaxResponseTime': selected_step_max_response = item['value'] if self.selected_step.is_lead(): self.max_response.show() self.max_response.set_text(selected_step_max_response) else: self.max_response.hide() selected_step_dynamic_content = [] for item in self.selected_step.items: if item['name'] == 'contentTypes': selected_step_dynamic_content = [ z in item['value'] for z in ['images', 'javaScript', 'css'] ] if self.selected_step.is_lead(): self.step_dynamic_content.show() self.step_dynamic_content.set_values(*selected_step_dynamic_content) else: self.step_dynamic_content.hide() self.step_flow_target_plus.hide() self.step_flow_sleep.hide() self.step_flow_ddl_ddi.hide() self.step_flow_varloop_start.hide() self.step_flow_varloop_end.hide() self.step_flow_fixloop.hide() self.step_flow_conditional_true.hide() self.step_flow_conditional_false.hide() self.step_flow_response_table.hide() self.step_flow_percentage_table.hide() self.step_flow_conditional_table.hide() # need to update the step list every time because new steps might have been added after the initial import steps = self.uj.list_step_name_id_pairs() steps.update({'NEXT_STEP': 'Next Step', 'END_CYCLE': 'End Cycle', 'END_USER': '******'}) self.step_flow_target_plus.reset_items(steps) # reset val even if hidden if not hasattr(self.selected_step, 'flow_type'): self.step_flow_control_type.set_text('GoTo') self.step_flow_target_plus.show() self.step_flow_target_plus.set_text('NEXT_STEP') self.step_flow_sleep.show() self.step_flow_sleep.set_text('0.0') else: # ==================================== ALL NON 'GOTO' FLOW CONTROL ==================================== self.step_flow_control_type.set_text(self.selected_step.flow_type) selected_step_flow_target = '' selected_step_flow_sleep = '' selected_step_flow_ddi = '' selected_step_flow_miniter = '' selected_step_flow_maxiter = '' selected_step_flow_iter = '' selected_step_flow_conditional_true_target = '' selected_step_flow_conditional_false_target = '' for item in self.selected_step.flow_items: if item['name'] == 'DESTINATIONSTEP': selected_step_flow_target = item['value'] if item['name'] == 'SLEEPTIME': selected_step_flow_sleep = str(float(item['value'])/1000) if item['name'] == 'DDITEM': selected_step_flow_ddi = item['value'] if item['name'] == 'MINITERCOUNT': selected_step_flow_miniter = item['value'] if item['name'] == 'MAXITERCOUNT': selected_step_flow_maxiter = item['value'] if item['name'] == 'ITERCOUNT': selected_step_flow_iter = item['value'] if item['name'] == 'TRUECONDITIONSTEP': selected_step_flow_conditional_true_target = item['value'] if item['name'] == 'FALSECONDITIONSTEP': selected_step_flow_conditional_false_target = item['value'] if self.selected_step.flow_type not in ['RESPONSE', 'CONDTITIONAL', 'PERCENTAGE']: self.step_flow_target_plus.show() self.step_flow_target_plus.set_text(selected_step_flow_target) if self.selected_step.flow_type not in ['RESPONSE', 'PERCENTAGE']: self.step_flow_sleep.show() self.step_flow_sleep.set_text(selected_step_flow_sleep) if self.selected_step.flow_type == 'DDLOOP': applicable_ddis_by_refresh = self.uj.find_ddis_by_attribute('lifecycle', 'T') # {'C': 'Cycle', 'R': 'Run', 'T': 'Time', 'U': 'User',} applicable_ddis_by_selection_randomunique = self.uj.find_ddis_by_attribute('selection_type', 'RANDONCE') applicable_ddis_by_selection_sequnique = self.uj.find_ddis_by_attribute('selection_type', 'SEQUONCE') applicable_ddis_by_selection = applicable_ddis_by_selection_randomunique + applicable_ddis_by_selection_sequnique applicable_ddis = { z.name:z.name for z in applicable_ddis_by_refresh if z in applicable_ddis_by_selection } if len(applicable_ddis): self.step_flow_ddl_ddi.reset_items(applicable_ddis) self.step_flow_ddl_ddi.set_text(selected_step_flow_ddi) self.step_flow_ddl_ddi.show() if self.selected_step.flow_type == 'VARIABLELOOP': self.step_flow_varloop_start.show() self.step_flow_varloop_end.show() self.step_flow_varloop_start.set_text(selected_step_flow_miniter) self.step_flow_varloop_end.set_text(selected_step_flow_maxiter) if self.selected_step.flow_type == 'FIXEDLOOP': self.step_flow_fixloop.show() self.step_flow_fixloop.set_text(selected_step_flow_iter) if self.selected_step.flow_type == 'RESPONSE': orders = list(set([ z['order'] for z in self.selected_step.flow_items])) orders.sort() if len(orders): self.step_flow_response_table.show() table = [] for order in orders: destination = '' match = '' source = '' sleep = '' for item in self.selected_step.flow_items: if item['name'] == 'DESTINATIONSTEP' and item['order'] == order: try: destination = self.uj.find_step_by_id(int(item['value'])).name except ValueError: if item['value'] == 'NEXT_STEP': destination = 'Next Step' elif item['value'] == 'END_CYCLE': destination = 'End Cycle' else: destination = 'End User' if item['name'] == 'MATCHCRITERIA' and item['order'] == order: match = item['value'] if item['name'] == 'RESPONSESTEP' and item['order'] == order: source = self.uj.find_step_by_id(int(item['value'])).name if item['name'] == 'SLEEPTIME' and item['order'] == order: sleep = str(float(item['value'])/1000) table.append([{source: self.uj.list_step_name_id_pairs()}, match, {destination: steps}, sleep]) self.step_flow_response_table.set_text(table) if self.selected_step.flow_type == 'PERCENTAGE': orders = list(set([ z['order'] for z in self.selected_step.flow_items])) orders.sort() if len(orders): self.step_flow_percentage_table.show() table = [['100', {'Next Step': ['Next Step']}, '0.0']] extra_percentage = 0 for order in orders: destination = '' percentage = '' sleep = '' for item in self.selected_step.flow_items: if item['name'] == 'DESTINATIONSTEP' and item['order'] == order: destination = item['value'] if item['name'] == 'PERCENTAGE' and item['order'] == order: percentage = item['value'] extra_percentage += int(percentage) if item['name'] == 'SLEEPTIME' and item['order'] == order: sleep = str(float(item['value'])/1000) table.append([percentage, {destination: steps}, sleep]) table[0][0] = str(100 - extra_percentage) self.step_flow_percentage_table.set_text(table) if self.selected_step.flow_type == 'CONDTITIONAL': self.step_flow_conditional_true.show() self.step_flow_conditional_true.reset_items(steps) self.step_flow_conditional_true.set_text(selected_step_flow_conditional_true_target) self.step_flow_conditional_false.show() self.step_flow_conditional_false.reset_items(steps) self.step_flow_conditional_false.set_text(selected_step_flow_conditional_false_target) orders = list(set([ z['order'] for z in self.selected_step.flow_items])) orders.sort() if len(orders): self.step_flow_conditional_table.show() table = [] for order in orders: condition = '' phrase1 = '' operator = '' phrase2 = '' for item in self.selected_step.flow_items: if item['name'] == 'CONDITION' and item['order'] == order: conditions = {'less than': '<', 'less than or equals': '<=', 'equals': '=', 'not equals': '!=', 'greater than or equals': '>=', 'greater than': '>', 'contains': 'in', 'does not contain': 'not in',} condition = conditions[item['value']] if item['name'] == 'FIRSTPHRASE' and item['order'] == order: phrase1 = item['value'] if item['name'] == 'OPERATOR' and item['order'] == order: operator = item['value'] if item['name'] == 'SECONDPHRASE' and item['order'] == order: phrase2 = item['value'] table.append([phrase1, {condition: ['<', '<=', '=', '=>', '>', '!=', 'in', 'not in']}, phrase2, {operator: ['AND', 'OR']}]) self.step_flow_conditional_table.set_text(table)
class PythonConsoleWidget(QWidget, MooseWidget): """ Widget holding the input/output of a python console. Saves/restores history to preferences. This allows previous commands to be saved/restored. There is a global dict called "peacock" that allows saving arbitrary variables in. For example, peacock["your_variable"] could be any python variable. Signals: new_line: A new line of input. Argument is the input. """ new_line = pyqtSignal(str) def __init__(self, **kwds): super(PythonConsoleWidget, self).__init__(**kwds) self.top_layout = WidgetUtils.addLayout(vertical=True) self.setLayout(self.top_layout) self.output = QPlainTextEdit(parent=self) self.output.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) self.output.setReadOnly(False) self.output.setFocusPolicy(Qt.ClickFocus) self.output.setStyleSheet("QPlainTextEdit { background: black; color: white;}") self.output.setTextInteractionFlags(Qt.TextSelectableByMouse|Qt.TextSelectableByKeyboard|Qt.LinksAccessibleByMouse|Qt.LinksAccessibleByKeyboard) self.top_layout.addWidget(self.output) self.input_layout = WidgetUtils.addLayout() self.top_layout.addLayout(self.input_layout) self.prompt = WidgetUtils.addLabel(self.input_layout, self, ">>>") self.input_line = WidgetUtils.addLineEdit(self.input_layout, self, self._returnPressed) self.input_line.setFocusPolicy(Qt.StrongFocus) self.input_line.installEventFilter(self) self.user_inputs = [] self.current_index = -1 # get a list of globals and locals from the callstack self._global_data = {} self._global_data['global_vars'] = globals() self._global_data['peacock'] = {} self.console = QPythonConsole(self._global_data, parent=self) self.console.write_output.connect(self.output.appendPlainText) self.output.appendPlainText("Peaock variables are in the dict 'peacock'") self.output.appendPlainText("Global variables are in the dict 'global_vars'") self.console.prompt_changed.connect(self.prompt.setText) self.new_line.connect(self.console._newLine) self.console._setPrompt() self._loadHistory() self.resize(600, 400) self.setup() def _loadHistory(self): """ Loads previous commands from settings. """ settings = QSettings() history = settings.value("python/history", type=str) if history != None: for v in history: self.user_inputs.append(str(v)) self.current_index = len(self.user_inputs) def eventFilter(self, obj, event): """ Process QEvent Input: obj: The object that the event happened on event: QEvent() object Return: True if we processed this event. False otherwise. """ if obj == self.input_line: if event.type() == QEvent.KeyPress: if event.key() == Qt.Key_Up: self._changeInput(-1) return True elif event.key() == Qt.Key_Down: self._changeInput(1) return True elif event.key() == Qt.Key_Tab: # don't allow to tab out of the command line return True return False def saveHistory(self): """ Save history into settings. """ settings = QSettings() num_to_save = settings.value("python/history_size", type=int) if num_to_save == None: num_to_save = 50 settings.setValue("python/history_size", num_to_save) settings.setValue("python/history", self.user_inputs[-num_to_save:]) def _changeInput(self, change): """ Looks through the history and changes the input line. Input: change: int that specifies where in the list to change to """ self.current_index += change if self.current_index < 0: self.current_index = 0 elif self.current_index >= len(self.user_inputs): self.current_index = len(self.user_inputs) if self.current_index >= 0 and self.current_index < len(self.user_inputs): self.input_line.setText(self.user_inputs[self.current_index ]) def setVariable(self, name, value): """ Put a variable into the global dict "peacock". Input: name: key value of the "peacock" dict value: The value """ self._global_data["peacock"][name] = value @pyqtSlot() def _returnPressed(self): """ The user pressed return so process the input line """ text = unicode(self.input_line.text()) self.input_line.setText("") self.new_line.emit(text) if text: self.user_inputs.append(text) self.current_index = len(self.user_inputs)
class MainWindow(QWidget): def __init__(self): super().__init__() self.running = False self.setWindowTitle('PySwicher v{}'.format(VERSION)) # Logging config self.log_textbox = QPlainTextEditLogger(self) logging.getLogger().addHandler(self.log_textbox) self.log_textbox.setFormatter(logging.Formatter('[%(asctime)s][%(levelname)s]: %(message)s')) self.log_textbox.setLevel(self.get_numeric_loglevel(options['log_level'])) self.log_to_file = False # System tray configuration self.tray_menu = QMenu(self) self.systemTrayIcon = QSystemTrayIcon() self.systemTrayIcon.setVisible(False) self.systemTrayIcon.setIcon(QtGui.QIcon('C:\\Users\\Admin\\Pictures\\tray_stop.jpg')) self.systemTrayIcon.activated.connect(self.sys_tray) self.exit_action = self.tray_menu.addAction('Exit') self.exit_action.triggered.connect(self.exit_app) self.systemTrayIcon.setContextMenu(self.tray_menu) self.click_tray_timer = QtCore.QTimer(self) # Fix for systemtray click trigger self.click_tray_timer.setSingleShot(True) self.click_tray_timer.timeout.connect(self.click_timeout) self.main_window_ui() self.starter() def set_log_to_file(self, state): logger = logging.getLogger(__name__) file = logging.FileHandler(HOME + '\\switcher.log') if state == QtCore.Qt.Checked: self.log_to_file = True file.setFormatter( logging.Formatter('%(filename)s[LINE:%(lineno)d]# %(levelname)-8s [%(asctime)s] %(message)s')) file.setLevel(self.get_numeric_loglevel(options['log_level'])) logger.addHandler(file) else: if 'file' in logger.handlers: logger.removeHandler(file) self.log_to_file = False def starter(self): if not self.running: self.running = True self.start_btn.setText('Stop switcher') self.systemTrayIcon.setIcon(QtGui.QIcon('C:\\Users\\Admin\\Pictures\\tray_stop.jpg')) start_app() elif self.running: self.running = False self.start_btn.setText('Start switcher') self.systemTrayIcon.setIcon(QtGui.QIcon('C:\\Users\\Admin\\Pictures\\tray_start.jpg')) stop_app() return def main_window_ui(self): grid = QGridLayout(self) self.setLayout(grid) grid.setSpacing(5) # Here goes options layout self.topleft = QFrame(self) self.topleft.setFrameShape(QFrame.StyledPanel) self.topleft_grid = QGridLayout(self) self.topleft.setLayout(self.topleft_grid) self.switch_comb_label = QLabel('Switch combination:') self.switch_comb_text = QLineEdit() self.switch_comb_text.setText(options['switch_combination']) self.hotkey_label = QLabel('Hotkey:') self.hotkey_comb_text = QLineEdit() self.hotkey_comb_text.setText(options['hotkey']) self.topleft_grid.addWidget(self.switch_comb_label, 0, 0) self.topleft_grid.addWidget(self.switch_comb_text, 1, 0) self.topleft_grid.addWidget(self.hotkey_label, 2, 0) self.topleft_grid.addWidget(self.hotkey_comb_text, 3, 0) grid.addWidget(self.topleft, 0, 0) self.topright = QFrame(self) self.topright.setFrameShape(QFrame.StyledPanel) self.topright_grid = QGridLayout(self) self.topright.setLayout(self.topright_grid) self.info_label = QLabel('===INFO===') self.info_label.setAlignment(QtCore.Qt.AlignHCenter) self.info_author = QLabel('Author: Kurashov Sergey') self.info_author.setAlignment(QtCore.Qt.AlignHCenter) self.info_contacts = QLabel('Contacts: [email protected]') self.info_contacts.setAlignment(QtCore.Qt.AlignHCenter) self.info_sourcecode = QLabel('<a href="https://github.com/shimielder/win_switcher">Sourcecode on GitHub</a>') self.info_sourcecode.setAlignment(QtCore.Qt.AlignHCenter) self.info_sourcecode.setOpenExternalLinks(True) self.topright_grid.addWidget(self.info_label, 0, 0) self.topright_grid.addWidget(self.info_author, 1, 0) self.topright_grid.addWidget(self.info_contacts, 2, 0) self.topright_grid.addWidget(self.info_sourcecode, 3, 0) grid.addWidget(self.topright, 0, 1) self.middle = QFrame(self) self.middle.setFrameShape(QFrame.StyledPanel) self.middle_grid = QGridLayout(self) self.middle.setLayout(self.middle_grid) self.dictionsries_label = QLabel('Dictionaries to switch:') self.dict_one = QPlainTextEdit() self.dict_one.clear() self.dict_one.appendPlainText(options['layouts'][0]) self.dict_two = QPlainTextEdit() self.dict_two.clear() self.dict_two.appendPlainText(options['layouts'][1]) self.middle_grid.addWidget(self.dictionsries_label, 0, 0, 1, 4) self.middle_grid.addWidget(self.dict_one, 1, 0, 1, 4) self.middle_grid.addWidget(self.dict_two, 2, 0, 1, 4) grid.addWidget(self.middle, 1, 0, 1, 2) self.bottom = QFrame(self) self.bottom.setFrameShape(QFrame.StyledPanel) self.bottom_grid = QGridLayout(self) self.bottom.setLayout(self.bottom_grid) self.loglevel_label = QLabel('Logging level:') self.loglevel_dropmenu = QComboBox(self) self.loglevel_dropmenu.addItems(LOGGING_LEVELS) self.loglevel_dropmenu.setCurrentIndex(LOGGING_LEVELS.index((options['log_level'].upper()))) self.loglevel_dropmenu.activated[str].connect(self.set_logginglevel) # self.log_to_file_label = QLabel('Check to save logs to file') self.log_to_file_chk = QCheckBox('Check to save logs to file') self.log_to_file_chk.stateChanged.connect(self.set_log_to_file) self.logging_output_label = QLabel('Logging output:') self.logging_output_label.setAlignment(QtCore.Qt.AlignHCenter) self.bottom_grid.addWidget(self.loglevel_label, 0, 0) self.bottom_grid.addWidget(self.loglevel_dropmenu, 0, 1) self.bottom_grid.addWidget(self.log_to_file_chk, 0, 3, 1, 1) self.bottom_grid.addWidget(self.logging_output_label, 1, 0, 1, 4) self.bottom_grid.addWidget(self.log_textbox.widget, 2, 0, 2, 4) grid.addWidget(self.bottom, 2, 0, 1, 2) self.bottom_buttons = QFrame(self) # self.bottom_buttons.setFrameShape(QFrame.StyledPanel) self.bottom_buttons_grid = QGridLayout(self) self.bottom_buttons.setLayout(self.bottom_buttons_grid) self.start_btn = QPushButton('Start switcher') self.start_btn.clicked.connect(self.starter) self.apply_btn = QPushButton('Apply changes') self.apply_btn.clicked.connect(self.apply) self.exit_btn = QPushButton('Exit app') self.exit_btn.clicked.connect(self.exit_app) self.bottom_buttons_grid.addWidget(self.start_btn, 0, 0) self.bottom_buttons_grid.addWidget(self.apply_btn, 0, 1) self.bottom_buttons_grid.addWidget(self.exit_btn, 0, 2) grid.addWidget(self.bottom_buttons, 3, 0, 1, 2) self.resize(480, 320) self.show() def get_numeric_loglevel(self, loglevel): numeric_level = getattr(logging, loglevel.upper(), None) if not isinstance(numeric_level, int): numeric_level = 0 return numeric_level def set_logginglevel(self, loglevel): return self.log_textbox.setLevel(self.get_numeric_loglevel(loglevel)) @QtCore.pyqtSlot(QSystemTrayIcon.ActivationReason) def sys_tray(self, reason): """ По-умолчанию, trigger срабатывает всегда. Для обхода этого я повесил таймер на событие. Взято отсюда: https://riverbankcomputing.com/pipermail/pyqt/2010-November/028394.html """ if reason == QSystemTrayIcon.Trigger: self.click_tray_timer.start(QApplication.doubleClickInterval()) elif reason == QSystemTrayIcon.DoubleClick: self.click_tray_timer.stop() if self.isHidden(): self.showNormal() self.systemTrayIcon.setVisible(False) def click_timeout(self): self.starter() def apply(self): self.starter() options['layouts'] = [] options['layouts'].append(self.dict_one.toPlainText()) options['layouts'].append(self.dict_two.toPlainText()) options['log_level'] = LOGGING_LEVELS[self.loglevel_dropmenu.currentIndex()] self.set_logginglevel(options['log_level']) options['switch_combination'] = self.switch_comb_text.text() options['hotkey'] = self.hotkey_comb_text.text() logging.debug('Options from GUI: {}'.format(options)) save_to(options) self.starter() return options def exit_app(self): if self.running: self.starter() self.systemTrayIcon.setVisible(False) self.destroy() def closeEvent(self, event): self.exit_app() def changeEvent(self, event): if event.type() == QtCore.QEvent.WindowStateChange: if self.windowState() & QtCore.Qt.WindowMinimized: event.ignore() self.hide() self.systemTrayIcon.setVisible(True) self.systemTrayIcon.showMessage('', 'Running in the background.') super(MainWindow, self).changeEvent(event)
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 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 SubscriberWindow(QDialog): WINDOW_NAME_PREFIX = 'Subscriber' def __init__(self, parent, node, active_data_type_detector): super(SubscriberWindow, self).__init__(parent) self.setWindowTitle(self.WINDOW_NAME_PREFIX) self.setAttribute(Qt.WA_DeleteOnClose) # This is required to stop background timers! self._node = node self._active_data_type_detector = active_data_type_detector self._active_data_type_detector.message_types_updated.connect(self._update_data_type_list) self._message_queue = queue.Queue() self._subscriber_handle = None self._update_timer = QTimer(self) self._update_timer.setSingleShot(False) self._update_timer.timeout.connect(self._do_redraw) self._update_timer.start(100) self._log_viewer = QPlainTextEdit(self) self._log_viewer.setReadOnly(True) self._log_viewer.setLineWrapMode(QPlainTextEdit.NoWrap) self._log_viewer.setFont(get_monospace_font()) self._log_viewer.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOn) try: self._log_viewer.setPlaceholderText('Received messages will be printed here in YAML format') except AttributeError: # Old PyQt pass self._num_rows_spinbox = QSpinBox(self) self._num_rows_spinbox.setToolTip('Number of rows to display; large number will impair performance') self._num_rows_spinbox.valueChanged.connect( lambda: self._log_viewer.setMaximumBlockCount(self._num_rows_spinbox.value())) self._num_rows_spinbox.setMinimum(1) self._num_rows_spinbox.setMaximum(1000000) self._num_rows_spinbox.setValue(100) self._num_errors = 0 self._num_messages_total = 0 self._num_messages_past_filter = 0 self._msgs_per_sec_estimator = RateEstimator() self._num_messages_total_label = QuantityDisplay(self, 'Total', 'msgs') self._num_messages_past_filter_label = QuantityDisplay(self, 'Accepted', 'msgs') self._msgs_per_sec_label = QuantityDisplay(self, 'Accepting', 'msg/sec') self._type_selector = CommitableComboBoxWithHistory(self) self._type_selector.setToolTip('Name of the message type to subscribe to') self._type_selector.setInsertPolicy(QComboBox.NoInsert) completer = QCompleter(self._type_selector) completer.setCaseSensitivity(Qt.CaseSensitive) completer.setModel(self._type_selector.model()) self._type_selector.setCompleter(completer) self._type_selector.on_commit = self._do_start self._type_selector.setFont(get_monospace_font()) self._type_selector.setSizeAdjustPolicy(QComboBox.AdjustToContents) self._type_selector.setFocus(Qt.OtherFocusReason) self._active_filter = None self._filter_bar = FilterBar(self) self._filter_bar.on_filter = self._install_filter self._start_stop_button = make_icon_button('video-camera', 'Begin subscription', self, checkable=True, on_clicked=self._toggle_start_stop) self._pause_button = make_icon_button('pause', 'Pause updates, non-displayed messages will be queued in memory', self, checkable=True) self._clear_button = make_icon_button('trash-o', 'Clear output and reset stat counters', self, on_clicked=self._do_clear) self._show_all_message_types = make_icon_button('puzzle-piece', 'Show all known message types, not only those that are ' 'currently being exchanged over the bus', self, checkable=True, on_clicked=self._update_data_type_list) layout = QVBoxLayout(self) controls_layout = QHBoxLayout(self) controls_layout.addWidget(self._start_stop_button) controls_layout.addWidget(self._pause_button) controls_layout.addWidget(self._clear_button) controls_layout.addWidget(self._filter_bar.add_filter_button) controls_layout.addWidget(self._show_all_message_types) controls_layout.addWidget(self._type_selector, 1) controls_layout.addWidget(self._num_rows_spinbox) layout.addLayout(controls_layout) layout.addWidget(self._filter_bar) layout.addWidget(self._log_viewer, 1) stats_layout = QHBoxLayout(self) stats_layout.addWidget(self._num_messages_total_label) stats_layout.addWidget(self._num_messages_past_filter_label) stats_layout.addWidget(self._msgs_per_sec_label) layout.addLayout(stats_layout) self.setLayout(layout) # Initial updates self._update_data_type_list() def _install_filter(self, f): self._active_filter = f def _apply_filter(self, yaml_message): """This function will throw if the filter expression is malformed!""" if self._active_filter is None: return True return self._active_filter.match(yaml_message) def _on_message(self, e): # Global statistics self._num_messages_total += 1 # Rendering and filtering try: text = uavcan.to_yaml(e) if not self._apply_filter(text): return except Exception as ex: self._num_errors += 1 text = '!!! [%d] MESSAGE PROCESSING FAILED: %s' % (self._num_errors, ex) else: self._num_messages_past_filter += 1 self._msgs_per_sec_estimator.register_event(e.transfer.ts_monotonic) # Sending the text for later rendering try: self._message_queue.put_nowait(text) except queue.Full: pass def _toggle_start_stop(self): try: if self._subscriber_handle is None: self._do_start() else: self._do_stop() finally: self._start_stop_button.setChecked(self._subscriber_handle is not None) def _do_stop(self): if self._subscriber_handle is not None: self._subscriber_handle.remove() self._subscriber_handle = None self._pause_button.setChecked(False) self.setWindowTitle(self.WINDOW_NAME_PREFIX) def _do_start(self): self._do_stop() self._do_clear() try: selected_type = self._type_selector.currentText().strip() if not selected_type: return data_type = uavcan.TYPENAMES[selected_type] except Exception as ex: show_error('Subscription error', 'Could not load requested data type', ex, self) return try: self._subscriber_handle = self._node.add_handler(data_type, self._on_message) except Exception as ex: show_error('Subscription error', 'Could not create requested subscription', ex, self) return self.setWindowTitle('%s [%s]' % (self.WINDOW_NAME_PREFIX, selected_type)) self._start_stop_button.setChecked(True) def _do_redraw(self): self._num_messages_total_label.set(self._num_messages_total) self._num_messages_past_filter_label.set(self._num_messages_past_filter) estimated_rate = self._msgs_per_sec_estimator.get_rate_with_timestamp() self._msgs_per_sec_label.set('N/A' if estimated_rate is None else ('%.0f' % estimated_rate[0])) if self._pause_button.isChecked(): return self._log_viewer.setUpdatesEnabled(False) while True: try: text = self._message_queue.get_nowait() except queue.Empty: break else: self._log_viewer.appendPlainText(text + '\n') self._log_viewer.setUpdatesEnabled(True) def _update_data_type_list(self): logger.info('Updating data type list') if self._show_all_message_types.isChecked(): items = self._active_data_type_detector.get_names_of_all_message_types_with_data_type_id() else: items = self._active_data_type_detector.get_names_of_active_messages() self._type_selector.clear() self._type_selector.addItems(items) def _do_clear(self): self._num_messages_total = 0 self._num_messages_past_filter = 0 self._do_redraw() self._log_viewer.clear() def closeEvent(self, qcloseevent): try: self._subscriber_handle.close() except Exception: pass super(SubscriberWindow, self).closeEvent(qcloseevent) @staticmethod def spawn(parent, node, active_data_type_detector): SubscriberWindow(parent, node, active_data_type_detector).show()