# --- REPLACE the entire content of ui/widgets.py with this --- from PyQt6.QtWidgets import ( QGroupBox, QVBoxLayout, QHBoxLayout, QLabel, QLineEdit, QFrame, QPushButton, QFormLayout ) from PyQt6.QtCore import Qt, pyqtSignal # <-- IMPORT pyqtSignal from PyQt6.QtGui import QFont class ChamberWidget(QGroupBox): # --- ADD SIGNALS HERE --- open_door_requested = pyqtSignal() chg_on_requested = pyqtSignal() chg_off_requested = pyqtSignal() def __init__(self, title="CHAMBER - X", scale=1.0): super().__init__(title) self.setObjectName("ChamberWidget") self.setFont(QFont("Arial", max(8, int(9 * scale)), QFont.Weight.Bold)) main_layout = QVBoxLayout(self) main_layout.setSpacing(max(2, int(4 * scale))) id_layout = QHBoxLayout() id_layout.addWidget(QLabel("BAT ID: ")) self.id_field = self._create_data_field(scale) self.id_field.setObjectName("BatIdField") # Set object name for styling id_layout.addWidget(self.id_field) main_layout.addLayout(id_layout) columns_layout = QHBoxLayout() battery_form_layout = QFormLayout() battery_form_layout.setVerticalSpacing(max(2, int(4 * scale))) self.battery_status_label = self._create_status_label("ABSENT", scale) self.battery_status_label.setProperty("status", "absent") # --- SET OBJECT NAMES FOR EACH DATA FIELD --- self.soc_field = self._create_data_field(scale) self.soc_field.setObjectName("DataField") self.voltage_field = self._create_data_field(scale) self.voltage_field.setObjectName("DataField") self.temp_field = self._create_data_field(scale) self.temp_field.setObjectName("DataField") self.battery_fault_field = self._create_data_field(scale) self.battery_fault_field.setObjectName("DataField") # --- END OF OBJECT NAMES --- battery_form_layout.addRow("Status:", self.battery_status_label) battery_form_layout.addRow("SOC:", self.soc_field) battery_form_layout.addRow("Voltage:", self.voltage_field) battery_form_layout.addRow("Temp:", self.temp_field) battery_form_layout.addRow("Fault:", self.battery_fault_field) separator_line = QFrame() separator_line.setFrameShape(QFrame.Shape.VLine) separator_line.setFrameShadow(QFrame.Shadow.Sunken) charger_form_layout = QFormLayout() charger_form_layout.setVerticalSpacing(max(2, int(4 * scale))) self.charger_status_label = self._create_status_label("OFF", scale) self.charger_status_label.setProperty("status", "absent") # --- SET OBJECT NAMES FOR EACH DATA FIELD --- self.slot_temp_field = self._create_data_field(scale) self.slot_temp_field.setObjectName("DataField") self.chg_temp_field = self._create_data_field(scale) self.chg_temp_field.setObjectName("DataField") self.door_status_field = self._create_data_field(scale) self.door_status_field.setObjectName("DoorStatusField") self.charger_fault_field = self._create_data_field(scale) self.charger_fault_field.setObjectName("DataField") # --- END OF OBJECT NAMES --- charger_form_layout.addRow("Chg Status:", self.charger_status_label) charger_form_layout.addRow("Chg Temp:", self.chg_temp_field) charger_form_layout.addRow("Slot Temp:", self.slot_temp_field) charger_form_layout.addRow("Door Status:", self.door_status_field) charger_form_layout.addRow("Fault:", self.charger_fault_field) columns_layout.addLayout(battery_form_layout) columns_layout.addWidget(separator_line) columns_layout.addLayout(charger_form_layout) main_layout.addLayout(columns_layout) main_layout.addStretch() button_layout = QHBoxLayout() self.open_door_btn = QPushButton("OPEN DOOR") self.chg_on_btn = QPushButton("CHG ON") self.chg_off_btn = QPushButton("CHG OFF") self.open_door_btn.setObjectName("ChamberOpenDoorButton") self.chg_on_btn.setObjectName("ChamberChgOnButton") self.chg_off_btn.setObjectName("ChamberChgOffButton") self.open_door_btn.clicked.connect(self.open_door_requested.emit) self.chg_on_btn.clicked.connect(self.chg_on_requested.emit) self.chg_off_btn.clicked.connect(self.chg_off_requested.emit) button_layout.addWidget(self.open_door_btn) button_layout.addWidget(self.chg_on_btn) button_layout.addWidget(self.chg_off_btn) main_layout.addLayout(button_layout) # ... (the rest of the class is unchanged) ... def _create_status_label(self, text, scale): label = QLabel(text) label.setAlignment(Qt.AlignmentFlag.AlignCenter) label.setFont(QFont("Arial", max(7, int(8 * scale)), QFont.Weight.Bold)) return label def _create_data_field(self, scale): field = QLineEdit("N/A") field.setReadOnly(True) field.setFont(QFont("Arial", max(7, int(8 * scale)))) return field def update_data(self, data): if data.get("batteryPresent") == 1: self.battery_status_label.setText("PRESENT") self.battery_status_label.setProperty("status", "present") else: self.battery_status_label.setText("ABSENT") self.battery_status_label.setProperty("status", "absent") if data.get("chargerPresent") == 1: self.charger_status_label.setText("CHARGER ON") self.charger_status_label.setProperty("status", "present") else: self.charger_status_label.setText("CHARGER OFF") self.charger_status_label.setProperty("status", "absent") for widget in [self.battery_status_label, self.charger_status_label]: widget.style().unpolish(widget) widget.style().polish(widget) self.id_field.setText(data.get("batteryIdentification", "N/A")) self.soc_field.setText(f'{data.get("soc", 0)}%') self.voltage_field.setText(f'{data.get("voltage", 0) / 1000.0:.2f} V') self.temp_field.setText(f'{data.get("batteryMaxTemp", 0) / 10.0:.1f} °C') self.battery_fault_field.setText(str(data.get("batteryFaultCode", 0))) self.slot_temp_field.setText(f'{data.get("slotTemperature", 0) / 10.0:.1f} °C') self.chg_temp_field.setText(f'{data.get("chargerTemp", 0) / 10.0:.1f} °C') self.charger_fault_field.setText(str(data.get("chargerFaultCode", 0))) door_status = "OPEN" if data.get("doorStatus") == 1 else "CLOSED" self.door_status_field.setText(door_status) def reset_to_default(self): """Resets all fields in this chamber widget to their default state.""" self.battery_status_label.setText("ABSENT") self.battery_status_label.setProperty("status", "absent") self.charger_status_label.setText("CHARGER OFF") self.charger_status_label.setProperty("status", "absent") # Re-apply the stylesheet for the status labels for widget in [self.battery_status_label, self.charger_status_label]: widget.style().unpolish(widget) widget.style().polish(widget) self.id_field.setText("N/A") self.soc_field.setText("N/A") self.voltage_field.setText("N/A") self.temp_field.setText("N/A") self.battery_fault_field.setText("N/A") self.slot_temp_field.setText("N/A") self.chg_temp_field.setText("N/A") self.door_status_field.setText("N/A") self.charger_fault_field.setText("N/A")