class ExecuteWidget(QWidget): def __init__(self): QWidget.__init__(self) self.ctrl = QApplication.instance().ctrl self.ctrl.switch_language.connect(self.on_switch_language) self.ctrl.switch_configuration.connect(self.on_switch_configuration) self.paras = self.ctrl.paras self.conf = GuiConf() self.setWindowTitle(_("Execute %s") % self.paras.configuration_name()) self.executor_thread = None self.splitter_event_moved = False self.splitter_title_moved = False self.init_ui() self.show() def init_ui(self): vbox = QVBoxLayout() self.splitter_title = QSplitter(Qt.Vertical) self.splitter_event = QSplitter(Qt.Vertical) self.splitter_title.splitterMoved.connect(self.on_splitter_title_moved) self.splitter_event.splitterMoved.connect(self.on_splitter_event_moved) self.lbl_events_title1 = QLabel(_("Main events")) self.splitter_title.addWidget(self.lbl_events_title1) self.lbl_events_title2 = QLabel(_("Resources")) self.splitter_title.addWidget(self.lbl_events_title2) self.lbl_events_title3 = QLabel(_("Errors")) self.splitter_title.addWidget(self.lbl_events_title3) self.pte_events1 = QTextBrowser() self.pte_events1.setOpenExternalLinks(True) self.pte_events1.setOpenLinks(False) self.pte_events1.anchorClicked.connect(self.on_anchor_clicked) self.pte_events1.setLineWrapMode(QTextEdit.NoWrap) self.splitter_event.addWidget(self.pte_events1) self.pte_events2 = QTextBrowser() self.pte_events2.setOpenExternalLinks(True) self.pte_events2.setOpenLinks(False) self.pte_events2.anchorClicked.connect(self.on_anchor_clicked) self.pte_events2.setLineWrapMode(QTextEdit.NoWrap) self.splitter_event.addWidget(self.pte_events2) self.pte_events3 = QPlainTextEdit() self.pte_events3.setReadOnly(True) self.pte_events3.setLineWrapMode(QPlainTextEdit.NoWrap) self.pte_events3.setStyleSheet(Style.red_text()) self.pte_events3.setCenterOnScroll(True) self.splitter_event.addWidget(self.pte_events3) self.splitter_title.setStretchFactor(0, 5) self.splitter_title.setStretchFactor(1, 3) self.splitter_title.setStretchFactor(2, 1) self.splitter_event.setStretchFactor(0, 5) self.splitter_event.setStretchFactor(1, 3) self.splitter_event.setStretchFactor(2, 1) hbox_splitters = QHBoxLayout() hbox_splitters.addWidget(self.splitter_title, 0) hbox_splitters.addWidget(self.splitter_event, 5) vbox.addLayout(hbox_splitters) lbl_box = QHBoxLayout() self.lbl_processing = QLabel(_("Processing:")) self.lbl_processing_file = QLabel("") self.lbl_processing.setVisible(False) self.lbl_processing_file.setVisible(False) lbl_box.addWidget(self.lbl_processing) lbl_box.addWidget(self.lbl_processing_file) lbl_box.addStretch(1) vbox.addLayout(lbl_box) btn_box = QHBoxLayout() btn_box.addStretch(1) self.chk_trial_run = QCheckBox(_("Trial run")) self.chk_trial_run.setChecked(not self.paras.is_saving_sitemaps) btn_box.addWidget(self.chk_trial_run) self.btn_run = QPushButton(_("Run")) self.btn_run.clicked.connect(self.on_btn_run_clicked) btn_box.addWidget(self.btn_run) self.btn_stop = QPushButton(_("Stop")) self.btn_stop.clicked.connect(self.on_btn_stop_clicked) self.normal_style = self.btn_stop.styleSheet() self.btn_stop.setEnabled(False) btn_box.addWidget(self.btn_stop) self.btn_close = QPushButton(_("Close")) self.btn_close.clicked.connect(self.on_btn_close_clicked) btn_box.addWidget(self.btn_close) vbox.addLayout(btn_box) self.setLayout(vbox) self.resize(self.conf.execute_widget_width(), self.conf.execute_widget_height()) def on_splitter_title_moved(self, pos, index): self.splitter_title_moved = True if not self.splitter_event_moved: self.splitter_event.moveSplitter(pos, index) self.splitter_title_moved = False def on_splitter_event_moved(self, pos, index): self.splitter_event_moved = True if not self.splitter_title_moved: self.splitter_title.moveSplitter(pos, index) self.splitter_event_moved = False def on_switch_language(self): self.setWindowTitle(_("Execute %s") % self.paras.configuration_name()) self.lbl_events_title1.setText(_("Main events")) self.lbl_events_title2.setText(_("Resources")) self.lbl_events_title3.setText(_("Errors")) self.lbl_processing.setText(_("Processing:")) self.chk_trial_run.setText(_("Trial run")) self.btn_run.setText(_("Run")) self.btn_stop.setText(_("Stop")) self.btn_close.setText(_("Close")) def on_switch_configuration(self, name=None): LOG.debug("Switch configuration: %s" % name) self.paras = self.ctrl.paras self.setWindowTitle(_("Execute %s") % self.paras.configuration_name()) self.chk_trial_run.setChecked(not self.paras.is_saving_sitemaps) def on_btn_run_clicked(self): if self.paras.select_mode == SelectMode.simple: selector = Selector() if self.paras.simple_select_file: selector.include(self.paras.simple_select_file) else: selector = self.ctrl.selector self.paras.is_saving_sitemaps = not self.chk_trial_run.isChecked() self.pte_events1.setPlainText("") self.pte_events2.setPlainText("") self.pte_events3.setPlainText("") self.lbl_processing.setVisible(True) self.lbl_processing_file.setVisible(True) self.btn_close.setEnabled(False) self.btn_run.setEnabled(False) self.chk_trial_run.setEnabled(False) self.btn_stop.setEnabled(True) self.btn_stop.setStyleSheet(Style.alarm()) self.executor_thread = ExecutorThread(self.paras, selector, self) self.executor_thread.signal_exception.connect(self.on_signal_exception) self.executor_thread.ask_confirmation.connect(self.on_ask_confirmation) self.executor_thread.signal_main_event.connect( self.on_signal_main_event) self.executor_thread.signal_minor_event.connect( self.on_signal_minor_event) self.executor_thread.signal_next_file.connect(self.on_signal_next_file) self.executor_thread.signal_end_processing.connect( self.on_signal_end_processing) self.executor_thread.finished.connect(self.on_executor_thread_finished) self.executor_thread.start() self.update() def on_btn_stop_clicked(self): self.btn_stop.setStyleSheet(self.normal_style) self.btn_stop.setEnabled(False) self.executor_thread.requestInterruption() def on_signal_exception(self, msg): self.pte_events3.appendHtml(msg) self.update() def on_ask_confirmation(self, text, i_text, answer): msg_box = QMessageBox() msg_box.setText(text) i_text += "\n\n" i_text += _("Ok to proceed?") msg_box.setInformativeText(i_text) msg_box.setIcon(QMessageBox.Question) msg_box.setStandardButtons(QMessageBox.No | QMessageBox.Yes) msg_box.setDefaultButton(QMessageBox.Yes) exe = msg_box.exec() if exe == QMessageBox.No: answer.answer = False else: answer.answer = True answer.answered = True def on_signal_main_event(self, msg): self.pte_events1.append(msg) self.update() def on_signal_minor_event(self, msg): self.pte_events2.append(msg) self.update() def on_signal_next_file(self, filename): lfn = len(filename) ww = (self.width() - 150) / 7 www = int(ww / 2) if lfn > ww: filename = filename[:www] + "..." + filename[lfn - www:] self.lbl_processing_file.setText(filename) self.update() def on_signal_end_processing(self, paras): self.ctrl.update_configuration(paras) def on_executor_thread_finished(self): self.btn_stop.setStyleSheet(self.normal_style) self.btn_stop.setEnabled(False) self.btn_close.setEnabled(True) self.btn_run.setEnabled(True) self.chk_trial_run.setEnabled(True) self.lbl_processing.setVisible(False) self.lbl_processing_file.setVisible(False) self.update() def on_anchor_clicked(self, url): QDesktopServices.openUrl(QUrl(url)) def on_btn_close_clicked(self): if self.windowState() & Qt.WindowFullScreen: self.setWindowState(Qt.WindowMaximized) else: self.close() def closeEvent(self, event): if self.executor_thread: self.executor_thread.requestInterruption() if self.windowState() & Qt.WindowFullScreen: self.setWindowState(Qt.WindowMaximized) event.ignore() else: self.conf.set_execute_widget_width(self.width()) self.conf.set_execute_widget_height(self.height()) self.conf.persist() event.accept()
class WorkWidget(QWidget): work_started = pyqtSignal() work_ended = pyqtSignal() def __init__(self, work="", title_style=Style.h2()): QWidget.__init__(self) self.ctrl = QApplication.instance().ctrl self.ctrl.switch_language.connect(self.on_switch_language) self.ctrl.switch_configuration.connect(self.on_switch_configuration) self.paras = self.ctrl.paras self.conf = GuiConf() # work should be a verb: Execute, Transport ... self.work = work self.title_style = title_style self.setWindowTitle(_(self.work)) self.executor_thread = None self.splitter_event_moved = False self.splitter_title_moved = False self.init_ui() self.show() def init_ui(self): vbox = QVBoxLayout() self.label_title = QLabel("%s %s" % (_(self.work), self.paras.configuration_name())) font = QFont() font.setPointSize(18) font.setBold(True) self.label_title.setFont(font) self.label_title.setContentsMargins(10, 5, 5, 7) self.label_title.setStyleSheet(self.title_style) hbox1 = QHBoxLayout() hbox1.addWidget(self.label_title, 1) vbox.addLayout(hbox1) self.splitter_title = QSplitter(Qt.Vertical) self.splitter_event = QSplitter(Qt.Vertical) self.splitter_title.splitterMoved.connect(self.on_splitter_title_moved) self.splitter_event.splitterMoved.connect(self.on_splitter_event_moved) self.lbl_events_title1 = QLabel(_("Main events")) self.splitter_title.addWidget(self.lbl_events_title1) self.lbl_events_title2 = QLabel(_("Resources")) self.splitter_title.addWidget(self.lbl_events_title2) self.lbl_events_title3 = QLabel(_("Errors")) self.splitter_title.addWidget(self.lbl_events_title3) self.pte_events1 = QTextBrowser() self.pte_events1.setOpenExternalLinks(True) self.pte_events1.setOpenLinks(False) self.pte_events1.anchorClicked.connect(self.on_anchor_clicked) self.pte_events1.setLineWrapMode(QTextEdit.NoWrap) self.splitter_event.addWidget(self.pte_events1) self.pte_events2 = QTextBrowser() self.pte_events2.setOpenExternalLinks(True) self.pte_events2.setOpenLinks(False) self.pte_events2.anchorClicked.connect(self.on_anchor_clicked) self.pte_events2.setLineWrapMode(QTextEdit.NoWrap) self.splitter_event.addWidget(self.pte_events2) self.pte_events3 = QPlainTextEdit() self.pte_events3.setReadOnly(True) self.pte_events3.setLineWrapMode(QPlainTextEdit.NoWrap) self.pte_events3.setStyleSheet(Style.red_text()) self.pte_events3.setCenterOnScroll(True) self.splitter_event.addWidget(self.pte_events3) self.splitter_title.setStretchFactor(0, 5) self.splitter_title.setStretchFactor(1, 3) self.splitter_title.setStretchFactor(2, 1) self.splitter_event.setStretchFactor(0, 5) self.splitter_event.setStretchFactor(1, 3) self.splitter_event.setStretchFactor(2, 1) hbox_splitters = QHBoxLayout() hbox_splitters.addWidget(self.splitter_title, 0) hbox_splitters.addWidget(self.splitter_event, 5) vbox.addLayout(hbox_splitters) lbl_box = QHBoxLayout() self.lbl_processing = QLabel(_("Processing:")) self.lbl_processing_file = QLabel("") font = QFontDatabase.systemFont(QFontDatabase.FixedFont) self.lbl_processing_file.setFont(font) self.lbl_processing.setFont(font) self.lbl_processing.setVisible(False) self.lbl_processing_file.setVisible(False) lbl_box.addWidget(self.lbl_processing) lbl_box.addWidget(self.lbl_processing_file) lbl_box.addStretch(1) vbox.addLayout(lbl_box) btn_box = QHBoxLayout() btn_box.addStretch(1) self.chk_trial_run = QCheckBox(_("Trial run")) self.chk_trial_run.setChecked(not self.paras.is_saving_sitemaps) btn_box.addWidget(self.chk_trial_run) self.btn_run = QPushButton(_("Run")) self.btn_run.clicked.connect(self.on_btn_run_clicked) btn_box.addWidget(self.btn_run) self.btn_stop = QPushButton(_("Stop")) self.btn_stop.clicked.connect(self.on_btn_stop_clicked) self.normal_style = self.btn_stop.styleSheet() self.btn_stop.setEnabled(False) btn_box.addWidget(self.btn_stop) self.btn_close = QPushButton(_("Close")) self.btn_close.clicked.connect(self.on_btn_close_clicked) btn_box.addWidget(self.btn_close) vbox.addLayout(btn_box) self.setLayout(vbox) self.resize(self.conf.work_widget_width(self.work), self.conf.work_widget_height(self.work)) def on_splitter_title_moved(self, pos, index): self.splitter_title_moved = True if not self.splitter_event_moved: self.splitter_event.moveSplitter(pos, index) self.splitter_title_moved = False def on_splitter_event_moved(self, pos, index): self.splitter_event_moved = True if not self.splitter_title_moved: self.splitter_title.moveSplitter(pos, index) self.splitter_event_moved = False def on_switch_language(self): self.setWindowTitle(_(self.work)) self.label_title.setText("%s %s" % (_(self.work), self.paras.configuration_name())) self.lbl_events_title1.setText(_("Main events")) self.lbl_events_title2.setText(_("Resources")) self.lbl_events_title3.setText(_("Errors")) self.lbl_processing.setText(_("Processing:")) self.chk_trial_run.setText(_("Trial run")) self.btn_run.setText(_("Run")) self.btn_stop.setText(_("Stop")) self.btn_close.setText(_("Close")) def on_switch_configuration(self, name=None): LOG.debug("Switch configuration: %s" % name) self.paras = self.ctrl.paras self.label_title.setText("%s %s" % (_(self.work), self.paras.configuration_name())) def on_anchor_clicked(self, url): QDesktopServices.openUrl(QUrl(url)) def on_btn_run_clicked(self): self.work_started.emit() self.pte_events1.setPlainText("") self.pte_events2.setPlainText("") self.pte_events3.setPlainText("") self.lbl_processing.setVisible(True) self.lbl_processing_file.setVisible(True) self.btn_close.setEnabled(False) self.btn_run.setEnabled(False) self.chk_trial_run.setEnabled(False) self.btn_stop.setEnabled(True) self.btn_stop.setStyleSheet(Style.alarm()) def on_btn_stop_clicked(self): self.btn_stop.setStyleSheet(self.normal_style) self.btn_stop.setEnabled(False) self.on_signal_main_event(_("Interrupt requested...")) if self.executor_thread: self.executor_thread.requestInterruption() def on_signal_exception(self, msg): self.pte_events3.appendHtml(msg) self.update() def on_ask_confirmation(self, text, i_text, answer): msg_box = QMessageBox() msg_box.setWindowTitle(_("MPT")) msg_box.setText(text) i_text += "\n\n" i_text += _("Ok to proceed?") msg_box.setInformativeText(i_text) msg_box.setIcon(QMessageBox.Question) msg_box.setStandardButtons(QMessageBox.No | QMessageBox.Yes) msg_box.setDefaultButton(QMessageBox.Yes) exe = msg_box.exec() if exe == QMessageBox.No: answer.answer = False else: answer.answer = True answer.answered = True def on_signal_main_event(self, msg): self.pte_events1.append(msg) self.update() def on_signal_minor_event(self, msg): self.pte_events2.append(msg) self.update() def on_signal_next_file(self, filename): lfn = len(filename) ww = (self.width() - 150)/7 www = int(ww/2) if lfn > ww: filename = filename[:www] + "..." + filename[lfn - www:] self.lbl_processing_file.setText(filename) self.update() def on_signal_end_processing(self, paras): self.ctrl.update_configuration(paras) def on_executor_thread_finished(self): self.btn_stop.setStyleSheet(self.normal_style) self.btn_stop.setEnabled(False) self.btn_close.setEnabled(True) self.btn_run.setEnabled(True) self.chk_trial_run.setEnabled(True) self.lbl_processing.setVisible(False) self.lbl_processing_file.setVisible(False) self.update() self.work_ended.emit() def on_btn_close_clicked(self): if self.windowState() & Qt.WindowFullScreen: self.setWindowState(Qt.WindowMaximized) else: self.close() self.destroy() def closeEvent(self, event): LOG.debug("Closing event on work window %s" % self.work) if self.executor_thread: self.executor_thread.requestInterruption() if self.windowState() & Qt.WindowFullScreen: self.setWindowState(Qt.WindowMaximized) event.ignore() else: self.save_dimensions() self.exit_if_last() event.accept() def save_dimensions(self): LOG.debug("Saving dimensions for work-window %s" % self.work) self.conf.set_work_widget_width(self.work, self.width()) self.conf.set_work_widget_height(self.work, self.height()) self.conf.persist() def exit_if_last(self): count_windows = 0 for window in QApplication.instance().topLevelWindows(): if window.type() == 1 or window.type() == 15: count_windows += 1 LOG.debug("Testing for last window. window_count=%d" % count_windows) if count_windows == 1: LOG.debug("Closing last window") QApplication.instance().quit()