Source code for pyqt_reactive.widgets.shared.button_panel
"""Reusable button panel with declarative configuration.
Extracted from AbstractManagerWidget to allow any widget to use the same
button panel pattern without inheriting from the full manager.
Example:
# Declarative configuration
BUTTON_CONFIGS = [
("Refresh", "refresh", "Refresh the display"),
("Toggle", "toggle_layout", "Toggle layout mode"),
]
# Create panel
panel = ButtonPanel(
button_configs=self.BUTTON_CONFIGS,
style_generator=self.style_generator,
on_action=self.handle_button_action
)
"""
from typing import List, Tuple, Callable, Optional
from PyQt6.QtWidgets import QWidget, QGridLayout, QPushButton
[docs]
class ButtonPanel(QWidget):
"""Reusable button panel with declarative configuration.
Uses BUTTON_CONFIGS format: [(label, action_id, tooltip), ...]
Supports grid layout with configurable columns.
"""
[docs]
def __init__(
self,
button_configs: List[Tuple[str, str, str]],
on_action: Callable[[str], None],
style_generator=None,
grid_columns: int = 0,
parent: Optional[QWidget] = None
):
"""Initialize button panel.
Args:
button_configs: List of (label, action_id, tooltip) tuples
on_action: Callback function(action_id) when button is clicked
style_generator: Optional style generator for button styling
grid_columns: Number of columns (0 = single row)
parent: Parent widget
"""
super().__init__(parent)
self.button_configs = button_configs
self.on_action = on_action
self.style_generator = style_generator
self.grid_columns = grid_columns
self.buttons: dict = {}
self._setup_ui()
def _setup_ui(self):
"""Create the button layout."""
layout = QGridLayout(self)
layout.setContentsMargins(5, 5, 5, 5)
layout.setSpacing(5)
# Determine number of columns (0 means single row)
num_cols = self.grid_columns or len(self.button_configs)
for i, (label, action_id, tooltip) in enumerate(self.button_configs):
button = QPushButton(label)
button.setToolTip(tooltip)
if self.style_generator:
button.setStyleSheet(self.style_generator.generate_button_style())
button.clicked.connect(lambda checked, a=action_id: self.on_action(a))
self.buttons[action_id] = button
row = i // num_cols
col = i % num_cols
layout.addWidget(button, row, col)
[docs]
def set_button_enabled(self, action_id: str, enabled: bool):
"""Enable or disable a button by action_id."""
if action_id in self.buttons:
self.buttons[action_id].setEnabled(enabled)
[docs]
def set_button_text(self, action_id: str, text: str):
"""Update button text by action_id."""
if action_id in self.buttons:
self.buttons[action_id].setText(text)
[docs]
def get_button(self, action_id: str) -> Optional[QPushButton]:
"""Get button widget by action_id."""
return self.buttons.get(action_id)