From a613beec442c7e71cc12458d89a07570a5e4e180 Mon Sep 17 00:00:00 2001 From: appleb_m Date: Tue, 9 Dec 2025 16:09:59 +0100 Subject: [PATCH] GUI: Added CheckLienEdit class --- gui/src/aaregui/widgets/number_line_edit.py | 134 +++++++++++++++++++- 1 file changed, 131 insertions(+), 3 deletions(-) diff --git a/gui/src/aaregui/widgets/number_line_edit.py b/gui/src/aaregui/widgets/number_line_edit.py index 0591623c..bd2e62d2 100644 --- a/gui/src/aaregui/widgets/number_line_edit.py +++ b/gui/src/aaregui/widgets/number_line_edit.py @@ -1,7 +1,6 @@ from PySide6.QtCore import Signal, Slot, Qt from PySide6.QtGui import QDoubleValidator -from PySide6.QtWidgets import QLineEdit - +from PySide6.QtWidgets import QLineEdit, QWidget, QCheckBox, QHBoxLayout class NumberLineEdit(QLineEdit): newValue = Signal(float) @@ -15,6 +14,8 @@ class NumberLineEdit(QLineEdit): parent=None, ): super().__init__(parent) + self._read_only: bool = False + self._is_valid: bool = True self.setStyleSheet("background-color: rgb(255, 255, 255);") @@ -44,7 +45,9 @@ class NumberLineEdit(QLineEdit): @Slot(str) def on_text_changed(self, text: str): - if self.validator.validate(text, 0)[0] == QDoubleValidator.State.Acceptable: + #when text changes check validation and change the colour of the line edit + self._is_valid = self.validate(text) + if self._is_valid: self.setStyleSheet("background-color: rgb(255, 255, 255);") else: self.setStyleSheet("background-color: rgb(255, 213, 213);") @@ -83,9 +86,134 @@ class NumberLineEdit(QLineEdit): ) ) + def validate(self, text) -> bool: + return self.validator.validate(str(text), 0)[0] == QDoubleValidator.State.Acceptable + + def setReadOnly(self, ro: bool): + #change state of read only and change colour of line edit based on read only state and validator + super().setReadOnly(ro) + self._read_only = ro + if self._read_only and self._is_valid: + self.setStyleSheet("background-color: rgb(240, 240, 240);") + elif not self._read_only and self._is_valid: + self.setStyleSheet("background-color: rgb(255, 255, 255);") + elif self._read_only and not self._is_valid: + self.setStyleSheet("background-color: rgb(240, 225, 225);") + elif not self._read_only and not self._is_valid: + self.setStyleSheet("background-color: rgb(255, 213, 213);") + else: + print(f"unknown ro state: {self._read_only} or validity {self._is_valid} default to writeable") + self.setStyleSheet("background-color: rgb(255, 255, 255);") + def get_default(self) -> float: return float(self.initial_value) def reset_to_default(self): # Force set to initial default self.force_update_value(self.initial_value) + + +class CheckedLineEdit(QWidget): + newValue = Signal(float) + readOnlyChanged = Signal(bool) + + def __init__(self, min_val: float, max_val: float, /, default: float = 0.0, decimals: int = 2, + check_box_text: str ="", parent = None): + super().__init__(parent) + self._busy = False + self._checked = False + self._internal_value = default + self._external_value = default + + self.check_box = QCheckBox(check_box_text, self) + self.check_box.stateChanged.connect(self._on_checked_toggled) + self.check_box.setChecked(False) + + self.editor = NumberLineEdit(min_val, max_val, default, decimals, self) + self.editor.newValue.connect(self.newValue.emit) + + self.layout = QHBoxLayout(self) + self.layout.setContentsMargins(0, 0, 0, 0) + self.layout.addWidget(self.check_box) + self.layout.addWidget(self.editor) + + def _on_editor_value_changed(self, value_float: float): + if self._checked: + self._internal_value = value_float + self.newValue.emit(value_float) + + def _on_checked_toggled(self, checked: bool): + #when check box is clicked, change read only state of editor + self._checked = checked + if checked: + self.editor.force_update_value(self._internal_value) + self.newValue.emit(self._internal_value) + else: + self.editor.force_update_value(self._external_value) + self.newValue.emit(self._external_value) + self.setReadOnly() + + def set_busy(self, busy: bool): + # if an external wants to change the busy state. + #update self._busy and change editor read only state. After enable/disable check_box and set colour + self._busy = busy + self.setReadOnly() + if self._busy: + self.check_box.setEnabled(False) + self.check_box.setStyleSheet("background-color: rgb(240, 240, 240);") + else: + self.check_box.setEnabled(True) + self.check_box.setStyleSheet("background-color: rgb(240, 240, 240);") + + def update_value(self, value): + #wrapper for NumberLineEdit.update_value + self._external_value = value + if not self._checked: + self.editor.update_value(value) + + def force_update_value(self, value): + #wrapper for NumberLineEdit.force_update_value + self._external_value = value + if not self._checked: + self.editor.force_update_value(value) + self.newValue.emit(value) + + def manual_update(self, value): + self._internal_value = value + self._external_value = value + self.editor.update_value(value) + + @property + def value(self) -> float: + #wrapper for NumberLineEdit.value + return self.editor.value + + def update_limits(self, min_val: float, max_val: float): + #wrapper for NumberLineEdit.update_limits + self.editor.update_limits(min_val, max_val) + + def isChecked(self) -> bool: + #wrapper for check_box.isChecked() + return self.check_box.isChecked() + + def isReadOnly(self) -> bool: + return self.editor.isReadOnly() + + def setReadOnly(self): + # Change editor read only state based on self._busy and self._checked + should_be_ro = True + if not self._busy and self._checked: # Only set editor to writeable if busy is False and the checkbox is checked, + should_be_ro = False + self.editor.setReadOnly(False) + if self.editor.isReadOnly() != should_be_ro: + self.editor.setReadOnly(should_be_ro) + self.readOnlyChanged.emit(should_be_ro) + self.editor.setReadOnly(should_be_ro) + + def get_default(self) -> float: + return float(self._internal_value) + + def reset_to_default(self): + # Force set to initial default + self.force_update_value(self._internal_value) + self.newValue.emit(self._internal_value)