Source code for pyqt_reactive.widgets.status_bar
"""
Status Bar Widget for PyQt6
Status display with system information and current operation status.
Uses hybrid approach: extracted business logic + clean PyQt6 UI.
"""
import logging
from datetime import datetime
from typing import Optional
from PyQt6.QtWidgets import (
QWidget, QHBoxLayout, QLabel, QProgressBar, QFrame
)
from PyQt6.QtCore import Qt, QTimer, pyqtSignal
from PyQt6.QtGui import QFont
from pyqt_reactive.theming import StyleSheetGenerator
from pyqt_reactive.theming import ColorScheme
logger = logging.getLogger(__name__)
[docs]
class StatusBarWidget(QWidget):
"""
PyQt6 Status Bar Widget.
Displays current status, progress, and system information.
Preserves all business logic from Textual version with clean PyQt6 UI.
"""
# Signals
status_updated = pyqtSignal(str) # status message
[docs]
def __init__(self, color_scheme: Optional[ColorScheme] = None, parent=None):
"""
Initialize the status bar widget.
Args:
color_scheme: Color scheme for styling (optional, uses default if None)
parent: Parent widget
"""
super().__init__(parent)
# Initialize color scheme and style generator
self.color_scheme = color_scheme or ColorScheme()
self.style_generator = StyleSheetGenerator(self.color_scheme)
# Business logic state
self.current_status = "Ready"
self.current_operation = ""
self.progress_value = 0
self.progress_visible = False
# UI components
self.status_label: Optional[QLabel] = None
self.operation_label: Optional[QLabel] = None
self.progress_bar: Optional[QProgressBar] = None
self.time_label: Optional[QLabel] = None
# Timer for time updates
self.time_timer = QTimer()
# Setup UI
self.setup_ui()
self.setup_connections()
self.start_time_updates()
logger.debug("Status bar widget initialized")
[docs]
def setup_ui(self):
"""Setup the user interface."""
layout = QHBoxLayout(self)
layout.setContentsMargins(5, 2, 5, 2)
layout.setSpacing(10)
# Status section
status_frame = self.create_status_section()
layout.addWidget(status_frame)
# Progress section
progress_frame = self.create_progress_section()
layout.addWidget(progress_frame)
# Spacer
layout.addStretch()
# Time section
time_frame = self.create_time_section()
layout.addWidget(time_frame)
# Set styling
self.setStyleSheet(f"""
StatusBarWidget {{
background-color: {self.color_scheme.to_hex(self.color_scheme.panel_bg)};
border-top: 1px solid {self.color_scheme.to_hex(self.color_scheme.border_color)};
color: white;
}}
""")
# Set fixed height
self.setFixedHeight(30)
[docs]
def create_status_section(self) -> QWidget:
"""
Create the status message section.
Returns:
Widget containing status information
"""
frame = QFrame()
layout = QHBoxLayout(frame)
layout.setContentsMargins(0, 0, 0, 0)
# Status icon
status_icon = QLabel("●")
status_icon.setStyleSheet(f"color: {self.color_scheme.to_hex(self.color_scheme.status_success)}; font-weight: bold;")
layout.addWidget(status_icon)
# Status label
self.status_label = QLabel(self.current_status)
self.status_label.setFont(QFont("Arial", 9))
self.status_label.setStyleSheet(f"color: {self.color_scheme.to_hex(self.color_scheme.text_primary)};")
layout.addWidget(self.status_label)
return frame
[docs]
def create_progress_section(self) -> QWidget:
"""
Create the progress section.
Returns:
Widget containing progress information
"""
frame = QFrame()
layout = QHBoxLayout(frame)
layout.setContentsMargins(0, 0, 0, 0)
# Operation label
self.operation_label = QLabel("")
self.operation_label.setFont(QFont("Arial", 8))
self.operation_label.setStyleSheet(f"color: {self.color_scheme.to_hex(self.color_scheme.text_secondary)};")
layout.addWidget(self.operation_label)
# Progress bar
self.progress_bar = QProgressBar()
self.progress_bar.setMaximumWidth(200)
self.progress_bar.setMaximumHeight(16)
self.progress_bar.setVisible(False)
self.progress_bar.setStyleSheet(f"""
QProgressBar {{
border: 1px solid {self.color_scheme.to_hex(self.color_scheme.border_color)};
border-radius: 2px;
background-color: {self.color_scheme.to_hex(self.color_scheme.window_bg)};
color: white;
text-align: center;
font-size: 8px;
}}
QProgressBar::chunk {{
background-color: {self.color_scheme.to_hex(self.color_scheme.selection_bg)};
border-radius: 1px;
}}
""")
layout.addWidget(self.progress_bar)
return frame
[docs]
def create_time_section(self) -> QWidget:
"""
Create the time display section.
Returns:
Widget containing time information
"""
frame = QFrame()
layout = QHBoxLayout(frame)
layout.setContentsMargins(0, 0, 0, 0)
# Time label
self.time_label = QLabel("")
self.time_label.setFont(QFont("Arial", 8))
self.time_label.setStyleSheet(f"color: {self.color_scheme.to_hex(self.color_scheme.text_disabled)};")
self.time_label.setMinimumWidth(120)
self.time_label.setAlignment(Qt.AlignmentFlag.AlignRight)
layout.addWidget(self.time_label)
return frame
[docs]
def setup_connections(self):
"""Setup signal/slot connections."""
self.status_updated.connect(self.update_status_display)
self.time_timer.timeout.connect(self.update_time_display)
[docs]
def start_time_updates(self):
"""Start the time update timer."""
self.time_timer.start(1000) # Update every second
self.update_time_display() # Initial update
[docs]
def update_time_display(self):
"""Update the time display."""
current_time = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
self.time_label.setText(current_time)
[docs]
def set_status(self, message: str, status_type: str = "info"):
"""
Set status message with type.
Args:
message: Status message
status_type: Type of status (info, warning, error, success)
"""
self.current_status = message
self.status_updated.emit(message)
# Update status icon color based on type
if hasattr(self, 'status_label') and self.status_label:
parent_frame = self.status_label.parent()
if parent_frame:
status_icon = parent_frame.findChild(QLabel)
if status_icon and status_icon.text() == "●":
color_map = {
"info": self.color_scheme.to_hex(self.color_scheme.status_info),
"warning": self.color_scheme.to_hex(self.color_scheme.status_warning),
"error": self.color_scheme.to_hex(self.color_scheme.status_error),
"success": self.color_scheme.to_hex(self.color_scheme.status_success)
}
color = color_map.get(status_type, self.color_scheme.to_hex(self.color_scheme.status_success))
status_icon.setStyleSheet(f"color: {color}; font-weight: bold;")
logger.debug(f"Status updated: {message} ({status_type})")
[docs]
def set_operation(self, operation: str):
"""
Set current operation description.
Args:
operation: Operation description
"""
self.current_operation = operation
if self.operation_label:
self.operation_label.setText(operation)
logger.debug(f"Operation updated: {operation}")
[docs]
def show_progress(self, value: int = 0, maximum: int = 100):
"""
Show progress bar with value.
Args:
value: Current progress value
maximum: Maximum progress value
"""
self.progress_visible = True
self.progress_value = value
if self.progress_bar:
self.progress_bar.setMaximum(maximum)
self.progress_bar.setValue(value)
self.progress_bar.setVisible(True)
logger.debug(f"Progress shown: {value}/{maximum}")
[docs]
def update_progress(self, value: int):
"""
Update progress value.
Args:
value: New progress value
"""
self.progress_value = value
if self.progress_bar and self.progress_visible:
self.progress_bar.setValue(value)
[docs]
def hide_progress(self):
"""Hide the progress bar."""
self.progress_visible = False
if self.progress_bar:
self.progress_bar.setVisible(False)
if self.operation_label:
self.operation_label.setText("")
logger.debug("Progress hidden")
[docs]
def update_status_display(self, message: str):
"""
Update the status display.
Args:
message: Status message to display
"""
if self.status_label:
self.status_label.setText(message)
[docs]
def set_info_status(self, message: str):
"""Set info status message."""
self.set_status(message, "info")
[docs]
def set_warning_status(self, message: str):
"""Set warning status message."""
self.set_status(message, "warning")
[docs]
def set_error_status(self, message: str):
"""Set error status message."""
self.set_status(message, "error")
[docs]
def set_success_status(self, message: str):
"""Set success status message."""
self.set_status(message, "success")
[docs]
def closeEvent(self, event):
"""Handle widget close event."""
self.stop_time_updates()
event.accept()