Coverage for openhcs/pyqt_gui/widgets/status_bar.py: 0.0%
142 statements
« prev ^ index » next coverage.py v7.10.3, created at 2025-08-14 05:57 +0000
« prev ^ index » next coverage.py v7.10.3, created at 2025-08-14 05:57 +0000
1"""
2Status Bar Widget for PyQt6
4Status display with system information and current operation status.
5Uses hybrid approach: extracted business logic + clean PyQt6 UI.
6"""
8import logging
9from datetime import datetime
10from typing import Optional
12from PyQt6.QtWidgets import (
13 QWidget, QHBoxLayout, QLabel, QProgressBar, QFrame
14)
15from PyQt6.QtCore import Qt, QTimer, pyqtSignal
16from PyQt6.QtGui import QFont
18from openhcs.pyqt_gui.shared.style_generator import StyleSheetGenerator
19from openhcs.pyqt_gui.shared.color_scheme import PyQt6ColorScheme
21logger = logging.getLogger(__name__)
24class StatusBarWidget(QWidget):
25 """
26 PyQt6 Status Bar Widget.
28 Displays current status, progress, and system information.
29 Preserves all business logic from Textual version with clean PyQt6 UI.
30 """
32 # Signals
33 status_updated = pyqtSignal(str) # status message
35 def __init__(self, color_scheme: Optional[PyQt6ColorScheme] = None, parent=None):
36 """
37 Initialize the status bar widget.
39 Args:
40 color_scheme: Color scheme for styling (optional, uses default if None)
41 parent: Parent widget
42 """
43 super().__init__(parent)
45 # Initialize color scheme and style generator
46 self.color_scheme = color_scheme or PyQt6ColorScheme()
47 self.style_generator = StyleSheetGenerator(self.color_scheme)
49 # Business logic state
50 self.current_status = "Ready"
51 self.current_operation = ""
52 self.progress_value = 0
53 self.progress_visible = False
55 # UI components
56 self.status_label: Optional[QLabel] = None
57 self.operation_label: Optional[QLabel] = None
58 self.progress_bar: Optional[QProgressBar] = None
59 self.time_label: Optional[QLabel] = None
61 # Timer for time updates
62 self.time_timer = QTimer()
64 # Setup UI
65 self.setup_ui()
66 self.setup_connections()
67 self.start_time_updates()
69 logger.debug("Status bar widget initialized")
71 def setup_ui(self):
72 """Setup the user interface."""
73 layout = QHBoxLayout(self)
74 layout.setContentsMargins(5, 2, 5, 2)
75 layout.setSpacing(10)
77 # Status section
78 status_frame = self.create_status_section()
79 layout.addWidget(status_frame)
81 # Progress section
82 progress_frame = self.create_progress_section()
83 layout.addWidget(progress_frame)
85 # Spacer
86 layout.addStretch()
88 # Time section
89 time_frame = self.create_time_section()
90 layout.addWidget(time_frame)
92 # Set styling
93 self.setStyleSheet(f"""
94 StatusBarWidget {{
95 background-color: {self.color_scheme.to_hex(self.color_scheme.panel_bg)};
96 border-top: 1px solid {self.color_scheme.to_hex(self.color_scheme.border_color)};
97 color: white;
98 }}
99 """)
101 # Set fixed height
102 self.setFixedHeight(30)
104 def create_status_section(self) -> QWidget:
105 """
106 Create the status message section.
108 Returns:
109 Widget containing status information
110 """
111 frame = QFrame()
112 layout = QHBoxLayout(frame)
113 layout.setContentsMargins(0, 0, 0, 0)
115 # Status icon
116 status_icon = QLabel("●")
117 status_icon.setStyleSheet(f"color: {self.color_scheme.to_hex(self.color_scheme.status_success)}; font-weight: bold;")
118 layout.addWidget(status_icon)
120 # Status label
121 self.status_label = QLabel(self.current_status)
122 self.status_label.setFont(QFont("Arial", 9))
123 self.status_label.setStyleSheet(f"color: {self.color_scheme.to_hex(self.color_scheme.text_primary)};")
124 layout.addWidget(self.status_label)
126 return frame
128 def create_progress_section(self) -> QWidget:
129 """
130 Create the progress section.
132 Returns:
133 Widget containing progress information
134 """
135 frame = QFrame()
136 layout = QHBoxLayout(frame)
137 layout.setContentsMargins(0, 0, 0, 0)
139 # Operation label
140 self.operation_label = QLabel("")
141 self.operation_label.setFont(QFont("Arial", 8))
142 self.operation_label.setStyleSheet(f"color: {self.color_scheme.to_hex(self.color_scheme.text_secondary)};")
143 layout.addWidget(self.operation_label)
145 # Progress bar
146 self.progress_bar = QProgressBar()
147 self.progress_bar.setMaximumWidth(200)
148 self.progress_bar.setMaximumHeight(16)
149 self.progress_bar.setVisible(False)
150 self.progress_bar.setStyleSheet(f"""
151 QProgressBar {{
152 border: 1px solid {self.color_scheme.to_hex(self.color_scheme.border_color)};
153 border-radius: 2px;
154 background-color: {self.color_scheme.to_hex(self.color_scheme.window_bg)};
155 color: white;
156 text-align: center;
157 font-size: 8px;
158 }}
159 QProgressBar::chunk {{
160 background-color: {self.color_scheme.to_hex(self.color_scheme.selection_bg)};
161 border-radius: 1px;
162 }}
163 """)
164 layout.addWidget(self.progress_bar)
166 return frame
168 def create_time_section(self) -> QWidget:
169 """
170 Create the time display section.
172 Returns:
173 Widget containing time information
174 """
175 frame = QFrame()
176 layout = QHBoxLayout(frame)
177 layout.setContentsMargins(0, 0, 0, 0)
179 # Time label
180 self.time_label = QLabel("")
181 self.time_label.setFont(QFont("Arial", 8))
182 self.time_label.setStyleSheet(f"color: {self.color_scheme.to_hex(self.color_scheme.text_disabled)};")
183 self.time_label.setMinimumWidth(120)
184 self.time_label.setAlignment(Qt.AlignmentFlag.AlignRight)
185 layout.addWidget(self.time_label)
187 return frame
189 def setup_connections(self):
190 """Setup signal/slot connections."""
191 self.status_updated.connect(self.update_status_display)
192 self.time_timer.timeout.connect(self.update_time_display)
194 def start_time_updates(self):
195 """Start the time update timer."""
196 self.time_timer.start(1000) # Update every second
197 self.update_time_display() # Initial update
199 def stop_time_updates(self):
200 """Stop the time update timer."""
201 self.time_timer.stop()
203 def update_time_display(self):
204 """Update the time display."""
205 current_time = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
206 self.time_label.setText(current_time)
208 def set_status(self, message: str, status_type: str = "info"):
209 """
210 Set status message with type.
212 Args:
213 message: Status message
214 status_type: Type of status (info, warning, error, success)
215 """
216 self.current_status = message
217 self.status_updated.emit(message)
219 # Update status icon color based on type
220 if hasattr(self, 'status_label') and self.status_label:
221 parent_frame = self.status_label.parent()
222 if parent_frame:
223 status_icon = parent_frame.findChild(QLabel)
224 if status_icon and status_icon.text() == "●":
225 color_map = {
226 "info": self.color_scheme.to_hex(self.color_scheme.status_info),
227 "warning": self.color_scheme.to_hex(self.color_scheme.status_warning),
228 "error": self.color_scheme.to_hex(self.color_scheme.status_error),
229 "success": self.color_scheme.to_hex(self.color_scheme.status_success)
230 }
231 color = color_map.get(status_type, self.color_scheme.to_hex(self.color_scheme.status_success))
232 status_icon.setStyleSheet(f"color: {color}; font-weight: bold;")
234 logger.debug(f"Status updated: {message} ({status_type})")
236 def set_operation(self, operation: str):
237 """
238 Set current operation description.
240 Args:
241 operation: Operation description
242 """
243 self.current_operation = operation
244 if self.operation_label:
245 self.operation_label.setText(operation)
247 logger.debug(f"Operation updated: {operation}")
249 def show_progress(self, value: int = 0, maximum: int = 100):
250 """
251 Show progress bar with value.
253 Args:
254 value: Current progress value
255 maximum: Maximum progress value
256 """
257 self.progress_visible = True
258 self.progress_value = value
260 if self.progress_bar:
261 self.progress_bar.setMaximum(maximum)
262 self.progress_bar.setValue(value)
263 self.progress_bar.setVisible(True)
265 logger.debug(f"Progress shown: {value}/{maximum}")
267 def update_progress(self, value: int):
268 """
269 Update progress value.
271 Args:
272 value: New progress value
273 """
274 self.progress_value = value
276 if self.progress_bar and self.progress_visible:
277 self.progress_bar.setValue(value)
279 def hide_progress(self):
280 """Hide the progress bar."""
281 self.progress_visible = False
283 if self.progress_bar:
284 self.progress_bar.setVisible(False)
286 if self.operation_label:
287 self.operation_label.setText("")
289 logger.debug("Progress hidden")
291 def update_status_display(self, message: str):
292 """
293 Update the status display.
295 Args:
296 message: Status message to display
297 """
298 if self.status_label:
299 self.status_label.setText(message)
301 def set_info_status(self, message: str):
302 """Set info status message."""
303 self.set_status(message, "info")
305 def set_warning_status(self, message: str):
306 """Set warning status message."""
307 self.set_status(message, "warning")
309 def set_error_status(self, message: str):
310 """Set error status message."""
311 self.set_status(message, "error")
313 def set_success_status(self, message: str):
314 """Set success status message."""
315 self.set_status(message, "success")
317 def clear_status(self):
318 """Clear status message."""
319 self.set_status("Ready", "info")
321 def closeEvent(self, event):
322 """Handle widget close event."""
323 self.stop_time_updates()
324 event.accept()