diff --git a/docs/release-notes.rst b/docs/release-notes.rst index 0bd008e..3a64991 100644 --- a/docs/release-notes.rst +++ b/docs/release-notes.rst @@ -1,6 +1,22 @@ ================================== Release Notes ================================== +************* +Version 0.7.0 +************* +Release Date 24/07/2026 + +Major Changes +################ +- New major version! This should have been done in the last update when python 3.8 to 3.11 was dropped. Doing it here now. + +New Features +############ +- Font size for buttons increased. +- Image scene now shows "TEST PASS" or "TEST FAIL" on sequence end. +- Added --user-id flag to be able to log which user ran a test. Defaults to 'None' if not provided. + + ************* Version 0.6.5 diff --git a/src/fixate/__init__.py b/src/fixate/__init__.py index 39ff3a3..653eba9 100644 --- a/src/fixate/__init__.py +++ b/src/fixate/__init__.py @@ -51,4 +51,4 @@ from fixate.main import run_main_program as run -__version__ = "0.6.5" +__version__ = "0.7.0" diff --git a/src/fixate/config/__init__.py b/src/fixate/config/__init__.py index 7a66238..72f9e17 100644 --- a/src/fixate/config/__init__.py +++ b/src/fixate/config/__init__.py @@ -56,6 +56,7 @@ "report-format={REPORT_FORMAT_VERSION}", "index_string={index}", "computername={COMPUTERNAME}", + "user_id={user_id}", ], } diff --git a/src/fixate/main.py b/src/fixate/main.py index 1db36bd..f9f93b5 100644 --- a/src/fixate/main.py +++ b/src/fixate/main.py @@ -117,6 +117,7 @@ def get_parser(): action="store_true", help="The sequencer will not prompt for retries.", ) + parser.add_argument("--user-id", help="ID of the user running the test") diagnostic_group = parser.add_mutually_exclusive_group() diagnostic_group.add_argument( "--disable-logs", action="store_true", help="Turn off diagnostic logs" @@ -289,6 +290,9 @@ def ui_run(self): if self.args.non_interactive: self.sequencer.non_interactive = True + if self.args.user_id: + self.sequencer.context_data["user_id"] = self.args.user_id + # parse script params for param in self.args.script_params: k, v = param.split("=") diff --git a/src/fixate/ui_gui_qt/layout.py b/src/fixate/ui_gui_qt/layout.py index 7812848..98143c3 100644 --- a/src/fixate/ui_gui_qt/layout.py +++ b/src/fixate/ui_gui_qt/layout.py @@ -212,6 +212,7 @@ def setupUi(self, FixateUI): self.ButtonLayout.setSpacing(100) self.ButtonLayout.setObjectName("ButtonLayout") self.Button_1 = QtWidgets.QPushButton(self.MainWindow) + self.Button_1.setStyleSheet("font-size: 12pt;") self.Button_1.setEnabled(False) sizePolicy = QtWidgets.QSizePolicy( QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding @@ -227,6 +228,7 @@ def setupUi(self, FixateUI): self.Button_1.setObjectName("Button_1") self.ButtonLayout.addWidget(self.Button_1) self.Button_2 = QtWidgets.QPushButton(self.MainWindow) + self.Button_2.setStyleSheet("font-size: 12pt;") self.Button_2.setEnabled(False) sizePolicy = QtWidgets.QSizePolicy( QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding @@ -239,6 +241,7 @@ def setupUi(self, FixateUI): self.Button_2.setObjectName("Button_2") self.ButtonLayout.addWidget(self.Button_2) self.Button_3 = QtWidgets.QPushButton(self.MainWindow) + self.Button_3.setStyleSheet("font-size: 12pt;") self.Button_3.setEnabled(False) sizePolicy = QtWidgets.QSizePolicy( QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding diff --git a/src/fixate/ui_gui_qt/ui_gui_qt.py b/src/fixate/ui_gui_qt/ui_gui_qt.py index 55f2395..c8993b3 100644 --- a/src/fixate/ui_gui_qt/ui_gui_qt.py +++ b/src/fixate/ui_gui_qt/ui_gui_qt.py @@ -94,6 +94,7 @@ class FixateGUI(QtWidgets.QMainWindow, layout.Ui_FixateUI): sig_image_update = pyqtSignal(str) sig_gif_update = pyqtSignal(str) sig_image_clear = pyqtSignal() + sig_image_result = pyqtSignal(str, str) # Progress Signals sig_indicator_start = pyqtSignal() @@ -181,6 +182,7 @@ def bind_qt_signals(self): self.sig_image_update.connect(self.on_image_update) self.sig_gif_update.connect(self.on_gif_update) self.sig_image_clear.connect(self.on_image_clear) + self.sig_image_result.connect(self._show_sequence_result) self.sig_button_reset.connect(self.on_button_reset) self.sig_progress_set_max.connect(self.on_progress_set_max) @@ -353,6 +355,32 @@ def on_image_clear(self): self.ImageView.set_scene(self.image_scene) self.ImageView.setScene(self.image_scene) + def _show_sequence_result(self, text, fill_colour): + """ + Uses the image window to show overall sequence status. + Paints entire background with 'fill_colour', and centers 'text' on screen. + """ + self.on_image_clear() + self.ImageView.setBackgroundBrush(QtGui.QBrush(QtGui.QColor(fill_colour))) + + viewport_rect = self.ImageView.viewport().rect() + scene_width = viewport_rect.width() + scene_height = viewport_rect.height() + text_item = self.image_scene.addText( + text, QtGui.QFont("Arial", 14, QtGui.QFont.Bold) + ) + text_item.setDefaultTextColor(QtGui.QColor("white")) + + text_bounds = text_item.boundingRect() + text_item.setPos( + (scene_width - text_bounds.width()) / 2, + (scene_height - text_bounds.height()) / 2, + ) + + scene_rect = QRectF(0, 0, scene_width, scene_height) + self.image_scene.setSceneRect(scene_rect) + self.ImageView.fitInView(scene_rect, Qt.KeepAspectRatio) + def file_not_found(self, path): """ Display warning box for an invalid image path @@ -834,6 +862,12 @@ def _topic_Sequence_Complete( self.sig_active_update.emit(self._reformat_text("Status: {}".format(status))) self.sig_history_update.emit("#" * wrapper.width) + # Emit signal to update the image window: + if status == "PASSED": + self.sig_image_result.emit("TEST PASS", "#2ECC71") + elif status != "PASSED": + self.sig_image_result.emit("TEST FAIL", "#E74C3C") + def _print_test_start(self, data, test_index): if self.closing: return