diff --git a/src/testium/interpreter/process.py b/src/testium/interpreter/process.py index bb0112e..f79a0ab 100644 --- a/src/testium/interpreter/process.py +++ b/src/testium/interpreter/process.py @@ -8,6 +8,7 @@ import copy from lib.string_queue import StringQueue from lib.tum_except import print_exception, ETUMRuntimeError, ETUMSyntaxError import libs.testium as tm +import interpreter.utils.globdict as globdict from interpreter.utils.params import expanse from interpreter.utils.test_ctrl import TestSetController from interpreter.utils.test_init import ( @@ -255,6 +256,7 @@ Is the python exec path correct ?""" try: test_run_init() print(test_run_header()) + globdict.set_update_queue(self.__squeue) test_set.execute() finally: if test_set.success(): @@ -274,6 +276,7 @@ Is the python exec path correct ?""" engine.join() # Sends signal to the GUI self.send_finished() + globdict.set_update_queue(None) restore_gd(gdict) except Exception as e: print_exception(e) @@ -311,6 +314,9 @@ Is the python exec path correct ?""" "enabled_state": test_set.getEnabledState, "process_param": self.process_param, "set_test_outputs": self.set_test_outputs, + "get_gd_vars": self.get_gd_vars, + "set_gd_var": self.set_gd_var, + "del_gd_var": self.del_gd_var, "set_enabled_state": test_set.setEnabledState, "check_uncheck_all": test_set.checkUncheckAll, "get_folded": test_set.getFolded, @@ -344,6 +350,25 @@ Is the python exec path correct ?""" def set_test_outputs(self, outputs: list): tm.setgd("test_outputs", outputs) + def get_gd_vars(self): + import json + result = {} + for k, v in globdict.global_dict.items(): + if k.startswith("_"): + continue + try: + json.dumps(v) + result[k] = v + except (TypeError, ValueError): + pass + return result + + def set_gd_var(self, name: str, value): + tm.setgd(name, value) + + def del_gd_var(self, name: str): + tm.delgd(name) + def process_control_commands(self, tctrl): term = False while (not term) and (not self.__closed): diff --git a/src/testium/interpreter/utils/globdict.py b/src/testium/interpreter/utils/globdict.py index 6f5ab15..c12721a 100644 --- a/src/testium/interpreter/utils/globdict.py +++ b/src/testium/interpreter/utils/globdict.py @@ -1,3 +1,4 @@ +import json from threading import Lock @@ -5,6 +6,30 @@ global_dict = {} global_dict_lock = Lock() +_update_queue = None + + +def set_update_queue(q): + global _update_queue + _update_queue = q + + +def _push_update(key, value): + if _update_queue is None or key.startswith("_"): + return + try: + json.dumps(value) + _update_queue.put({"type": "gd_update", "key": key, "value": value}) + except (TypeError, ValueError): + pass + + +def _push_delete(key): + if _update_queue is None or key.startswith("_"): + return + _update_queue.put({"type": "gd_delete", "key": key}) + + # Global dictionnary helper functions def gd(name, default=None): ''' Function which returns a variable from the global dictionary of testium @@ -31,6 +56,7 @@ def setgd(name, value): ''' with global_dict_lock: global_dict.update({name: value}) + _push_update(name, value) def delgd(name): ''' Function which removes a variable from the global dictionary of testium @@ -44,6 +70,7 @@ def delgd(name): del global_dict[name] except: pass + _push_delete(name) def cleargd(): with global_dict_lock: diff --git a/src/testium/main_win/f1_win/d_f1_win.py b/src/testium/main_win/f1_win/d_f1_win.py index 8c3112b..c88090a 100644 --- a/src/testium/main_win/f1_win/d_f1_win.py +++ b/src/testium/main_win/f1_win/d_f1_win.py @@ -1,11 +1,16 @@ +import ast +import json import os -import sys -import subprocess import re +import subprocess +import sys -from PySide6.QtWidgets import QDialog +from PySide6.QtWidgets import ( + QDialog, QDialogButtonBox, QHeaderView, QMenu, QMessageBox, + QPushButton, QTextEdit, QVBoxLayout, +) from PySide6.QtGui import QSyntaxHighlighter, QTextCharFormat, QColor, QFont, QDesktopServices -from PySide6.QtCore import Qt, QUrl +from PySide6.QtCore import Qt, QUrl, Slot from main_win.f1_win.f1_win_core import Ui_F1Dialog @@ -16,58 +21,253 @@ class YamlHighlighter(QSyntaxHighlighter): self.highlightingRules = [] - # --- KEY formatting (before colon) --- key_format = QTextCharFormat() - key_format.setForeground(QColor("#268bd2")) # Solarized blue + key_format.setForeground(QColor("#268bd2")) key_format.setFontWeight(QFont.Bold) self.highlightingRules.append((r"^\s*[^:]+(?=:)", key_format)) - # --- VALUE formatting (strings) --- value_format = QTextCharFormat() - value_format.setForeground(QColor("#2aa198")) # teal + value_format.setForeground(QColor("#2aa198")) self.highlightingRules.append((r":\s*[^#\n]+", value_format)) - # --- Booleans (true/false) --- bool_format = QTextCharFormat() - bool_format.setForeground(QColor("#b58900")) # yellow + bool_format.setForeground(QColor("#b58900")) bool_format.setFontWeight(QFont.Bold) self.highlightingRules.append((r"\b(true|false)\b", bool_format)) - # --- Numbers --- num_format = QTextCharFormat() - num_format.setForeground(QColor("#d33682")) # magenta + num_format.setForeground(QColor("#d33682")) self.highlightingRules.append((r"\b[0-9]+\b", num_format)) - # --- Comments (# ...) --- comment_format = QTextCharFormat() - comment_format.setForeground(QColor("#586e75")) # gray + comment_format.setForeground(QColor("#586e75")) self.highlightingRules.append((r"#.*", comment_format)) def highlightBlock(self, text): for pattern, fmt in self.highlightingRules: - for match in re.finditer(pattern, text): start, end = match.span() - self.setFormat(start, end-start, fmt) + self.setFormat(start, end - start, fmt) + + +class GdVarEditDialog(QDialog): + """JSON editor dialog for dict/list values.""" + + def __init__(self, key, value, parent=None): + super().__init__(parent) + self.setWindowTitle(f"Edit: {key}") + self.result_value = None + + layout = QVBoxLayout(self) + + self._edit = QTextEdit() + self._edit.setPlainText(json.dumps(value, indent=2)) + font = QFont("Monospace") + font.setStyleHint(QFont.StyleHint.TypeWriter) + font.setPointSize(9) + self._edit.setFont(font) + layout.addWidget(self._edit) + + buttons = QDialogButtonBox(QDialogButtonBox.StandardButton.Ok | QDialogButtonBox.StandardButton.Cancel) + buttons.accepted.connect(self._on_ok) + buttons.rejected.connect(self.reject) + layout.addWidget(buttons) + + self.resize(400, 300) + + def _on_ok(self): + try: + self.result_value = json.loads(self._edit.toPlainText()) + self.accept() + except json.JSONDecodeError as e: + QMessageBox.warning(self, "Invalid JSON", str(e)) class DialogF1(QDialog): - def __init__(self, parent = None): + def __init__(self, parent=None): super().__init__(parent) self.ui = Ui_F1Dialog() self.ui.setupUi(self) self.highlighter = YamlHighlighter(self.ui.TestContentEdit.document()) - self.setWindowFlags( - Qt.Window | Qt.WindowStaysOnTopHint | Qt.Tool - ) + self.setWindowFlags(Qt.Window | Qt.WindowStaysOnTopHint | Qt.Tool) + self.ui.ButtLocOpen.clicked.connect(self.on_butlocopen_click) self.ui.ButtClose.clicked.connect(self.close) + self._service = None + self._key_rows = {} + self._updating = False + self._mono_font = QFont("Monospace") + self._mono_font.setStyleHint(QFont.StyleHint.TypeWriter) + self._mono_bold_font = QFont("Monospace") + self._mono_bold_font.setStyleHint(QFont.StyleHint.TypeWriter) + self._mono_bold_font.setBold(True) + + self._setup_vars_tab() + + def _setup_vars_tab(self): + table = self.ui.varsTable + table.horizontalHeader().setSectionResizeMode(0, QHeaderView.ResizeMode.ResizeToContents) + table.horizontalHeader().setSectionResizeMode(1, QHeaderView.ResizeMode.Stretch) + table.horizontalHeader().setSectionResizeMode(2, QHeaderView.ResizeMode.Fixed) + table.setColumnWidth(2, 36) + table.verticalHeader().setVisible(False) + table.setContextMenuPolicy(Qt.ContextMenuPolicy.CustomContextMenu) + table.customContextMenuRequested.connect(self._on_context_menu) + table.cellChanged.connect(self._on_cell_changed) + table.setEnabled(False) + self.ui.addVarButton.setEnabled(False) + self.ui.addVarButton.clicked.connect(self._on_add_var) + + def load_initial_vars(self, vars_dict: dict): + for key, value in vars_dict.items(): + self.gd_var_updated(key, value) + + def set_service(self, service): + self._service = service + enabled = service is not None + self.ui.varsTable.setEnabled(enabled) + self.ui.addVarButton.setEnabled(enabled) + if not enabled: + self._updating = True + try: + self.ui.varsTable.setRowCount(0) + finally: + self._updating = False + self._key_rows.clear() + + @Slot(str, object) + def gd_var_updated(self, key, value): + if key in self._key_rows: + self._refresh_row(self._key_rows[key], key, value) + else: + self._updating = True + try: + row = self.ui.varsTable.rowCount() + self.ui.varsTable.insertRow(row) + finally: + self._updating = False + self._key_rows[key] = row + self._refresh_row(row, key, value) + + @Slot(str) + def gd_var_deleted(self, key): + if key not in self._key_rows: + return + row = self._key_rows.pop(key) + self._updating = True + try: + self.ui.varsTable.removeRow(row) + finally: + self._updating = False + self._key_rows = {k: (r - 1 if r > row else r) for k, r in self._key_rows.items()} + + def _refresh_row(self, row, key, value): + from PySide6.QtWidgets import QTableWidgetItem + self._updating = True + try: + table = self.ui.varsTable + + key_item = QTableWidgetItem(key) + key_item.setFlags(key_item.flags() & ~Qt.ItemFlag.ItemIsEditable) + key_item.setFont(self._mono_bold_font) + table.setItem(row, 0, key_item) + + display = self._display_value(value) + val_item = QTableWidgetItem(display) + val_item.setData(Qt.ItemDataRole.UserRole, value) + val_item.setToolTip(self._full_tooltip(value)) + val_item.setFont(self._mono_font) + if self._is_complex(value): + val_item.setFlags(val_item.flags() & ~Qt.ItemFlag.ItemIsEditable) + table.setItem(row, 1, val_item) + + if self._is_complex(value): + btn = QPushButton("[…]") + captured_key = key + btn.clicked.connect(lambda: self._on_edit_complex(captured_key)) + table.setCellWidget(row, 2, btn) + else: + table.setCellWidget(row, 2, None) + table.setItem(row, 2, QTableWidgetItem()) + finally: + self._updating = False + + def _is_complex(self, value): + return isinstance(value, (dict, list)) + + def _display_value(self, value): + if self._is_complex(value): + text = repr(value) + return (text[:60] + "…") if len(text) > 60 else text + return repr(value) + + def _full_tooltip(self, value): + try: + text = json.dumps(value, indent=2) + except (TypeError, ValueError): + text = repr(value) + escaped = text.replace("&", "&").replace("<", "<").replace(">", ">") + return f"
{escaped}
" + + def _on_cell_changed(self, row, col): + if self._updating or col != 1 or self._service is None: + return + from PySide6.QtWidgets import QTableWidgetItem + key_item = self.ui.varsTable.item(row, 0) + val_item = self.ui.varsTable.item(row, 1) + if key_item is None or val_item is None: + return + key = key_item.text() + text = val_item.text() + try: + value = ast.literal_eval(text) + except (ValueError, SyntaxError): + value = text + self._service.set_gd_var(key, value) + + def _on_edit_complex(self, key): + if key not in self._key_rows: + return + val_item = self.ui.varsTable.item(self._key_rows[key], 1) + if val_item is None: + return + value = val_item.data(Qt.ItemDataRole.UserRole) + dlg = GdVarEditDialog(key, value, self) + if dlg.exec() == QDialog.DialogCode.Accepted and self._service is not None: + self._service.set_gd_var(key, dlg.result_value) + + def _on_add_var(self): + key = self.ui.newKeyEdit.text().strip() + value_text = self.ui.newValueEdit.text().strip() + if not key or self._service is None: + return + try: + value = ast.literal_eval(value_text) + except (ValueError, SyntaxError): + value = value_text + self._service.set_gd_var(key, value) + self.ui.newKeyEdit.clear() + self.ui.newValueEdit.clear() + + def _on_context_menu(self, pos): + row = self.ui.varsTable.rowAt(pos.y()) + if row < 0: + return + key_item = self.ui.varsTable.item(row, 0) + if key_item is None or self._service is None: + return + key = key_item.text() + menu = QMenu(self) + delete_action = menu.addAction("Delete") + if menu.exec(self.ui.varsTable.mapToGlobal(pos)) == delete_action: + self._service.del_gd_var(key) + def on_butlocopen_click(self): file = self.ui.sequenceFileNameLineEdit.text() if os.path.exists(file): - if sys.platform.startswith("win"): # Windows + if sys.platform.startswith("win"): subprocess.Popen(f'explorer "{file}"') - else: # Linux / autres + else: subprocess.Popen(["xdg-open", file]) - QDesktopServices.openUrl(QUrl.fromLocalFile(file)) \ No newline at end of file + QDesktopServices.openUrl(QUrl.fromLocalFile(file)) diff --git a/src/testium/main_win/f1_win/f1_win_core.py b/src/testium/main_win/f1_win/f1_win_core.py index 1e2b1e5..4549fb7 100644 --- a/src/testium/main_win/f1_win/f1_win_core.py +++ b/src/testium/main_win/f1_win/f1_win_core.py @@ -3,7 +3,7 @@ ################################################################################ ## Form generated from reading UI file 'f1_win_core.ui' ## -## Created by: Qt User Interface Compiler version 6.10.1 +## Created by: Qt User Interface Compiler version 6.11.0 ## ## WARNING! All changes made in this file will be lost when recompiling UI file! ################################################################################ @@ -16,8 +16,9 @@ from PySide6.QtGui import (QBrush, QColor, QConicalGradient, QCursor, QImage, QKeySequence, QLinearGradient, QPainter, QPalette, QPixmap, QRadialGradient, QTransform) from PySide6.QtWidgets import (QApplication, QDialog, QFormLayout, QHBoxLayout, - QLabel, QLineEdit, QPushButton, QSizePolicy, - QSpacerItem, QTextEdit, QToolButton, QVBoxLayout, + QHeaderView, QLabel, QLineEdit, QPushButton, + QSizePolicy, QSpacerItem, QTabWidget, QTableWidget, + QTableWidgetItem, QTextEdit, QToolButton, QVBoxLayout, QWidget) import f1_win_rc @@ -25,7 +26,7 @@ class Ui_F1Dialog(object): def setupUi(self, F1Dialog): if not F1Dialog.objectName(): F1Dialog.setObjectName(u"F1Dialog") - F1Dialog.resize(400, 300) + F1Dialog.resize(550, 450) icon = QIcon() if QIcon.hasThemeIcon(QIcon.ThemeIcon.HelpAbout): icon = QIcon.fromTheme(QIcon.ThemeIcon.HelpAbout) @@ -36,19 +37,20 @@ class Ui_F1Dialog(object): F1Dialog.setLayoutDirection(Qt.LayoutDirection.LeftToRight) self.verticalLayout_2 = QVBoxLayout(F1Dialog) self.verticalLayout_2.setObjectName(u"verticalLayout_2") - self.horizontalLayout_2 = QHBoxLayout() - self.horizontalLayout_2.setObjectName(u"horizontalLayout_2") - - self.verticalLayout_2.addLayout(self.horizontalLayout_2) - + self.tabWidget = QTabWidget(F1Dialog) + self.tabWidget.setObjectName(u"tabWidget") + self.tabTestItem = QWidget() + self.tabTestItem.setObjectName(u"tabTestItem") + self.verticalLayout_tab0 = QVBoxLayout(self.tabTestItem) + self.verticalLayout_tab0.setObjectName(u"verticalLayout_tab0") self.formLayout = QFormLayout() self.formLayout.setObjectName(u"formLayout") - self.typeLabel = QLabel(F1Dialog) + self.typeLabel = QLabel(self.tabTestItem) self.typeLabel.setObjectName(u"typeLabel") self.formLayout.setWidget(0, QFormLayout.ItemRole.LabelRole, self.typeLabel) - self.typeLineEdit = QLineEdit(F1Dialog) + self.typeLineEdit = QLineEdit(self.tabTestItem) self.typeLineEdit.setObjectName(u"typeLineEdit") sizePolicy = QSizePolicy(QSizePolicy.Policy.Fixed, QSizePolicy.Policy.Fixed) sizePolicy.setHorizontalStretch(0) @@ -59,20 +61,20 @@ class Ui_F1Dialog(object): self.formLayout.setWidget(0, QFormLayout.ItemRole.FieldRole, self.typeLineEdit) - self.sequenceFileNameLabel = QLabel(F1Dialog) + self.sequenceFileNameLabel = QLabel(self.tabTestItem) self.sequenceFileNameLabel.setObjectName(u"sequenceFileNameLabel") self.formLayout.setWidget(1, QFormLayout.ItemRole.LabelRole, self.sequenceFileNameLabel) self.horizontalLayout_3 = QHBoxLayout() self.horizontalLayout_3.setObjectName(u"horizontalLayout_3") - self.sequenceFileNameLineEdit = QLineEdit(F1Dialog) + self.sequenceFileNameLineEdit = QLineEdit(self.tabTestItem) self.sequenceFileNameLineEdit.setObjectName(u"sequenceFileNameLineEdit") self.sequenceFileNameLineEdit.setReadOnly(True) self.horizontalLayout_3.addWidget(self.sequenceFileNameLineEdit) - self.ButtLocOpen = QToolButton(F1Dialog) + self.ButtLocOpen = QToolButton(self.tabTestItem) self.ButtLocOpen.setObjectName(u"ButtLocOpen") self.horizontalLayout_3.addWidget(self.ButtLocOpen) @@ -81,18 +83,61 @@ class Ui_F1Dialog(object): self.formLayout.setLayout(1, QFormLayout.ItemRole.FieldRole, self.horizontalLayout_3) - self.verticalLayout_2.addLayout(self.formLayout) + self.verticalLayout_tab0.addLayout(self.formLayout) - self.label = QLabel(F1Dialog) + self.label = QLabel(self.tabTestItem) self.label.setObjectName(u"label") - self.verticalLayout_2.addWidget(self.label) + self.verticalLayout_tab0.addWidget(self.label) - self.TestContentEdit = QTextEdit(F1Dialog) + self.TestContentEdit = QTextEdit(self.tabTestItem) self.TestContentEdit.setObjectName(u"TestContentEdit") self.TestContentEdit.setReadOnly(True) - self.verticalLayout_2.addWidget(self.TestContentEdit) + self.verticalLayout_tab0.addWidget(self.TestContentEdit) + + self.tabWidget.addTab(self.tabTestItem, "") + self.tabVariables = QWidget() + self.tabVariables.setObjectName(u"tabVariables") + self.verticalLayout_tab1 = QVBoxLayout(self.tabVariables) + self.verticalLayout_tab1.setObjectName(u"verticalLayout_tab1") + self.varsTable = QTableWidget(self.tabVariables) + if (self.varsTable.columnCount() < 3): + self.varsTable.setColumnCount(3) + __qtablewidgetitem = QTableWidgetItem() + self.varsTable.setHorizontalHeaderItem(0, __qtablewidgetitem) + __qtablewidgetitem1 = QTableWidgetItem() + self.varsTable.setHorizontalHeaderItem(1, __qtablewidgetitem1) + __qtablewidgetitem2 = QTableWidgetItem() + self.varsTable.setHorizontalHeaderItem(2, __qtablewidgetitem2) + self.varsTable.setObjectName(u"varsTable") + + self.verticalLayout_tab1.addWidget(self.varsTable) + + self.addVarLayout = QHBoxLayout() + self.addVarLayout.setObjectName(u"addVarLayout") + self.newKeyEdit = QLineEdit(self.tabVariables) + self.newKeyEdit.setObjectName(u"newKeyEdit") + + self.addVarLayout.addWidget(self.newKeyEdit) + + self.newValueEdit = QLineEdit(self.tabVariables) + self.newValueEdit.setObjectName(u"newValueEdit") + + self.addVarLayout.addWidget(self.newValueEdit) + + self.addVarButton = QPushButton(self.tabVariables) + self.addVarButton.setObjectName(u"addVarButton") + self.addVarButton.setMaximumSize(QSize(30, 16777215)) + + self.addVarLayout.addWidget(self.addVarButton) + + + self.verticalLayout_tab1.addLayout(self.addVarLayout) + + self.tabWidget.addTab(self.tabVariables, "") + + self.verticalLayout_2.addWidget(self.tabWidget) self.horizontalLayout = QHBoxLayout() self.horizontalLayout.setObjectName(u"horizontalLayout") @@ -113,6 +158,9 @@ class Ui_F1Dialog(object): self.retranslateUi(F1Dialog) + self.tabWidget.setCurrentIndex(0) + + QMetaObject.connectSlotsByName(F1Dialog) # setupUi @@ -122,6 +170,15 @@ class Ui_F1Dialog(object): self.sequenceFileNameLabel.setText(QCoreApplication.translate("F1Dialog", u"Test file name", None)) self.ButtLocOpen.setText(QCoreApplication.translate("F1Dialog", u"...", None)) self.label.setText(QCoreApplication.translate("F1Dialog", u"Test content:", None)) + self.tabWidget.setTabText(self.tabWidget.indexOf(self.tabTestItem), QCoreApplication.translate("F1Dialog", u"Test item", None)) + ___qtablewidgetitem = self.varsTable.horizontalHeaderItem(0) + ___qtablewidgetitem.setText(QCoreApplication.translate("F1Dialog", u"Key", None)) + ___qtablewidgetitem1 = self.varsTable.horizontalHeaderItem(1) + ___qtablewidgetitem1.setText(QCoreApplication.translate("F1Dialog", u"Value", None)) + self.newKeyEdit.setPlaceholderText(QCoreApplication.translate("F1Dialog", u"New key", None)) + self.newValueEdit.setPlaceholderText(QCoreApplication.translate("F1Dialog", u"Value", None)) + self.addVarButton.setText(QCoreApplication.translate("F1Dialog", u"+", None)) + self.tabWidget.setTabText(self.tabWidget.indexOf(self.tabVariables), QCoreApplication.translate("F1Dialog", u"Variables", None)) self.ButtClose.setText(QCoreApplication.translate("F1Dialog", u"Close", None)) # retranslateUi diff --git a/src/testium/main_win/f1_win/f1_win_core.ui b/src/testium/main_win/f1_win/f1_win_core.ui index fb48f24..93727b1 100644 --- a/src/testium/main_win/f1_win/f1_win_core.ui +++ b/src/testium/main_win/f1_win/f1_win_core.ui @@ -6,8 +6,8 @@ 0 0 - 400 - 300 + 550 + 450 @@ -22,69 +22,139 @@ - - - - - - - - Test step type - - - - - - - - 0 - 0 - - - - true - - - - - - - Test file name - - - - - + + + 0 + + + + + Test item + + - + + + + + Test step type + + + + + + + + 0 + 0 + + + + true + + + + + + + Test file name + + + + + + + + + true + + + + + + + ... + + + + + + + + + + + Test content: + + + + + true + + + + + + Variables + + - - - ... - + + + + Key + + + + + Value + + + + + + + + + + + + + New key + + + + + + + Value + + + + + + + + + + + + 30 + 16777215 + + + + + + - - - - - - - Test content: - - - - - - - true - + diff --git a/src/testium/main_win/test_controller_service.py b/src/testium/main_win/test_controller_service.py index 33583f4..2c26b07 100644 --- a/src/testium/main_win/test_controller_service.py +++ b/src/testium/main_win/test_controller_service.py @@ -69,3 +69,12 @@ class TestControllerService: def set_test_outputs(self, outputs: list) -> None: self._ctrl.control("set_test_outputs", outputs=outputs) + + def get_gd_vars(self) -> dict: + return self._ctrl.control("get_gd_vars") + + def set_gd_var(self, name: str, value) -> None: + self._ctrl.control("set_gd_var", name=name, value=value) + + def del_gd_var(self, name: str) -> None: + self._ctrl.control("del_gd_var", name=name) diff --git a/src/testium/main_win/test_file_manager.py b/src/testium/main_win/test_file_manager.py index fa35b14..fbe4d9e 100644 --- a/src/testium/main_win/test_file_manager.py +++ b/src/testium/main_win/test_file_manager.py @@ -41,6 +41,7 @@ class TestFileManager: w.test_proc = None del w.test_service w.test_service = None + w.d_f1_win.set_service(None) del w.ts_controller w.ts_controller = None @@ -89,6 +90,7 @@ class TestFileManager: w.testFile = None w.ts_controller = TestSetController() w.test_service = TestControllerService(w.ts_controller) + w.d_f1_win.set_service(w.test_service) w.test_proc = TestProcess( file_name, w.status_queue, @@ -112,6 +114,7 @@ class TestFileManager: w.test_proc = None del w.test_service w.test_service = None + w.d_f1_win.set_service(None) del w.ts_controller w.ts_controller = None raise ETUMRuntimeError( @@ -128,6 +131,7 @@ class TestFileManager: progress = None w.treeTests.setFoldDefault() w.treeTests.updateTreeSkipState(w.test_service) + w.d_f1_win.load_initial_vars(w.test_service.get_gd_vars()) w.checkSelect.setChecked(True) w.testFile = file_name diff --git a/src/testium/main_win/test_run/test_run.py b/src/testium/main_win/test_run/test_run.py index 9ad0480..fba9a59 100644 --- a/src/testium/main_win/test_run/test_run.py +++ b/src/testium/main_win/test_run/test_run.py @@ -6,6 +6,8 @@ from PySide6.QtCore import (Signal, QThread) class ThreadTestStatus(QThread): statusToBeUpdated = Signal(dict) testSetIsFinished = Signal() + gdUpdated = Signal(str, object) + gdDeleted = Signal(str) def __init__(self, status_queue, parent=None, debug=False): super().__init__(parent) @@ -21,7 +23,12 @@ class ThreadTestStatus(QThread): while True: while not self._status_queue.empty(): m = self._status_queue.get() - if m.get("id", None) is None: + msg_type = m.get("type") + if msg_type == "gd_update": + self.gdUpdated.emit(m["key"], m["value"]) + elif msg_type == "gd_delete": + self.gdDeleted.emit(m["key"]) + elif m.get("id", None) is None: self.testSetIsFinished.emit() else: self.statusToBeUpdated.emit(m) diff --git a/src/testium/main_win/testium_win.py b/src/testium/main_win/testium_win.py index 6631b13..4088f2a 100755 --- a/src/testium/main_win/testium_win.py +++ b/src/testium/main_win/testium_win.py @@ -247,6 +247,8 @@ class MainWindow(QMainWindow, Ui_MainWindow): self.threadTestStatus.testSetIsFinished.connect(self.runner.on_run_finished) self.threadTestStatus.statusToBeUpdated.connect(self.treeTests.updateStatus) + self.threadTestStatus.gdUpdated.connect(self.d_f1_win.gd_var_updated) + self.threadTestStatus.gdDeleted.connect(self.d_f1_win.gd_var_deleted) self.reconnect_signals() if runandclose: