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() self.show() def start(self): # Create a runner self.runner = SubProcessWorker("python dummy_script.py") self.runner.signals.result.connect(self.result) self.threadpool.start(self.runner) def result(self, s): self.text.appendPlainText(s)
class QLogsWindow(QDialog): appendLogSignal = Signal(str) vbox: QVBoxLayout textbox: QPlainTextEdit clear_button: QPushButton _logging_handler: typing.Optional[HookableInMemoryHandler] def __init__(self): super().__init__() self.setWindowTitle("Logs") self.setMinimumSize(400, 100) self.resize(1000, 450) self.setWindowIcon(QIcon("./resources/icon.png")) self.vbox = QVBoxLayout() self.setLayout(self.vbox) self.textbox = QPlainTextEdit(self) self.textbox.setReadOnly(True) self.textbox.setLineWrapMode(QPlainTextEdit.LineWrapMode.NoWrap) self.textbox.move(10, 10) self.textbox.resize(1000, 450) self.textbox.setStyleSheet( "font-family: 'Courier New', monospace; background: #1D2731;") self.vbox.addWidget(self.textbox) self.clear_button = QPushButton(self) self.clear_button.setText("CLEAR") self.clear_button.setProperty("style", "btn-primary") self.clear_button.clicked.connect(self.clearLogs) self.vbox.addWidget(self.clear_button) self.appendLogSignal.connect(self.appendLog) self._logging_handler = None logger = logging.getLogger() for handler in logger.handlers: if isinstance(handler, HookableInMemoryHandler): self._logging_handler = handler break if self._logging_handler is not None: self.textbox.setPlainText(self._logging_handler.log) self.textbox.moveCursor(QTextCursor.End) # The Handler might be called from a different thread, # so use signal/slot to properly handle the event in the main thread. # https://github.com/dcs-liberation/dcs_liberation/issues/1493 self._logging_handler.setHook(self.appendLogSignal.emit) else: self.textbox.setPlainText("WARNING: logging not initialized!") def clearLogs(self) -> None: if self._logging_handler is not None: self._logging_handler.clearLog() self.textbox.setPlainText("") def appendLog(self, msg: str): self.textbox.appendPlainText(msg) self.textbox.moveCursor(QTextCursor.End)
class QTextEditLogger(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 MainWindow(QMainWindow): def __init__(self): super().__init__() self.urls = [ "https://www.learnpyqt.com/", "https://www.mfitzp.com/", "https://www.google.com", "https://www.udemy.com/create-simple-gui-applications-with-python-and-qt/", ] # tag::init[] self.parsers = { # <1> # Regular expression parsers, to extract data from the HTML. "title": re.compile(r"<title.*?>(.*?)<\/title>", re.M | re.S), "h1": re.compile(r"<h1.*?>(.*?)<\/h1>", re.M | re.S), "h2": re.compile(r"<h2.*?>(.*?)<\/h2>", re.M | re.S), } # end::init[] layout = QVBoxLayout() self.text = QPlainTextEdit() self.text.setReadOnly(True) button = QPushButton("GO GET EM!") button.pressed.connect(self.execute) layout.addWidget(self.text) layout.addWidget(button) w = QWidget() w.setLayout(layout) self.setCentralWidget(w) self.show() self.threadpool = QThreadPool() print("Multithreading with maximum %d threads" % self.threadpool.maxThreadCount()) # tag::execute[] def execute(self): for n, url in enumerate(self.urls): worker = Worker(n, url, self.parsers) # <1> worker.signals.data.connect(self.display_output) # Execute self.threadpool.start(worker) # end::execute[] def display_output(self, data): id, s = data self.text.appendPlainText("WORKER %d: %s" % (id, s))
class MainWindow(QMainWindow): def __init__(self): super().__init__() # Hold process reference. self.p = None layout = QVBoxLayout() self.text = QPlainTextEdit() layout.addWidget(self.text) self.progress = QProgressBar() layout.addWidget(self.progress) btn_run = QPushButton("Execute") btn_run.clicked.connect(self.start) layout.addWidget(btn_run) w = QWidget() w.setLayout(layout) self.setCentralWidget(w) self.show() def start(self): if self.p is not None: return self.p = QProcess() 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.start("python", ["dummy_script.py"]) def handle_stderr(self): result = bytes(self.p.readAllStandardError()).decode("utf8") progress = simple_percent_parser(result) self.progress.setValue(progress) def handle_stdout(self): result = bytes(self.p.readAllStandardOutput()).decode("utf8") data = extract_vars(result) self.text.appendPlainText(str(data)) def handle_state(self, state): self.statusBar().showMessage(STATES[state]) def cleanup(self): self.p = None
class Log(QWidget): def __init__(self, sender, title=''): super(Log, self).__init__() self.main_layout = QVBoxLayout() self.header_layout = QHBoxLayout() title_label = QLabel(title) title_label.setFont(QFont('Poppins', 13)) self.header_layout.addWidget(title_label) holder_label = QLabel(str(sender)) holder_label.setWordWrap(True) self.log_view = QPlainTextEdit() self.log_view.setReadOnly(True) self.main_layout.addLayout(self.header_layout) self.main_layout.addWidget(holder_label) self.main_layout.addWidget(self.log_view) self.setLayout(self.main_layout) self.setStyleSheet(''' QLabel { border: None; } QWidget { color: #e9f4fb; } ''') def log(self, *args): s = '' for arg in args: s += ' ' + str(arg) self.log_view.appendPlainText('> ' + s) def clear(self): self.log_view.clear() def removing(self): # old method, delete later self.remove() def remove(self): self.log_view.setStyleSheet('background: black; color: grey;') remove_button = QPushButton('x') remove_button.clicked.connect(self.remove_clicked) self.header_layout.addWidget(remove_button) def remove_clicked(self): self.setParent(None) # removes the widget
class MainWindow(QMainWindow): def __init__(self): super().__init__() self.workers = WorkerManager() self.workers.status.connect(self.statusBar().showMessage) layout = QVBoxLayout() self.progress = QListView() self.progress.setModel(self.workers) delegate = ProgressBarDelegate() self.progress.setItemDelegate(delegate) layout.addWidget(self.progress) self.text = QPlainTextEdit() self.text.setReadOnly(True) start = QPushButton("Start a worker") start.pressed.connect(self.start_worker) clear = QPushButton("Clear") clear.pressed.connect(self.workers.cleanup) layout.addWidget(self.text) layout.addWidget(start) layout.addWidget(clear) w = QWidget() w.setLayout(layout) self.setCentralWidget(w) self.show() # tag::startWorker[] def start_worker(self): x = random.randint(0, 1000) y = random.randint(0, 1000) w = Worker(x, y) w.signals.result.connect(self.display_result) w.signals.error.connect(self.display_result) self.workers.enqueue(w) # end::startWorker[] def display_result(self, job_id, data): self.text.appendPlainText("WORKER %s: %s" % (job_id, data))
class MainWindow(QMainWindow): def __init__(self): super().__init__() self.job = JobManager() self.job.status.connect(self.statusBar().showMessage) self.job.result.connect(self.display_result) layout = QVBoxLayout() self.progress = QListView() self.progress.setModel(self.job) delegate = ProgressBarDelegate() self.progress.setItemDelegate(delegate) layout.addWidget(self.progress) self.text = QPlainTextEdit() self.text.setReadOnly(True) button = QPushButton("Run a command") button.pressed.connect(self.run_command) clear = QPushButton("Clear") clear.pressed.connect(self.job.cleanup) layout.addWidget(self.text) layout.addWidget(button) layout.addWidget(clear) w = QWidget() w.setLayout(layout) self.setCentralWidget(w) self.show() # tag::startJob[] def run_command(self): self.job.execute( "python", ['dummy_script.py'], parsers=parsers(progress=simple_percent_parser, data=extract_vars), ) # end::startJob[] def display_result(self, job_id, data): self.text.appendPlainText("WORKER %s: %s" % (job_id, data))
class Log(Handler): def __init__(self, parent=None, width=150, height=150): super().__init__() self.widget = QPlainTextEdit(parent) self.widget.setPlainText("Placeholder log text\n") self.widget.resize(width, height) self.widget.setReadOnly(True) self.widget.setLineWrapMode(QPlainTextEdit.LineWrapMode.WidgetWidth) @Slot() @Slot(str) def addEntry(self, text='blo'): self.widget.appendPlainText(text) print('appending')
class MainWindow(QMainWindow): def __init__(self): super().__init__() self.urls = [ "https://www.learnpyqt.com/", "https://www.mfitzp.com/", "https://www.google.com", "https://www.udemy.com/create-simple-gui-applications-with-python-and-qt/", ] layout = QVBoxLayout() self.text = QPlainTextEdit() self.text.setReadOnly(True) button = QPushButton("GO GET EM!") button.pressed.connect(self.execute) layout.addWidget(self.text) layout.addWidget(button) w = QWidget() w.setLayout(layout) self.setCentralWidget(w) self.show() self.threadpool = QThreadPool() print("Multithreading with maximum %d threads" % self.threadpool.maxThreadCount()) def execute(self): for n, url in enumerate(self.urls): worker = Worker(n, url) worker.signals.data.connect(self.display_output) # Execute self.threadpool.start(worker) def display_output(self, data): id, s = data self.text.appendPlainText("WORKER %d: %s" % (id, s))
class MainWindow(QMainWindow): def __init__(self): super().__init__() layout = QVBoxLayout() self.text = QPlainTextEdit() layout.addWidget(self.text) self.progress = QProgressBar() self.progress.setRange(0, 100) self.progress.setValue(0) layout.addWidget(self.progress) 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() self.show() # tag::start[] def start(self): # Create a runner self.runner = SubProcessWorker( command="python dummy_script.py", parser=simple_percent_parser ) self.runner.signals.result.connect(self.result) self.runner.signals.progress.connect(self.progress.setValue) self.threadpool.start(self.runner) # end::start[] def result(self, s): self.text.appendPlainText(s)
class LoggerTextboxWidget(logging.Handler, QWidget): """The LoggerTextboxWidget class provides a textbox widget that can also work as a logging handler for the Python logging system. Examples: textbox_logger = LoggerTextboxWidget() logging.getLogger().addHandler(textbox_logger) """ def __init__(self, formatter: "logging.Formatter", parent: QWidget = None): logging.Handler.__init__(self) QWidget.__init__(self, parent) self.setFormatter(formatter) self._textbox = QPlainTextEdit(self) self._textbox.setReadOnly(True) layout = QVBoxLayout() layout.setContentsMargins(0, 0, 0, 0) layout.addWidget(self._textbox) self.setLayout(layout) @property def text(self) -> str: """Returns the text written on the textbox.""" return self._textbox.toPlainText() def set_plain_text(self, text: str): """Replaces the textbox content with `text`.""" self._textbox.setPlainText(text) def emit(self, record): """This method is called each time a logger emits a message. It applies the corresponding format and sends it to the textbox.""" msg = self.format(record) self._textbox.appendPlainText(msg)
class UserTab(QWidget): def __init__(self): QWidget.__init__(self) layout = QVBoxLayout(self) self.text = QPlainTextEdit() layout.addWidget(self.text) self.setLayout(layout) self.ds = DataSource() self.worker = UpdateUserWorker() self.worker_thread = QThread() self.worker_thread.started.connect(self.worker.run) self.worker.finished.connect(self.worker_thread.quit) self.worker.moveToThread(self.worker_thread) self.worker_thread.start() self.worker.processed.connect(self.processed) @Slot(dict) def processed(self, user): self.text.appendPlainText('USER: {}'.format(str(user))) def finish(self): self.worker.finish() self.worker_thread.quit() self.worker_thread.wait()
class RunTab(QtWidgets.QWidget): run_checks = QtCore.Signal() def __init__(self, prj: QAXProject): super(RunTab, self).__init__() self.prj = prj self.check_executor = None self.vbox = QtWidgets.QVBoxLayout() self.setLayout(self.vbox) self._add_check_outputs() self._add_process() # final setup self.set_run_stop_buttons_enabled(False) def _add_check_outputs(self): co_groupbox = QGroupBox("Check outputs") co_groupbox.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed) co_layout = QVBoxLayout() co_layout.setSpacing(16) co_groupbox.setLayout(co_layout) self.qajson_spatial_checkbox = QCheckBox( "Include summary spatial output in QAJSON. " "Supports QAX visualisation.") self.qajson_spatial_checkbox.setCheckState( QtCore.Qt.CheckState.Checked) co_layout.addWidget(self.qajson_spatial_checkbox) export_layout = QVBoxLayout() export_layout.setSpacing(4) self.export_spatial_checkbox = QCheckBox( "Export detailed spatial outputs to file. " "Supports visualisation in other geospatial applications.") self.export_spatial_checkbox.stateChanged.connect( self._on_export_spatial_changed) export_layout.addWidget(self.export_spatial_checkbox) output_folder_layout = QHBoxLayout() output_folder_layout.setSpacing(4) output_folder_layout.addSpacerItem(QtWidgets.QSpacerItem(37, 20)) self.output_folder_label = QLabel( "Detailed spatial output folder location:") output_folder_layout.addWidget(self.output_folder_label) self.output_folder_input = QLineEdit() self.output_folder_input.setText( GuiSettings.settings().value("spatial_outputs")) self.output_folder_input.setMinimumWidth(300) self.output_folder_input.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) output_folder_layout.addWidget(self.output_folder_input) self.open_output_folder_button = QPushButton() output_folder_layout.addWidget(self.open_output_folder_button) self.open_output_folder_button.setIcon(qta.icon('fa.folder-open')) self.open_output_folder_button.setToolTip( f"Select file containing data") self.open_output_folder_button.clicked.connect( self._click_open_spatial_export_folder) export_layout.addLayout(output_folder_layout) co_layout.addLayout(export_layout) self._on_export_spatial_changed() self.vbox.addWidget(co_groupbox) def _click_open_spatial_export_folder(self): output_folder = QFileDialog.getExistingDirectory( self, f"Select folder for spatial outputs", GuiSettings.settings().value("spatial_outputs"), QFileDialog.ShowDirsOnly) if os.path.exists(output_folder): GuiSettings.settings().setValue("spatial_outputs", output_folder) self.output_folder_input.setText(output_folder) def _on_export_spatial_changed(self): is_export = self.export_spatial_checkbox.isChecked() self.output_folder_label.setEnabled(is_export) self.output_folder_input.setEnabled(is_export) self.open_output_folder_button.setEnabled(is_export) def _add_process(self): process_groupbox = QGroupBox("Process") process_groupbox.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) process_layout = QVBoxLayout() process_layout.setSpacing(0) process_groupbox.setLayout(process_layout) pbar_frame = QFrame() pbar_frame.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed) pbar_hbox = QHBoxLayout() pbar_hbox.setContentsMargins(QtCore.QMargins(0, 0, 0, 16)) pbar_hbox.setSpacing(16) # Run and stop buttons hbox = QHBoxLayout() hbox.setSpacing(8) self.run_button = QPushButton() # is only enabled when validation passes self.run_button.setEnabled(False) self.run_button.setText("Run") self.run_button.setToolTip("Start check execution") self.run_button.setFixedWidth(100) run_icon = qta.icon('fa.play', color='green') self.run_button.setIcon(run_icon) self.run_button.clicked.connect(self._click_run) hbox.addWidget(self.run_button) self.stop_button = QPushButton() self.stop_button.setEnabled(False) self.stop_button.setText("Stop") self.stop_button.setToolTip("Stop check execution") self.stop_button.setFixedWidth(100) stop_icon = qta.icon('fa.stop', color='red') self.stop_button.setIcon(stop_icon) self.stop_button.clicked.connect(self._click_stop) hbox.addWidget(self.stop_button) self.progress_bar = QProgressBar() self.progress_bar.setTextVisible(True) self.progress_bar.setAlignment(QtCore.Qt.AlignCenter) self.progress_bar.setValue(0) self.progress_bar.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) pbar_hbox.addLayout(hbox) pbar_hbox.addWidget(self.progress_bar) pbar_frame.setLayout(pbar_hbox) process_layout.addWidget(pbar_frame) vbox = QVBoxLayout() vbox.setSpacing(8) vbox.setContentsMargins(QtCore.QMargins(0, 0, 0, 16)) process_layout.addLayout(vbox) hbox = QHBoxLayout() vbox.addLayout(hbox) check_name_label = QLabel("Check:") check_name_label.setFixedWidth(80) hbox.addWidget(check_name_label) self.check_name_text_label = QLabel("n/a") hbox.addWidget(self.check_name_text_label) hbox = QHBoxLayout() vbox.addLayout(hbox) status_name_label = QLabel("Status:") status_name_label.setFixedWidth(80) hbox.addWidget(status_name_label) self.status_name_text_label = QLabel("Not started") hbox.addWidget(self.status_name_text_label) self.warning_frame = QFrame() self.warning_frame.setVisible(False) self.warning_frame.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed) hbox = QHBoxLayout() warning_icon_widget = qta.IconWidget('fa.warning', color='red') warning_icon_widget.setIconSize(QtCore.QSize(48, 48)) warning_icon_widget.update() hbox.addWidget(warning_icon_widget) warning_label = QLabel( "Grid Transformer did not complete successfully. Please refer to " "log output.") warning_label.setStyleSheet("QLabel { color: red; }") warning_label.setWordWrap(True) warning_label.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Preferred) hbox.addWidget(warning_label) self.warning_frame.setLayout(hbox) process_layout.addWidget(self.warning_frame) self.success_frame = QFrame() self.success_frame.setVisible(False) self.success_frame.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed) hbox = QHBoxLayout() success_icon_widget = qta.IconWidget('fa.check', color='green') success_icon_widget.setIconSize(QtCore.QSize(48, 48)) success_icon_widget.update() hbox.addWidget(success_icon_widget) success_label = QLabel("All checks completed successfully.") success_label.setStyleSheet("QLabel { color: green; }") success_label.setWordWrap(True) success_label.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Preferred) hbox.addWidget(success_label) self.success_frame.setLayout(hbox) process_layout.addWidget(self.success_frame) log_layout = QVBoxLayout() log_layout.setSpacing(4) log_label = QLabel("Log messages") log_label.setStyleSheet("QLabel { color: grey; }") log_layout.addWidget(log_label) self.log_messages = QPlainTextEdit() log_font = QFont("monospace") log_font.setStyleHint(QFont.TypeWriter) self.log_messages.setFont(log_font) self.log_messages.setReadOnly(True) self.log_messages.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) log_layout.addWidget(self.log_messages) process_layout.addLayout(log_layout) self.vbox.addWidget(process_groupbox) def set_run_stop_buttons_enabled(self, is_running: bool) -> NoReturn: if is_running: self.run_button.setEnabled(False) self.stop_button.setEnabled(True) else: self.run_button.setEnabled(True) self.stop_button.setEnabled(False) def _log_message(self, message): self.log_messages.appendPlainText(message) def run_executor(self, check_executor: QtCheckExecutorThread): # we pass the check_executor into the run tab as this is where the UI # components are that will display the execution status. self.set_run_stop_buttons_enabled(True) self._log_message("Check execution started") self.start_time = time.perf_counter() self.check_executor = check_executor self.check_executor.options = self.get_options() self.check_executor.check_tool_started.connect( self._on_check_tool_started) self.check_executor.progress.connect(self._on_progress) self.check_executor.qajson_updated.connect(self._on_qajson_update) self.check_executor.checks_complete.connect(self._on_checks_complete) self.check_executor.status_changed.connect(self._on_status_change) self.check_executor.start() def get_options(self) -> Dict: ''' Gets a list of options based on user entered data. eg; the spatial output specifications. ''' return { CheckOption.spatial_output_qajson: self.qajson_spatial_checkbox.isChecked(), CheckOption.spatial_output_export: self.export_spatial_checkbox.isChecked(), CheckOption.spatial_output_export_location: self.output_folder_input.text() } def _click_run(self): self.run_checks.emit() def _click_stop(self): if self.check_executor is None: logger.warn("Check executor does not exist, cannot stop") return self._log_message("Stopping check execution") self.check_executor.stop() @QtCore.Slot(float) def _on_progress(self, progress): self.progress_bar.setValue(int(progress * 100)) @QtCore.Slot() def _on_qajson_update(self): self.prj.qa_json = self.check_executor.qa_json @QtCore.Slot(object) def _on_check_tool_started(self, tpl): check_tool_name, check_number, total_check_count = tpl self.check_name_text_label.setText("{} ({}/{})".format( check_tool_name, check_number, total_check_count)) @QtCore.Slot() def _on_checks_complete(self): run_time = time.perf_counter() - self.start_time self._log_message( f"Execution time for all checks = {run_time:.2f} sec") self._log_message("\n\n") self.set_run_stop_buttons_enabled(False) self.prj.qa_json = self.check_executor.qa_json @QtCore.Slot(str) def _on_status_change(self, status): self.status_name_text_label.setText(status)
class Log(QWidget): def __init__(self, sender, title=''): super(Log, self).__init__() self.main_layout = QVBoxLayout() self.header_layout = QHBoxLayout() title_label = QLabel(title) title_label.setFont(QFont('Poppins', 13)) self.header_layout.addWidget(title_label) self.remove_button = QPushButton('x') self.remove_button.clicked.connect(self.remove_clicked) self.header_layout.addWidget(self.remove_button) self.remove_button.hide() holder_label = QLabel(shorten(str(sender), 76)) holder_label.setWordWrap(True) self.log_view = QPlainTextEdit() self.log_view.setReadOnly(True) self.main_layout.addLayout(self.header_layout) self.main_layout.addWidget(holder_label) self.main_layout.addWidget(self.log_view) self.setLayout(self.main_layout) self.enabled_style_sheet = ''' QLabel { border: None; } QWidget { color: #e9f4fb; } ''' self.disabled_style_sheet = ''' QLabel { border: None; } QWidget { color: #e9f4fb; } QPlainTextEdit { background: black; color: grey; } ''' self.setStyleSheet(self.enabled_style_sheet) def log(self, *args): s = '' for arg in args: s += ' ' + str(arg) self.log_view.appendPlainText('> ' + s) def clear(self): self.log_view.clear() def disable(self): self.remove_button.show() self.setStyleSheet(self.disabled_style_sheet) def enable(self): self.remove_button.hide() self.setStyleSheet(self.enabled_style_sheet) self.show() def remove_clicked(self): self.hide()
class TrainingConsoleWidget(QWidget): """The TrainingConsoleWidget provides a widget for controlling the training status of a model, in a simple way. (Analog of the console output in Keras, but with a few more options). It also can save and show an history of the last trained models. """ training_started = Signal() training_stopped = Signal() class TrainingStatus(Enum): Running = 1 Stopped = 2 Not_Compiled = 3 def __init__(self, parent: "QWidget" = None): super().__init__(parent) # Components self._pretrained_model: Optional["keras.models.Model"] = None self._ttv: Optional["TTVSets"] = None self._hyperparameters: Optional[Dict] = None self._callbacks: List[Callback] = [] self._trained_model: Optional["keras.models.Model"] = None # Widgets self._start_training_button = QPushButton("Start training") self._stop_training_button = QPushButton("Stop training") self._buttons_layout = QHBoxLayout() self._buttons_layout.addWidget(self._start_training_button) self._buttons_layout.addWidget(self._stop_training_button) self._status_label = QLabel() self._batch_progress_bar = QProgressBar() self._epoch_progress_bar = QProgressBar() self.training_output_textbox = QPlainTextEdit() self.training_output_textbox.setReadOnly(True) console_output_group = QGroupBox("Console output") console_output_layout = QVBoxLayout() console_output_layout.setContentsMargins(0, 0, 0, 0) console_output_layout.addWidget(self.training_output_textbox) console_output_group.setLayout(console_output_layout) self._main_layout = QVBoxLayout() self._main_layout.addLayout(self._buttons_layout) self._main_layout.addWidget(self._status_label, Qt.AlignRight) self._main_layout.addWidget(console_output_group) self._main_layout.addWidget(self._batch_progress_bar) self._main_layout.addWidget(self._epoch_progress_bar) self.setLayout(self._main_layout) # Connections self._start_training_button.clicked.connect(self.start_training) self._stop_training_button.clicked.connect(self.stop_training) # Inner workings self.training_status = self.TrainingStatus.Not_Compiled self._training_thread = None @property def training_status(self): """Returns the current status of the training (Running, Stopped...)""" return self._training_status @training_status.setter def training_status(self, new_status): """Changes the training status. Doing so will update the interface accordingly. """ self._training_status = new_status if self._training_status == self.TrainingStatus.Running: self._start_training_button.setEnabled(False) self._stop_training_button.setEnabled(True) self._status_label.setText("Running") self.start_training elif self._training_status == self.TrainingStatus.Stopped: self._start_training_button.setEnabled(True) self._stop_training_button.setEnabled(False) self._status_label.setText("Stopped") elif self._training_status == self.TrainingStatus.Not_Compiled: self._start_training_button.setEnabled(True) self._stop_training_button.setEnabled(False) self._status_label.setText("Not Compiled") def set_ttv(self, ttv: "TTVSets"): """Sets the Train/Test/Validation models used for training.""" self._ttv = ttv def set_pretrained_model(self, pretrained_model: "Model"): """Sets a new pretrained model for training.""" self._pretrained_model = pretrained_model self.training_status = self.TrainingStatus.Not_Compiled def set_hyperparameters(self, hyperparameters: Dict): """Sets new hyperparameters for training.""" self._hyperparameters = hyperparameters self.training_status = self.TrainingStatus.Not_Compiled def set_callbacks(self, callbacks: List[Callback]): self._callbacks = callbacks def get_trained_model(self): """Returns the model after it has been trained.""" return self._trained_model def compile_model(self): """Compile the model with the passed hyperparameters. The dataset is needed for the input shape.""" LOGGER.info("Starting to compile the model...") if not self._is_input_ready(): return False # Create a new model based on the pretrained one, but with a new InputLayer # compatible with the dataset if self._pretrained_model.layers[0].__class__.__name__ != "InputLayer": input_layer = Input(self._ttv.train.input_shape) output = self._pretrained_model(input_layer) self._trained_model = Model(input_layer, output) else: self._trained_model = self._pretrained_model try: self._trained_model.compile( optimizer=self._hyperparameters["optimizer"], loss=self._hyperparameters["loss_function"], metrics=["accuracy"], ) self._trained_model.summary() LOGGER.info("Model compiled successfully!!") self.training_status = self.TrainingStatus.Stopped return True except Exception as err: LOGGER.exception("Model Compiling error: ", err) self.training_output_textbox.setPlainText( "> Error while compiling the model:\n", str(err)) return False def start_training(self): """Starts the training on a new thread.""" if self.training_status == self.TrainingStatus.Not_Compiled: successfully_compiled = self.compile_model() if not successfully_compiled: LOGGER.info("Couldn't compile model. Training not started.") return total_train_batches = len(self._ttv.train) total_train_epochs = self._hyperparameters["epochs"] self._batch_progress_bar.setMaximum(total_train_batches) self._epoch_progress_bar.setMaximum(total_train_epochs) self._epoch_progress_bar.setValue(0) self.training_output_textbox.clear() def epoch_begin_update(epoch: int, logs): message = f"==== Epoch {epoch + 1}/{total_train_epochs} ====" LOGGER.info(message) self.training_output_textbox.appendPlainText(message) self._epoch_progress_bar.setValue(epoch) def batch_end_update(batch: int, logs): # Update progress self._batch_progress_bar.setValue(batch) # Log metrics on console message = f"{batch}/{total_train_batches}" for (k, v) in list(logs.items()): message += f" - {k}: {v:.4f}" LOGGER.info(message) self.training_output_textbox.appendPlainText(message) def train_end_update(logs): # Put the progress bar at 100% when the training ends self._batch_progress_bar.setValue( self._batch_progress_bar.maximum()) self._epoch_progress_bar.setValue( self._epoch_progress_bar.maximum()) # Stop the training self.stop_training() # Connect callbacks signals_callback = SignalsCallback() signals_callback.epoch_begin.connect(epoch_begin_update) signals_callback.train_batch_end.connect(batch_end_update) signals_callback.train_end.connect(train_end_update) self.training_stopped.connect(signals_callback.stop_model) print(self._callbacks) # log_dir = "logs/fit/" + datetime.datetime.now().strftime("%Y_%m_%d-%H_%M_%S") # tb = program.TensorBoard() # tb.configure(argv=[None, "--logdir", log_dir]) # url = tb.launch() # print("Launched Tensorboard instance in:", url) # tf_callback=tf.keras.callbacks.TensorBoard(log_dir=log_dir, histogram_freq=1) # tf_callback.set_model(self._trained_model) # Start training self._fit_worker = FitWorker( self._trained_model, self._ttv.train, self._hyperparameters, callbacks=[signals_callback] + self._callbacks, ) self.training_status = self.TrainingStatus.Running self._fit_worker.start() self.training_started.emit() def stop_training(self): """Stops the training.""" self.training_status = self.TrainingStatus.Stopped self.training_stopped.emit() def _is_input_ready(self) -> bool: """Checks if the input values used for training (model, dataset, hyperparameters...) are valid.""" message = "" if not self._ttv.train: message += "> Training dataset not specified\n" if not self._pretrained_model: message += "> Model not specified.\n" if not self._hyperparameters: message += "> Hyperparameters not specified.\n" if message: self.training_output_textbox.setPlainText(message) LOGGER.info(message) return False return True def sizeHint(self) -> "QSize": """Returns the expected size of the widget.""" return QSize(500, 300) def __reduce__(self): return (TrainingConsoleWidget, ())
class application(QTabWidget): bot = 0 def __init__(self, parent=None): super(application, self).__init__(parent) self.bot = None self.db = sqlite3.connect('database') # tabs self.tab1 = QWidget() self.tab2 = QWidget() self.tab3 = QWidget() self.tab4 = QWidget() self.tab5 = QWidget() self.resize(640, 400) self.addTab(self.tab1, "Tab 1") self.addTab(self.tab2, "Tab 2") self.addTab(self.tab3, "Tab 3") self.addTab(self.tab4, "Tab 4") self.addTab(self.tab5, "Tab 5") # tab set keys self.h_box_key = QHBoxLayout() self.change_key_b = QPushButton("Edit keys") self.edit_1 = QLineEdit() self.edit_2 = QLineEdit() self.edit_3 = QLineEdit() self.edit_4 = QLineEdit() self.result = QLabel() self.set_button = QPushButton("Set keys") self.handle_info = QLabel() self.follower_info = QLabel() self.ready_lab = QLabel() # tab follow self.box_label = QLabel("Link to tweet") self.combo_label = QLabel("Mode") self.spin_label = QLabel("Limit before sleep") self.prog_bar = QProgressBar() self.combo_box = QComboBox() self.h_box = QHBoxLayout() self.spin_box = QSpinBox() self.link_box = QLineEdit() self.link_result = QLabel() self.follow_button = QPushButton("Follow Retweeters") self.cancel_button = QPushButton("Cancel") self.logger = QPlainTextEdit() self.h_box2 = QHBoxLayout() self.max_box = QSpinBox() self.max_label = QLabel("Max follows before stop") # tab unfollow self.unfollow_button = QPushButton("Unfollow Auto followers") self.unf_logger = QPlainTextEdit() self.unfollow_res = QLabel() self.prog_bar_unf = QProgressBar() self.unfollow_cancel = QPushButton("Cancel") self.unf_confirm = QMessageBox() # tab help self.help_box = QPlainTextEdit() self.help_label = QLabel( "<a href='http://Optumsense.com/'>http://Optumsense.com/</a>") #tab schedule self.tweet_box = QPlainTextEdit() self.date_time = QDateTimeEdit(QDateTime.currentDateTime()) self.schedule_but = QPushButton("Schedule Tweet") self.schedule_info = QLabel() self.schedule_table = QTableView() # threads self.follow_thread = None self.unfollow_thread = None self.schedule_thread = None # tabs self.tab1UI() self.tab2UI() self.tab3UI() self.tab4UI() self.tab5UI() self.setWindowTitle("Optumize") self.setWindowIcon(QtGui.QIcon('assets/oo.png')) # db cursor = self.db.cursor() cursor.execute(''' CREATE TABLE IF NOT EXISTS keys(one TEXT, two TEXT, three TEXT, four TEXT)''' ) self.db.commit() def tab1UI(self): layout = QFormLayout() layout.addRow(self.h_box) self.h_box.addWidget(self.combo_label) self.combo_label.setAlignment(Qt.AlignRight) self.h_box.addWidget(self.combo_box) self.combo_box.addItem("Follow Retweeters") self.combo_box.addItem("Follow Followers") self.combo_box.currentIndexChanged.connect(self.selection_change) self.h_box.addWidget(self.spin_label) self.spin_label.setAlignment(Qt.AlignRight) self.h_box.addWidget(self.spin_box) self.spin_box.setMinimum(1) self.spin_box.setValue(30) layout.addRow(self.box_label, self.link_box) self.link_result.setAlignment(Qt.AlignCenter) layout.addRow(self.link_result) layout.addRow(self.follow_button) self.follow_button.clicked.connect(self.follow_ret) layout.addRow(self.cancel_button) self.cancel_button.clicked.connect(self.cancel_onclick) layout.addRow(self.h_box2) self.h_box2.addWidget(self.max_label) self.h_box2.addWidget(self.max_box) self.max_box.setFixedWidth(100) self.max_label.setAlignment(Qt.AlignRight) self.max_box.setMaximum(1000000) self.max_box.setValue(100) self.max_label.hide() self.max_box.hide() layout.addRow(self.logger) self.logger.setReadOnly(True) layout.addRow(self.prog_bar) self.prog_bar.setAlignment(Qt.AlignCenter) self.setTabText(0, "Follow") self.setTabIcon(0, QtGui.QIcon('assets/check_mark.png')) self.tab1.setLayout(layout) def selection_change(self, i): if i == 0: self.box_label.setText("Link to tweet") self.follow_button.setText("Follow Retweeters") self.link_result.setText("") self.max_label.hide() self.max_box.hide() self.follow_button.clicked.connect(self.follow_ret) else: self.box_label.setText("Handle of user") self.follow_button.setText("Follow Followers") self.link_result.setText("") self.max_label.show() self.max_box.show() self.max_label.setText("Max follows before stop") self.follow_button.clicked.connect(self.follow_fol) def cancel_onclick(self): if self.follow_thread is None: pass elif self.follow_thread.isRunning(): self.prog_bar.setValue(0) self.logger.appendPlainText("Cancelled script") self.follow_thread.terminate() self.follow_thread = None def follow_ret(self): self.prog_bar.setValue(0) self.follow_button.setEnabled(False) self.link_result.setText("") self.logger.clear() limit = self.spin_box.value() if self.bot is None: self.link_result.setText( "<font color='red'>Configure access keys in set keys tab</font>" ) return if self.follow_thread is not None: return link = self.link_box.text() id_tweet = link.split("/")[-1] try: tweet = self.bot.api.get_status(id_tweet) self.logger.appendPlainText( f"following retweeters from link: {link}...") self.follow_thread = FollowThread(self.bot, id_tweet, limit, 1, 0) self.follow_thread.start() self.connect(self.follow_thread, SIGNAL("finished()"), self.done) self.connect(self.follow_thread, SIGNAL("setup_prog(QString)"), self.setup_prog) self.connect(self.follow_thread, SIGNAL("post_follow(QString)"), self.post_follow) except tweepy.error.TweepError: self.follow_button.setEnabled(True) self.link_result.setText( "<font color='red'>Could not find tweet</font>") def setup_prog(self, msg): self.prog_bar.setMaximum(int(msg)) def follow_fol(self): self.prog_bar.setValue(0) self.follow_button.setEnabled(False) self.link_result.setText("") self.logger.clear() limit = self.spin_box.value() if self.bot is None: self.link_result.setText( "<font color='red'>Configure access keys in set keys tab</font>" ) return if self.follow_thread is not None: return handle = self.link_box.text() if handle == '': self.link_result.setText( "<font color='red'>Enter a handle above</font>") return elif handle[0] == '@': id_user = handle[1:] else: id_user = handle try: man = self.bot.api.get_user(id_user) self.logger.appendPlainText( f"following followers of {man.screen_name}...") self.logger.appendPlainText(f"Collecting") self.follow_thread = FollowThread(self.bot, id_user, limit, 2, self.max_box.value()) self.follow_thread.start() self.connect(self.follow_thread, SIGNAL("finished()"), self.done) self.connect(self.follow_thread, SIGNAL("setup_prog(QString)"), self.setup_prog) self.connect(self.follow_thread, SIGNAL("post_follow(QString)"), self.post_follow) except tweepy.error.TweepError: self.follow_button.setEnabled(True) self.link_result.setText( "<font color='red'>Could not find user</font>") def post_follow(self, message): if message == "bad": self.logger.appendPlainText( "Rate limit exceeded... sleeping for cooldown") else: self.logger.appendPlainText(message) self.prog_bar.setValue(self.prog_bar.value() + 1) def done(self): self.follow_thread = None self.follow_button.setEnabled(True) def tab2UI(self): layout = QFormLayout() layout.addRow(self.unfollow_button) layout.addRow(self.unfollow_cancel) layout.addRow(self.unfollow_res) self.unfollow_res.setAlignment(Qt.AlignCenter) self.unfollow_button.clicked.connect(self.unfollow_fol) self.unfollow_cancel.clicked.connect(self.unfollow_can) layout.addWidget(self.unf_logger) self.unf_logger.setReadOnly(True) layout.addRow(self.prog_bar_unf) self.prog_bar_unf.setAlignment(Qt.AlignCenter) self.setTabText(1, "Unfollow") self.setTabIcon(1, QtGui.QIcon('assets/cross.png')) self.tab2.setLayout(layout) def unfollow_fol(self): self.unfollow_button.setEnabled(False) self.unfollow_thread = UnfollowThread(self.bot) self.unfollow_thread.start() self.connect(self.unfollow_thread, SIGNAL("post_unfol(QString)"), self.post_unfol) self.connect(self.unfollow_thread, SIGNAL("finished()"), self.done_unf) def done_unf(self): self.unfollow_thread = None self.unf_logger.appendPlainText("Done") self.unfollow_button.setEnabled(True) def post_unfol(self, msg): if msg == "bad": self.unf_logger.appendPlainText( "rate limit exceeded, resting for 15 minutes") else: self.unf_logger.appendPlainText(f"Unfollowing {msg}") def unfollow_can(self): if self.unfollow_thread is None: pass elif self.unfollow_thread.isRunning(): self.unf_logger.appendPlainText("Cancelled script") self.unfollow_thread.terminate() self.unfollow_thread = None def tab3UI(self): layout = QFormLayout() layout.addWidget(self.tweet_box) self.tweet_box.setMaximumHeight(150) self.tweet_box.setPlaceholderText("Tweet contents") layout.addRow(self.date_time) self.date_time.setCalendarPopup(True) layout.addRow(self.schedule_info) layout.addRow(self.schedule_but) self.schedule_but.clicked.connect(self.schedule_tweet) layout.addWidget(self.schedule_table) self.setTabText(2, "Schedule Tweet") self.setTabIcon(2, QtGui.QIcon('assets/calendar.png')) self.tab3.setLayout(layout) def schedule_tweet(self): tweet_contents = self.tweet_box.toPlainText() if (len(tweet_contents) == 0): print("length of tweet is 0") self.schedule_info.setText("length of tweet is 0") return elif (len(tweet_contents) >= 280): self.schedule_info.setText("Tweet char limit exceeded") return if self.bot is None: self.schedule_info.setText( "<font color='red'>Configure access keys in set keys tab</font>" ) return datetime = self.date_time.text() try: print("done") self.schedule_thread.start() self.schedule_thread.add_tweet(tweet_contents, datetime) except: self.follow_button.setEnabled(True) self.link_result.setText( "<font color='red'>Could not find user</font>") def done_schedule(self): print("done scheduler") def tab4UI(self): layout = QFormLayout() layout.addRow("API key", self.edit_1) layout.addRow("API key secret", self.edit_2) layout.addRow("Auth token", self.edit_3) layout.addRow("Auth token secret", self.edit_4) self.set_button.clicked.connect(self.set_keys) l = self.read_file() if l is not None: if len(l) == 4: self.edit_1.setText(l[0]) self.edit_2.setText(l[1]) self.edit_3.setText(l[2]) self.edit_4.setText(l[3]) self.set_keys() layout.addRow(self.result) self.result.setAlignment(Qt.AlignCenter) layout.addRow(self.h_box_key) self.h_box_key.addWidget(self.change_key_b) self.h_box_key.addWidget(self.set_button) self.change_key_b.clicked.connect(self.change_keys) layout.addRow(self.handle_info) self.handle_info.setAlignment(Qt.AlignCenter) layout.addRow(self.follower_info) self.follower_info.setAlignment(Qt.AlignCenter) layout.addRow(self.ready_lab) self.ready_lab.setAlignment(Qt.AlignCenter) self.setTabText(3, "Settings") self.setTabIcon(3, QtGui.QIcon('assets/settings.png')) self.tab4.setLayout(layout) def change_keys(self): self.set_button.setEnabled(True) def set_keys(self): self.set_button.setEnabled(False) self.result.setText("") one = self.edit_1.text() two = self.edit_2.text() three = self.edit_3.text() four = self.edit_4.text() try: self.bot = apiconnector.ApiConnector(one, two, three, four) me = self.bot.add_keys(one, two, three, four) self.handle_info.setText("Handle: @" + me.screen_name) self.follower_info.setText("Followers: " + str(me.followers_count)) self.ready_lab.setText("<font color='green'>Ready!</font>") cursor = self.db.cursor() cursor.execute('DELETE FROM keys;', ) cursor.execute( '''INSERT INTO keys(one, two, three, four) VALUES(?,?,?,?)''', (one, two, three, four)) self.db.commit() self.schedule_thread = ScheduleThread(self.bot) except: print("Could not authenticate you") self.result.setText( "<font color='red'>Could not authenticate you</font>") def read_file(self): result = [] try: cursor = self.db.cursor() cursor.execute('''SELECT one, two, three, four FROM keys''') all_rows = cursor.fetchall() for row in all_rows: result.append(row[0]) result.append(row[1]) result.append(row[2]) result.append(row[3]) return result except: return None def tab5UI(self): layout = QFormLayout() layout.addRow("Website", self.help_label) self.help_label.setOpenExternalLinks(True) self.setTabText(4, "Help") self.setTabIcon(4, QtGui.QIcon('assets/help.png')) self.tab5.setLayout(layout)
class PDLEditor(QWidget): def __init__(self): QWidget.__init__(self) self.setLayout(QGridLayout()) split = QSplitter(Qt.Horizontal) split.setChildrenCollapsible(False) self.vis_area = WidgetVisualizationArea() split.addWidget(self.vis_area) edit_pane = QWidget() edit_pane.setLayout(QVBoxLayout()) font = QFont('Courier New', 11) self.editor = QPlainTextEdit() self.editor.document().setDefaultFont(font) edit_pane.layout().addWidget(self.editor) compile_b = QPushButton("Compile") compile_b.clicked.connect(self.compilePDL) edit_pane.layout().addWidget(compile_b) self.messages = QPlainTextEdit() self.messages.setReadOnly(True) self.messages.document().setDefaultFont(font) edit_pane.layout().addWidget(self.messages) split.addWidget(edit_pane) self.layout().addWidget(split) @Slot() def compilePDL(self): self.messages.appendPlainText('------------') pdl_text = self.editor.toPlainText() try: parser = top.Parser([pdl_text], 's') plumb = parser.make_engine() except Exception as e: self.messages.appendPlainText( 'Error encountered in PDL compilation:') self.messages.appendPlainText(str(e)) scrollbar = self.messages.verticalScrollBar() scrollbar.setValue(scrollbar.maximum()) return if not plumb.is_valid(): self.messages.appendPlainText('Plumbing engine is invalid:') error_str = str('\n'.join( [e.error_message for e in plumb.error_set])) self.messages.appendPlainText(error_str) scrollbar = self.messages.verticalScrollBar() scrollbar.setValue(scrollbar.maximum()) return self.messages.appendPlainText('PDL compilation successful') scrollbar = self.messages.verticalScrollBar() scrollbar.setValue(scrollbar.maximum()) self.vis_area.visualizer.uploadEngineInstance(plumb)
class DLPPrinterGUI(QWidget): closing_window_event = Signal() spinboxValueChanged = Signal(float) def __init__(self, dlp_controller=None, parent=None, printer_setup='BOTTOM-UP'): QWidget.__init__(self, parent) if dlp_controller: self.dlp_controller = dlp_controller else: self.dlp_controller = DLPMainController(printer_setup) self.dlp_controller.block_parameters_signal.connect( self.block_parameters_signals) self.dlp_controller.reactivate_parameters_signal.connect( self.reactivate_parameters_signals) self.dlp_controller.motor_changed_signal.connect( self.update_motor_parameters) self.closing_window_event.connect(self.dlp_controller.close_projector) self.parent = parent self.main_layout = QHBoxLayout() self.__init_widget__() self.setLayout(self.main_layout) def __init_widget__(self): self.__left_widget = QWidget() self.__left_widget.setSizePolicy(QSizePolicy.Maximum, QSizePolicy.MinimumExpanding) self.__right_widget = QWidget() self.__right_widget.setSizePolicy(QSizePolicy.MinimumExpanding, QSizePolicy.MinimumExpanding) self.__init_printer_options_widget__(self.__left_widget) self.__init_projector_widget__(self.__left_widget) self.__init_support_widget__(self.__left_widget) self.__init_features_widget__(self.__left_widget) self.__init_advanced_features_widget__(self.__left_widget) # self.__init_expected_time_widget__(self.__left_widget) self.__left_layout = QGridLayout() self.__left_layout.addWidget(self.__printer_options_widget, 0, 0, 1, 2) self.__left_layout.addWidget(self.__projector_widget, 1, 0, 1, 2) self.__left_layout.addWidget(self.__support_widget, 2, 0, 1, 1) self.__left_layout.addWidget(self.__features_widget, 2, 1, 1, 1) self.__left_layout.addWidget(self.__advanced_widget, 3, 0, 1, 2) # self.__left_layout.addWidget(self.__expected_time_widget, 4,0) self.__left_widget.setLayout(self.__left_layout) self.__left_widget.show() self.__init_start_stop_widget__(self.__right_widget) self.__init_preview_widget__(self.__right_widget) self.__init_console_widget__(self.__right_widget) self.__init_username_jobname_widget__() self.__right_layout = QVBoxLayout() self.__right_layout.addWidget(self.__start_stop_widget) self.__right_layout.addWidget(self.__username_jobname_widget) self.__right_layout.addWidget(self.__preview_widget) self.__right_layout.addWidget(self.__console_widget) self.__right_widget.setLayout(self.__right_layout) # print(self.__left_layout.sizeHint(), self.__right_layout.sizeHint()) self.main_layout.addWidget(self.__left_widget) self.main_layout.addWidget(self.__right_widget) def __init_printer_options_widget__(self, parent=None): self.__printer_options_widget = QGroupBox("Printer Options", parent) # self.__printer_options_widget.setSizePolicy(QSizePolicy.Maximum, QSizePolicy.Maximum) port_label = QLabel("Port:", self.__printer_options_widget) self.port_list = MyQComboBox(self.__printer_options_widget) self.port_list.addItems(self.dlp_controller.available_ports()) self.port_list.currentIndexChanged.connect( self.dlp_controller.select_port) self.port_list.combo_box_clicked.connect(self.update_port_list) connect_button = QPushButton("Connect", self.__printer_options_widget) connect_button.clicked.connect(self.dlp_controller.connect_printer) disconnect_button = QPushButton("Disconnect", self.__printer_options_widget) disconnect_button.clicked.connect( self.dlp_controller.disconnect_printer) reset_button = QPushButton("Reset", self.__printer_options_widget) reset_button.clicked.connect(self.dlp_controller.reset_printer) move_button = QPushButton("Move Building Plate", self.__printer_options_widget) self.move_edit = MyDiscreteStepsSpinBox( self.dlp_controller.get_step_length_microns() / 1000.0, self.__printer_options_widget) self.move_edit.setSuffix("mm") self.move_edit.setMaximum(1000) self.move_edit.setMinimum(-1000) self.move_edit.setDecimals(6) self.move_edit.my_value_changed_signal.connect( self.dlp_controller.update_building_plate_distance) move_button.clicked.connect(self.dlp_controller.move_building_plate) set_origin_button = QPushButton("Set Building Plate Origin", self.__printer_options_widget) set_origin_button.clicked.connect( self.dlp_controller.set_building_plate_origin) home_button = QPushButton("Home Building Plate", self.__printer_options_widget) home_button.clicked.connect(self.dlp_controller.home_building_plate) origin_button = QPushButton("Send Building Plate to Origin", self.__printer_options_widget) origin_button.clicked.connect( self.dlp_controller.move_building_plate_to_origin) options_layout = QGridLayout(self.__printer_options_widget) # options_layout.addWidget(options_label, 0, 0, 1, 5) options_layout.addWidget(port_label, 0, 0) options_layout.addWidget(self.port_list, 0, 1) options_layout.addWidget(connect_button, 0, 2) options_layout.addWidget(disconnect_button, 0, 3) options_layout.addWidget(reset_button, 0, 4) options_layout.addWidget(move_button, 1, 0, 1, 2) options_layout.addWidget(self.move_edit, 1, 2) options_layout.addWidget(set_origin_button, 1, 3, 1, 2) options_layout.addWidget(home_button, 2, 0, 1, 2) options_layout.addWidget(origin_button, 2, 2, 1, 2) self.__printer_options_widget.setLayout(options_layout) def __init_projector_widget__(self, parent=None): self.__projector_widget = QGroupBox("Projector Options", parent) # self.__projector_widget.setSizePolicy(QSizePolicy.Maximum, QSizePolicy.Maximum) mirror_x = QCheckBox("Mirror X") mirror_x.setChecked(self.dlp_controller.is_horizontal_mirrored()) mirror_x.toggled.connect(self.dlp_controller.set_horizontal_mirroring) mirror_y = QCheckBox("Mirror Y") mirror_y.setChecked(self.dlp_controller.is_vertical_mirrored()) mirror_y.toggled.connect(self.dlp_controller.set_vertical_mirroring) start_projector_button = QPushButton("Start Projector", self.__projector_widget) start_projector_button.clicked.connect( self.dlp_controller.start_projector) project_pattern_button = QPushButton("Project Pattern", self.__projector_widget) project_pattern_button.clicked.connect( self.dlp_controller.project_calibration_pattern) print_position_button = QPushButton("Print Position", self.__projector_widget) print_position_button.clicked.connect( self.dlp_controller.print_motor_position) home_projector_button = QPushButton("Home Projector", self.__projector_widget) home_projector_button.clicked.connect( self.dlp_controller.home_projector) move_projector_button = QPushButton("Move Projector", self.__projector_widget) move_projector_button.clicked.connect( self.dlp_controller.move_projector) move_projector_edit = QDoubleSpinBox(self.__projector_widget) move_projector_edit.setSuffix("mm") move_projector_edit.setMaximum(10000) move_projector_edit.setMinimum(-10000) move_projector_edit.setDecimals(3) move_projector_edit.setSingleStep(0.001) move_projector_edit.valueChanged.connect( self.dlp_controller.update_projector_distance) set_amplitude_button = QPushButton("Set Projector Amplitude", self.__projector_widget) set_amplitude_button.clicked.connect( self.dlp_controller.set_projector_amplitude) set_amplitude_edit = QSpinBox(self.__projector_widget) set_amplitude_edit.setMaximum(1000) set_amplitude_edit.setMinimum(0) set_amplitude_edit.setValue(self.dlp_controller.projector_amplitude) set_amplitude_edit.valueChanged.connect( self.dlp_controller.update_projector_amplitude) lock_unlock_projector_button = QPushButton("Lock/Unlock Projector", self.__projector_widget) lock_unlock_projector_button.clicked.connect( self.dlp_controller.lock_unlock_projector) projector_layout = QGridLayout(self.__projector_widget) # projector_layout.addWidget(projector_label, 0, 0) projector_layout.addWidget(mirror_x, 0, 1) projector_layout.addWidget(mirror_y, 0, 2) projector_layout.addWidget(start_projector_button, 1, 0, 1, 1) projector_layout.addWidget(project_pattern_button, 1, 1, 1, 1) projector_layout.addWidget(print_position_button, 1, 2, 1, 1) projector_layout.addWidget(home_projector_button, 2, 0, 1, 1) projector_layout.addWidget(move_projector_button, 2, 1, 1, 1) projector_layout.addWidget(move_projector_edit, 2, 2) projector_layout.addWidget(set_amplitude_button, 3, 0, 1, 1) projector_layout.addWidget(set_amplitude_edit, 3, 1) projector_layout.addWidget(lock_unlock_projector_button, 3, 2, 1, 1) self.__projector_widget.setLayout(projector_layout) def __init_support_widget__(self, parent=None): self.__support_widget = QGroupBox("Support Layers Parameters", parent) # self.__support_widget.setSizePolicy(QSizePolicy.Maximum, QSizePolicy.Maximum) thickness_label = QLabel("Layer Thickness", self.__support_widget) self.support_thickness_edit = MyDiscreteStepsSpinBox( self.dlp_controller.get_step_length_microns(), self.__support_widget) self.support_thickness_edit.setSuffix(str('\u03BCm')) self.support_thickness_edit.setMaximum(1000000) self.support_thickness_edit.setMinimum(0) self.support_thickness_edit.setDecimals(3) self.support_thickness_edit.my_value_changed_signal.connect( self.dlp_controller.set_support_thickness) self.support_thickness_edit.setValue( self.dlp_controller.support_thickness * 1000) exposure_label = QLabel("Exposure Time", self.__support_widget) exposure_edit = QDoubleSpinBox(self.__support_widget) exposure_edit.setSuffix(str('ms')) exposure_edit.setMaximum(10000000) exposure_edit.setMinimum(0) exposure_edit.setDecimals(1) exposure_edit.setSingleStep(0.1) exposure_edit.setValue(self.dlp_controller.support_exposure) exposure_edit.valueChanged.connect( self.dlp_controller.set_support_exposure_time) amplitude_label = QLabel("Light Amplitude", self.__support_widget) amplitude_edit = QSpinBox(self.__support_widget) amplitude_edit.setMaximum(1600) amplitude_edit.setMinimum(0) amplitude_edit.setSingleStep(1) amplitude_edit.setValue(self.dlp_controller.support_amplitude) amplitude_edit.valueChanged.connect( self.dlp_controller.set_support_amplitude) burn_layers_label = QLabel("Burn Layers", self.__support_widget) burn_layers_edit = QSpinBox(self.__support_widget) burn_layers_edit.setMaximum(1000) burn_layers_edit.setMinimum(0) burn_layers_edit.setSingleStep(1) burn_layers_edit.setValue(self.dlp_controller.support_burn_layers) burn_layers_edit.valueChanged.connect( self.dlp_controller.set_support_burning_layers) burn_exposure_label = QLabel("Burn Exposure", self.__support_widget) burn_exposure_edit = QDoubleSpinBox(self.__support_widget) burn_exposure_edit.setSuffix(str('ms')) burn_exposure_edit.setMaximum(100000) burn_exposure_edit.setMinimum(0) burn_exposure_edit.setDecimals(1) burn_exposure_edit.setSingleStep(0.1) burn_exposure_edit.setValue(self.dlp_controller.support_burn_exposure) burn_exposure_edit.valueChanged.connect( self.dlp_controller.set_support_burning_exposure_time) burn_amplitude_label = QLabel("Burn Amplitude", self.__support_widget) burn_amplitude_edit = QSpinBox(self.__support_widget) burn_amplitude_edit.setMaximum(1600) burn_amplitude_edit.setMinimum(0) burn_amplitude_edit.setSingleStep(1) burn_amplitude_edit.setValue( self.dlp_controller.support_burn_amplitude) burn_amplitude_edit.valueChanged.connect( self.dlp_controller.set_support_burning_amplitude) select_layers_button = QPushButton("Select Support Images") select_layers_button.clicked.connect(self.load_support_images) support_layout = QGridLayout(self.__support_widget) support_layout.addWidget(thickness_label, 1, 0) support_layout.addWidget(self.support_thickness_edit, 1, 1) support_layout.addWidget(exposure_label, 2, 0) support_layout.addWidget(exposure_edit, 2, 1) support_layout.addWidget(amplitude_label, 3, 0) support_layout.addWidget(amplitude_edit, 3, 1) support_layout.addWidget(burn_layers_label, 4, 0) support_layout.addWidget(burn_layers_edit, 4, 1) support_layout.addWidget(burn_exposure_label, 5, 0) support_layout.addWidget(burn_exposure_edit, 5, 1) support_layout.addWidget(burn_amplitude_label, 6, 0) support_layout.addWidget(burn_amplitude_edit, 6, 1) support_layout.addWidget(select_layers_button, 7, 0, 1, 2) self.__support_widget.setLayout(support_layout) def __init_features_widget__(self, parent=None): self.__features_widget = QGroupBox("Features Layers Parameters", parent) # self.__features_widget.setSizePolicy(QSizePolicy.Maximum, QSizePolicy.Maximum) thickness_label = QLabel("Layer Thickness", self.__features_widget) self.features_thickness_edit = MyDiscreteStepsSpinBox( self.dlp_controller.get_step_length_microns(), self.__features_widget) self.features_thickness_edit.setSuffix(str('\u03BCm')) self.features_thickness_edit.setMaximum(1000000) self.features_thickness_edit.setMinimum(0) self.features_thickness_edit.setDecimals(3) self.features_thickness_edit.my_value_changed_signal.connect( self.dlp_controller.set_features_thickness) self.features_thickness_edit.setValue( self.dlp_controller.features_thickness * 1000) exposure_label = QLabel("Exposure Time", self.__features_widget) exposure_edit = QDoubleSpinBox(self.__features_widget) exposure_edit.setSuffix(str('ms')) exposure_edit.setMaximum(10000000) exposure_edit.setMinimum(0) exposure_edit.setDecimals(1) exposure_edit.setSingleStep(0.1) exposure_edit.setValue(self.dlp_controller.features_exposure) exposure_edit.valueChanged.connect( self.dlp_controller.set_features_exposure_time) amplitude_label = QLabel("Light Amplitude", self.__features_widget) amplitude_edit = QSpinBox(self.__features_widget) amplitude_edit.setMaximum(1600) amplitude_edit.setMinimum(0) amplitude_edit.setSingleStep(1) amplitude_edit.setValue(self.dlp_controller.features_amplitude) amplitude_edit.valueChanged.connect( self.dlp_controller.set_features_amplitude) burn_layers_label = QLabel("Burn Layers", self.__features_widget) burn_layers_edit = QSpinBox(self.__features_widget) burn_layers_edit.setMaximum(1000) burn_layers_edit.setMinimum(0) burn_layers_edit.setSingleStep(1) burn_layers_edit.setValue(self.dlp_controller.features_burn_layers) burn_layers_edit.valueChanged.connect( self.dlp_controller.set_features_burning_layers) burn_exposure_label = QLabel("Burn Exposure", self.__features_widget) burn_exposure_edit = QDoubleSpinBox(self.__features_widget) burn_exposure_edit.setSuffix(str('ms')) burn_exposure_edit.setMaximum(100000) burn_exposure_edit.setMinimum(0) burn_exposure_edit.setDecimals(1) burn_exposure_edit.setSingleStep(0.1) burn_exposure_edit.setValue(self.dlp_controller.features_burn_exposure) burn_exposure_edit.valueChanged.connect( self.dlp_controller.set_features_burning_exposure_time) burn_amplitude_label = QLabel("Burn Amplitude", self.__features_widget) burn_amplitude_edit = QSpinBox(self.__features_widget) burn_amplitude_edit.setMaximum(1600) burn_amplitude_edit.setMinimum(0) burn_amplitude_edit.setSingleStep(1) burn_amplitude_edit.setValue( self.dlp_controller.features_burn_amplitude) burn_amplitude_edit.valueChanged.connect( self.dlp_controller.set_features_burning_amplitude) select_layers_button = QPushButton("Select Features Images") select_layers_button.clicked.connect(self.load_features_images) features_layout = QGridLayout(self.__features_widget) features_layout.addWidget(thickness_label, 1, 0) features_layout.addWidget(self.features_thickness_edit, 1, 1) features_layout.addWidget(exposure_label, 2, 0) features_layout.addWidget(exposure_edit, 2, 1) features_layout.addWidget(amplitude_label, 3, 0) features_layout.addWidget(amplitude_edit, 3, 1) features_layout.addWidget(burn_layers_label, 4, 0) features_layout.addWidget(burn_layers_edit, 4, 1) features_layout.addWidget(burn_exposure_label, 5, 0) features_layout.addWidget(burn_exposure_edit, 5, 1) features_layout.addWidget(burn_amplitude_label, 6, 0) features_layout.addWidget(burn_amplitude_edit, 6, 1) features_layout.addWidget(select_layers_button, 7, 0, 1, 2) self.__features_widget.setLayout(features_layout) def __init_advanced_features_widget__(self, parent=None): self.__advanced_widget = QGroupBox("Advanced Features Options", parent) fixed_layer_check = QCheckBox("Fixed Layer", self.__advanced_widget) fixed_layer_check.setChecked(self.dlp_controller.fixed_layer) fixed_layer_check.toggled.connect(self.dlp_controller.set_fixed_layer) incremental_amplitude_check = QCheckBox("Incremental Amplitude", self.__advanced_widget) incremental_amplitude_check.setChecked( self.dlp_controller.incremental_amplitude) incremental_amplitude_check.toggled.connect( self.dlp_controller.set_incremental_amplitude) starting_amplitude_label = QLabel("Starting Amplitude", self.__advanced_widget) starting_amplitude_edit = QSpinBox(self.__advanced_widget) starting_amplitude_edit.setMaximum(1000) starting_amplitude_edit.setMinimum(0) starting_amplitude_edit.setSingleStep(1) starting_amplitude_edit.setValue( self.dlp_controller.starting_incremental_amplitude) starting_amplitude_edit.valueChanged.connect( self.dlp_controller.set_starting_incremental_amplitude) amplitude_step_label = QLabel("Step Size", self.__advanced_widget) amplitude_step_edit = QSpinBox(self.__advanced_widget) amplitude_step_edit.setMaximum(1000) amplitude_step_edit.setMinimum(0) amplitude_step_edit.setSingleStep(1) amplitude_step_edit.setValue( self.dlp_controller.incremental_step_amplitude) amplitude_step_edit.valueChanged.connect( self.dlp_controller.set_incremental_step_amplitude) incremental_exposure_check = QCheckBox("Incremental Exposure", self.__advanced_widget) incremental_exposure_check.setChecked( self.dlp_controller.incremental_exposure) incremental_exposure_check.toggled.connect( self.dlp_controller.set_incremental_exposure) starting_exposure_label = QLabel("Starting Exposure", self.__advanced_widget) starting_exposure_edit = QDoubleSpinBox(self.__advanced_widget) starting_exposure_edit.setSuffix(str('ms')) starting_exposure_edit.setMaximum(100000) starting_exposure_edit.setMinimum(0) starting_exposure_edit.setDecimals(1) starting_exposure_edit.setSingleStep(0.1) starting_exposure_edit.valueChanged.connect( self.dlp_controller.set_starting_incremental_exposure) starting_exposure_edit.setValue( self.dlp_controller.starting_incremental_exposure) exposure_step_label = QLabel("Step Size", self.__advanced_widget) exposure_step_edit = QDoubleSpinBox(self.__advanced_widget) exposure_step_edit.setSuffix(str('ms')) exposure_step_edit.setMaximum(100000) exposure_step_edit.setMinimum(0) exposure_step_edit.setDecimals(1) exposure_step_edit.setSingleStep(0.1) exposure_step_edit.valueChanged.connect( self.dlp_controller.set_incremental_step_exposure) exposure_step_edit.setValue( self.dlp_controller.incremental_step_exposure) incremental_thickness_check = QCheckBox("Incremental Thickness", self.__advanced_widget) incremental_thickness_check.setChecked( self.dlp_controller.incremental_thickness) incremental_thickness_check.toggled.connect( self.dlp_controller.set_incremental_thickness) thickness_label = QLabel("Starting Thickness", self.__features_widget) self.starting_thickness_edit = MyDiscreteStepsSpinBox( self.dlp_controller.get_step_length_microns(), self.__features_widget) self.starting_thickness_edit.setSuffix(str('\u03BCm')) self.starting_thickness_edit.setMaximum(1000000) self.starting_thickness_edit.setMinimum(0) self.starting_thickness_edit.setDecimals(3) self.starting_thickness_edit.my_value_changed_signal.connect( self.dlp_controller.set_starting_incremental_thickness) self.starting_thickness_edit.setValue( self.dlp_controller.starting_incremental_thickness * 1000) thickness_step_label = QLabel("Step Size", self.__features_widget) self.thickness_step_edit = MyDiscreteStepsSpinBox( self.dlp_controller.get_step_length_microns(), self.__features_widget) self.thickness_step_edit.setSuffix(str('\u03BCm')) self.thickness_step_edit.setMaximum(1000000) self.thickness_step_edit.setMinimum(0) self.thickness_step_edit.setDecimals(3) self.thickness_step_edit.my_value_changed_signal.connect( self.dlp_controller.set_incremental_step_thickness) self.thickness_step_edit.setValue( self.dlp_controller.incremental_step_thickness * 1000) apply_grayscale_correction_check = QCheckBox("Grayscale Correction", self.__advanced_widget) apply_grayscale_correction_check.setChecked( self.dlp_controller.grayscale_correction) apply_grayscale_correction_check.toggled.connect( self.dlp_controller.set_grayscale_correction) grayscale_parameters_widget = QWidget(self.__features_widget) a_parameter_label = QLabel("\u03B1", grayscale_parameters_widget) alpha_parameter_edit = QDoubleSpinBox(grayscale_parameters_widget) alpha_parameter_edit.setMaximum(1000) alpha_parameter_edit.setMinimum(0) alpha_parameter_edit.setDecimals(3) alpha_parameter_edit.setSingleStep(0.001) alpha_parameter_edit.valueChanged.connect( self.dlp_controller.set_grayscale_alpha) alpha_parameter_edit.setValue(self.dlp_controller.grayscale_alpha) beta_parameter_label = QLabel("\u03B2", grayscale_parameters_widget) beta_parameter_edit = QDoubleSpinBox(grayscale_parameters_widget) beta_parameter_edit.setMaximum(1000) beta_parameter_edit.setMinimum(0) beta_parameter_edit.setDecimals(3) beta_parameter_edit.setSingleStep(0.001) beta_parameter_edit.valueChanged.connect( self.dlp_controller.set_grayscale_beta) beta_parameter_edit.setValue(self.dlp_controller.grayscale_beta) gamma_parameter_label = QLabel("\u03B3", grayscale_parameters_widget) gamma_parameter_edit = QDoubleSpinBox(grayscale_parameters_widget) gamma_parameter_edit.setMaximum(1000) gamma_parameter_edit.setMinimum(0) gamma_parameter_edit.setDecimals(3) gamma_parameter_edit.setSingleStep(0.001) gamma_parameter_edit.valueChanged.connect( self.dlp_controller.set_grayscale_gamma) gamma_parameter_edit.setValue(self.dlp_controller.grayscale_gamma) grayscale_parameters_layout = QHBoxLayout(grayscale_parameters_widget) grayscale_parameters_layout.addWidget(a_parameter_label) grayscale_parameters_layout.addWidget(alpha_parameter_edit) grayscale_parameters_layout.addWidget(beta_parameter_label) grayscale_parameters_layout.addWidget(beta_parameter_edit) grayscale_parameters_layout.addWidget(gamma_parameter_label) grayscale_parameters_layout.addWidget(gamma_parameter_edit) grayscale_parameters_widget.setLayout(grayscale_parameters_layout) advanced_features_layout = QGridLayout(self.__advanced_widget) advanced_features_layout.addWidget(incremental_amplitude_check, 1, 0, 1, 2) advanced_features_layout.addWidget(fixed_layer_check, 1, 3) advanced_features_layout.addWidget(starting_amplitude_label, 2, 0) advanced_features_layout.addWidget(starting_amplitude_edit, 2, 1) advanced_features_layout.addWidget(amplitude_step_label, 2, 2) advanced_features_layout.addWidget(amplitude_step_edit, 2, 3) advanced_features_layout.addWidget(incremental_exposure_check, 3, 0, 1, 2) advanced_features_layout.addWidget(starting_exposure_label, 4, 0) advanced_features_layout.addWidget(starting_exposure_edit, 4, 1) advanced_features_layout.addWidget(exposure_step_label, 4, 2) advanced_features_layout.addWidget(exposure_step_edit, 4, 3) advanced_features_layout.addWidget(incremental_thickness_check, 5, 0, 1, 2) advanced_features_layout.addWidget(thickness_label, 6, 0) advanced_features_layout.addWidget(self.starting_thickness_edit, 6, 1) advanced_features_layout.addWidget(thickness_step_label, 6, 2) advanced_features_layout.addWidget(self.thickness_step_edit, 6, 3) advanced_features_layout.addWidget(apply_grayscale_correction_check, 7, 0, 1, 2) advanced_features_layout.addWidget(grayscale_parameters_widget, 8, 0, 1, 4) self.__advanced_widget.setLayout(advanced_features_layout) def __init_start_stop_widget__(self, parent=None): self.__start_stop_widget = QFrame(parent) size = self.__left_layout.sizeHint() start_button = QPushButton("START", self.__start_stop_widget) start_button.setFixedSize(size.width() / 2, size.height() / 7) start_button.clicked.connect( self.dlp_controller.starting_printing_process) stop_button = QPushButton("STOP", self.__start_stop_widget) stop_button.setFixedSize(size.width() / 3, size.height() / 8) stop_button.setStyleSheet( "QPushButton {background-color: red; border-style: outset; border-width: 2px; " "border-radius: 10px; border-color: beige; font: bold 20px; padding: 10px;}" ) stop_button.clicked.connect(self.dlp_controller.stop_printing_process) self.__start_stop_widget.setMinimumSize(size.width(), size.height() / 6) start_stop_layout = QGridLayout(self.__start_stop_widget) start_stop_layout.addWidget(start_button, 0, 0) start_stop_layout.addWidget(stop_button, 0, 1) self.__start_stop_widget.setLayout(start_stop_layout) def __init_preview_widget__(self, parent=None): self.__preview_widget = QLabel(parent) size = self.__left_layout.sizeHint() self.dlp_controller.display_image_signal.connect(self.preview_image) self.__preview_widget.setMinimumSize(size.width(), size.height() / 2.3) # self.__preview_widget.setSizePolicy(QSizePolicy.Minimum, QSizePolicy.Minimum) self.__preview_widget.setScaledContents(True) self.__preview_widget.setStyleSheet( "QLabel { background-color : black}") def __init_console_widget__(self, parent=None): self.__console_widget = QPlainTextEdit(parent) self.__console_widget.setReadOnly(True) size = self.__left_layout.sizeHint() # self.__console_widget.setFixedSize(size.width(), size.height()/3) self.__console_widget.setStyleSheet( "QPlainTextEdit { background-color : gray}") palette = self.__console_widget.palette() palette.setColor(QPalette.Text, QColor(255, 255, 255)) self.__console_widget.setPalette(palette) self.dlp_controller.print_text_signal.connect(self.print_to_console) def __init_username_jobname_widget__(self, parent=None): self.__username_jobname_widget = QFrame(parent) self.__username_jobname_widget.setSizePolicy(QSizePolicy.Maximum, QSizePolicy.Maximum) username_label = QLabel("Username", parent=self.__username_jobname_widget) username_edit = QLineEdit(parent=self.__username_jobname_widget) username_edit.setText(self.dlp_controller.username) username_edit.textChanged.connect(self.dlp_controller.set_username) jobname_label = QLabel("Print Job Name", parent=self.__username_jobname_widget) jobname_edit = QLineEdit(parent=self.__username_jobname_widget) jobname_edit.setText(self.dlp_controller.print_job_name) jobname_edit.textChanged.connect(self.dlp_controller.set_printjob_name) etc = self.dlp_controller.evaluate_time_estimate() self.etc_label = QLabel( "ETC: " + QDateTime.fromTime_t(etc / 1000.0).toUTC().toString('hh:mm:ss'), self.__username_jobname_widget) self.dlp_controller.etc_updated_signal.connect( self.update_time_estimate) username_jobname_layout = QHBoxLayout(self.__username_jobname_widget) username_jobname_layout.addWidget(self.etc_label) username_jobname_layout.addWidget(username_label) username_jobname_layout.addWidget(username_edit) username_jobname_layout.addWidget(jobname_label) username_jobname_layout.addWidget(jobname_edit) self.__username_jobname_widget.setLayout(username_jobname_layout) @Slot(QPixmap) def preview_image(self, image): image = image.scaled(self.__preview_widget.width(), self.__preview_widget.height(), Qt.IgnoreAspectRatio) self.__preview_widget.setPixmap(image) @Slot(str) def print_to_console(self, txt): self.__console_widget.appendPlainText(txt) @Slot() def closeEvent(self, event: QCloseEvent): self.closing_window_event.emit() event.accept() @Slot() def load_support_images(self): file_names = QFileDialog.getOpenFileNames( caption='Select images', dir='../', filter="Image Files (*.png *.jpg *.bmp)") self.dlp_controller.set_support_images(file_names[0]) @Slot() def load_features_images(self): file_names = QFileDialog.getOpenFileNames( caption='Select images', dir='../', filter="Image Files (*.png *.jpg *.bmp)") self.dlp_controller.set_features_images(file_names[0]) @Slot() def block_parameters_signals(self): for widget in self.__left_widget.findChildren(QWidget): widget.blockSignals(True) @Slot() def reactivate_parameters_signals(self): for widget in self.__left_widget.findChildren(QWidget): widget.blockSignals(False) @Slot() def update_time_estimate(self, etc_ms): self.etc_label.setText( "ETC: " + QDateTime.fromTime_t(etc_ms / 1000.0).toUTC().toString('hh:mm:ss')) @Slot() def update_port_list(self): self.dlp_controller.update_port_list() self.port_list.clear() self.port_list.addItems(self.dlp_controller.available_ports()) @Slot(bool) def update_motor_parameters(self, is_changed): self.move_edit.set_step_size( self.dlp_controller.get_step_length_microns() / 1000.0) self.support_thickness_edit.set_step_size( self.dlp_controller.get_step_length_microns()) self.support_thickness_edit.spinbox_is_value_valid( self.dlp_controller.support_thickness * 1000) self.features_thickness_edit.set_step_size( self.dlp_controller.get_step_length_microns()) self.features_thickness_edit.spinbox_is_value_valid( self.dlp_controller.features_thickness * 1000) self.starting_thickness_edit.set_step_size( self.dlp_controller.get_step_length_microns()) self.starting_thickness_edit.spinbox_is_value_valid( self.dlp_controller.starting_incremental_thickness * 1000) self.thickness_step_edit.set_step_size( self.dlp_controller.get_step_length_microns()) self.thickness_step_edit.spinbox_is_value_valid( self.dlp_controller.incremental_step_thickness * 1000)
class MyWidget(QWidget): def __init__(self, parent=None): QWidget.__init__(self, parent) self.thread = SerialMonitorThread() self.thread.dataReady.connect(self.get_data, Qt.QueuedConnection) self.thread.setTerminationEnabled(True) #Menu self.setPalette(get_verifone_color()) collapsible = CollapsibleWidget() self.init_logging(collapsible) self.init_download(collapsible) self.init_analyser(collapsible) collapsible.add_sections() # Scroll Area self.createLoggingDisplayLabel() self.scrollArea = QScrollArea() self.scrollArea.setBackgroundRole(QPalette.Dark) self.scrollArea.setWidget(self.text) self.scrollArea.setWidgetResizable(True) hLayout = QHBoxLayout() #hLayout.addLayout(vLayout) hLayout.addWidget(collapsible) hLayout.addWidget(self.scrollArea) self.setLayout(hLayout) def init_logging(self, collapsible): self.logger = QPushButton("Start Logging", self) self.logger.setFont(QFont("Times", 14, QFont.Bold)) self.logger.clicked.connect(lambda: self.display_log_data()) self.logger.setStyleSheet("background-color: white") #self.filterLayout = QtWidgets.QHBoxLayout() self.logFilterLabel = QLabel('Filter', self) self.logFilterLabel.setFont(QFont("Times", 14, QFont.Bold)) self.logFilterLabel.setPalette(get_white_color_text()) self.logFilterLabel.setFixedWidth(60) self.logFilter = QLineEdit(self) self.logFilter.setPalette(get_white_color()) self.logFilter.setStyleSheet("background-color: white") self.logFilter.setFixedWidth(200) #self.filterLayout.addWidget(self.logFilterLabel, QtCore.Qt.AlignLeft) #self.filterLayout.addWidget(self.logFilter, QtCore.Qt.AlignLeft) self.serialList = QComboBox() ports = get_available_serial_ports() if (len(ports) == 1): self.serialList.addItem(ports[0]) self.thread.set_comport(self.serialList.currentText()) else: self.serialList.addItem("Select") for port in ports: self.serialList.addItem(port) self.serialList.currentIndexChanged.connect( lambda: self.set_serial_port()) self.serialList.setStyleSheet("background-color: white") self.clear = QPushButton("Clear Log File", self) self.clear.setStyleSheet("background-color: white") self.clear.setFont(QFont("Times", 14, QFont.Bold)) self.clear.clicked.connect(lambda: self.clear_data()) widget = QFrame(collapsible.get_tree()) widget.setPalette(get_verifone_color()) title = "Logging" self.loggerGrid = QGridLayout(widget) self.loggerGrid.addWidget(self.logger, 0, 0, 1, 2) self.loggerGrid.addWidget(self.logFilterLabel, 1, 0, 1, 1) self.loggerGrid.addWidget(self.logFilter, 1, 1, 1, 1) self.loggerGrid.addWidget(self.serialList, 2, 0, 1, 2) self.loggerGrid.addWidget(self.clear, 3, 0, 1, 2) collapsible.include_section(title, widget) def init_download(self, collapsible): self.download = QPushButton("Download Package", self) self.download.setFont(QFont("Times", 14, QFont.Bold)) self.download.clicked.connect(lambda: self.send_file()) self.download.setStyleSheet("background-color: white") self.loadDownloadFile = QPushButton("Load File", self) self.loadDownloadFile.setFont(QFont("Times", 14, QFont.Bold)) self.loadDownloadFile.clicked.connect(self.loadFromFile) self.loadDownloadFile.setStyleSheet("background-color: white") self.downloadFileName = QLineEdit("File name", self) self.downloadFileName.setStyleSheet("background-color: white") self.downloadFileName.setFixedWidth(300) self.downloadAddress = QLineEdit("IP Address", self) self.downloadAddress.setStyleSheet("background-color: white") self.downloadAddress.setFixedWidth(300) self.downloadStatus = QLabel("Download Status", self) self.downloadStatus.setStyleSheet( "background-color: rgba(3, 169, 229, 0); color : white") self.downloadStatus.setFixedWidth(300) widget = QFrame(collapsible.get_tree()) title = "Download" self.downloadGrid = QGridLayout(widget) self.downloadGrid.addWidget(self.download, 0, 0, 1, 2) self.downloadGrid.addWidget(self.loadDownloadFile, 1, 0, 1, 2) self.downloadGrid.addWidget(self.downloadFileName, 2, 0, 1, 2) self.downloadGrid.addWidget(self.downloadAddress, 3, 0, 1, 2) self.downloadGrid.addWidget(self.downloadStatus, 4, 0, 1, 2) collapsible.include_section(title, widget) def init_analyser(self, collapsible): self.performanceData = QPushButton("View Performance Data", self) self.performanceData.setFont(QFont("Times", 14, QFont.Bold)) self.performanceData.clicked.connect( lambda: self.display_performance_data()) self.performanceData.setStyleSheet("background-color: white") self.performanceChart = QPushButton("View Performance Chart", self) self.performanceChart.setFont(QFont("Times", 14, QFont.Bold)) self.performanceChart.clicked.connect( lambda: self.display_performance_chart()) self.performanceChart.setStyleSheet("background-color: white") widget = QFrame(collapsible.get_tree()) title = "Analyser" self.analyserGrid = QGridLayout(widget) self.analyserGrid.addWidget(self.performanceData, 0, 0, 1, 2) self.analyserGrid.addWidget(self.performanceChart, 1, 0, 1, 2) collapsible.include_section(title, widget) def loadFromFile(self): fileName, _ = QFileDialog.getOpenFileName( self, "Load Package", '', "Download Files (*.tgz);;All Files (*)") if not fileName: return try: in_file = open(str(fileName), 'rb') except IOError: QMessageBox.information( self, "Unable to open file", "There was an error opening \"%s\"" % fileName) return in_file.close() self.downloadFileName.setText(fileName) def createLoggingDisplayLabel(self): # Display Area self.text = QPlainTextEdit(self) self.text.setReadOnly(True) self.text.setFont(QFont("Times", 12, QFont.Bold)) self.text.setTextInteractionFlags(Qt.TextSelectableByMouse | Qt.TextSelectableByKeyboard) def clear_data(self): self.text.clear() os.remove(logfile_path, dir_fd=None) def display_log_data(self): #send_file() if ('COM' in self.serialList.currentText()): self.createLoggingDisplayLabel() self.scrollArea.setWidget(self.text) self.thread.stop() self.thread.start() data = get_data_from_file(logfile_path) if (len(data) > 0 and data != None): self.text.appendPlainText(data) self.logger.setDisabled(True) def get_data(self, data): if (len(data) > 0): logFile = open(logfile_path, "a") logFile.write(data) logFile.close() filterText = self.logFilter.text() if filterText in data.rstrip(): self.text.appendPlainText(data.rstrip()) vbar = self.scrollArea.verticalScrollBar() vbar.setValue(vbar.maximum()) def display_performance_data(self): self.thread.stop() data = get_data_from_file(logfile_path) jsonData = translate_data_to_json(data) self.performanceData = DisplayPerformanceData() self.performanceData.loadCsv( os.path.join(base_log_path, "performance_data.csv")) self.scrollArea.setWidget(self.performanceData) self.logger.setDisabled(False) def display_performance_chart(self): self.thread.stop() self.scrollArea.setWidget(get_performace_chart()) self.logger.setDisabled(False) def set_serial_port(self): self.thread.set_comport(self.serialList.currentText()) def send_file(self): base_path = os.path.join("c:/", "VFI", 'wks', 'global-payment-application', 'GPA', 'output', 'vos2', 'gpa', 'dl.gpa-1.0.0.0-000.tgz') fileName = self.downloadFileName.text() try: in_file = open(str(fileName), 'rb') except IOError: QMessageBox.information( self, "Unable to open file", "There was an error opening \"%s\"" % fileName) return in_file.close() load_vos_package_ip('192.168.0.104', fileName, self.downloadStatus)
class MainWindow(QMainWindow): font: QFont vertical_layout: QVBoxLayout central_widget: QWidget text_box: QPlainTextEdit recognize_button: QPushButton assistant: AssistantInterface def __init__(self, assistant: AssistantInterface): super().__init__() qInitResources() self.assistant = assistant self.build_layout() self.init_handlers() def build_layout(self): self.setup_window() self.setup_styles() self.setup_font() self.build_central_widget() self.build_vertical_layout() self.build_text_box() self.build_recognize_button() QMetaObject.connectSlotsByName(self) def setup_window(self): window_size = QSize(420, 700) self.setObjectName("window") self.resize(window_size) self.setMinimumSize(window_size) self.setMaximumSize(window_size) self.setWindowTitle(u"Voice Assistant") self.setAutoFillBackground(False) def setup_styles(self): file = QFile(":/styles/style.css") file.open(QFile.ReadOnly) byte_array = file.readAll() file.close() self.setStyleSheet(byte_array.data().decode()) def setup_font(self): self.font = QFont() self.font.setFamily(u"Helvetica") self.font.setPointSize(18) def build_central_widget(self): size_policy = QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) size_policy.setHorizontalStretch(0) size_policy.setVerticalStretch(0) self.central_widget = QWidget(self) self.central_widget.setObjectName(u"central_widget") self.central_widget.setSizePolicy(size_policy) self.setCentralWidget(self.central_widget) def build_vertical_layout(self): self.vertical_layout = QVBoxLayout(self.central_widget) self.vertical_layout.setObjectName(u"vertical_layout") def build_text_box(self): text_box_size = QSize(420, 600) self.text_box = QPlainTextEdit(self.central_widget) self.text_box.setObjectName(u"text_box") self.text_box.setMaximumSize(text_box_size) self.text_box.setFont(self.font) self.text_box.setContextMenuPolicy(Qt.NoContextMenu) self.text_box.setUndoRedoEnabled(False) self.text_box.setReadOnly(True) self.text_box.setPlaceholderText("Waiting for your question...") self.vertical_layout.addWidget(self.text_box) def build_recognize_button(self): button_size = QSize(140, 40) self.recognize_button = QPushButton(self.central_widget) self.recognize_button.setObjectName(u"recognize_button") self.recognize_button.setEnabled(True) self.recognize_button.setMinimumSize(button_size) self.recognize_button.setMaximumSize(button_size) self.recognize_button.setFont(self.font) self.recognize_button.setAutoFillBackground(False) self.recognize_button.setText("Recognize") self.recognize_button.setShortcut("Return") self.vertical_layout.addWidget(self.recognize_button, 0, Qt.AlignHCenter) def init_handlers(self): self.recognize_button.pressed.connect(self.start_recognition) self.assistant.on_wake = self.on_assistant_started self.assistant.on_sleep = self.on_assistant_finished self.assistant.on_assistant_listen = self.on_recognize_started self.assistant.on_user_message = self.on_user_text self.assistant.on_assistant_message = self.on_assistant_text def on_assistant_started(self): self.recognize_button.setEnabled(False) def on_assistant_finished(self): self.recognize_button.setEnabled(True) self.recognize_button.setText("Recognize") def on_recognize_started(self): self.async_play_sound() self.recognize_button.setText("Listening...") def on_user_text(self, user_text: str): self.recognize_button.setText("Processing...") self.append_message(f"[You] {user_text}") def on_assistant_text(self, assistant_answer: str): signed_text = f"[{self.assistant.get_name()}] {assistant_answer}" self.append_message(signed_text) def append_message(self, message: str): self.text_box.appendPlainText(f"{message}\n") def start_recognition(self): coroutine = self.assistant.handle() asyncio.create_task(coroutine) @async_function def async_play_sound(self): file = QFile(":/sounds/click.mp3") file.open(QFile.ReadOnly) byte_array = file.readAll() file.close() with tempfile.NamedTemporaryFile("wb", delete=True) as temp: temp.write(byte_array.data()) playsound(temp.name) def closeEvent(self, event: QCloseEvent): for task in asyncio.all_tasks(): task.cancel() asyncio.get_running_loop().stop() async def start(self): self.show()