feat: Widget Registry - plugins register widgets dynamically
This commit is contained in:
parent
3ee405475f
commit
defb83d213
|
|
@ -1590,55 +1590,55 @@ class OverlayWindow(QMainWindow):
|
||||||
layout.addWidget(header)
|
layout.addWidget(header)
|
||||||
|
|
||||||
# Description
|
# Description
|
||||||
desc = QLabel("Add overlay widgets to your game. Drag to position, resize, and configure.")
|
desc = QLabel("Add overlay widgets to your game. Install plugins to get more widgets.")
|
||||||
desc.setStyleSheet(f"color: {c['text_secondary']}; font-size: 12px;")
|
desc.setStyleSheet(f"color: {c['text_secondary']}; font-size: 12px;")
|
||||||
desc.setWordWrap(True)
|
desc.setWordWrap(True)
|
||||||
layout.addWidget(desc)
|
layout.addWidget(desc)
|
||||||
|
|
||||||
# Built-in widgets section
|
# Get registered widgets
|
||||||
builtin_header = QLabel("Built-in Widgets")
|
from core.widget_registry import get_widget_registry
|
||||||
builtin_header.setStyleSheet(f"""
|
registry = get_widget_registry()
|
||||||
color: {c['text_primary']};
|
widgets = registry.get_all_widgets()
|
||||||
font-weight: {EU_TYPOGRAPHY['weight_bold']};
|
|
||||||
font-size: 14px;
|
|
||||||
margin-top: 16px;
|
|
||||||
padding-bottom: 8px;
|
|
||||||
border-bottom: 1px solid {c['border_default']};
|
|
||||||
""")
|
|
||||||
layout.addWidget(builtin_header)
|
|
||||||
|
|
||||||
# Clock widget button
|
if widgets:
|
||||||
clock_btn = self._create_widget_button(
|
# Available widgets section
|
||||||
"⏰ Clock",
|
available_header = QLabel("Available Widgets")
|
||||||
"A customizable clock with 12/24h format and date display",
|
available_header.setStyleSheet(f"""
|
||||||
lambda: self._add_clock_widget()
|
color: {c['text_primary']};
|
||||||
)
|
font-weight: {EU_TYPOGRAPHY['weight_bold']};
|
||||||
layout.addWidget(clock_btn)
|
font-size: 14px;
|
||||||
|
margin-top: 16px;
|
||||||
# System monitor widget button
|
padding-bottom: 8px;
|
||||||
monitor_btn = self._create_widget_button(
|
border-bottom: 1px solid {c['border_default']};
|
||||||
"📊 System Monitor",
|
""")
|
||||||
"Monitor CPU and RAM usage in real-time",
|
layout.addWidget(available_header)
|
||||||
lambda: self._add_system_monitor_widget()
|
|
||||||
)
|
# Create buttons for each registered widget
|
||||||
layout.addWidget(monitor_btn)
|
for widget_info in widgets:
|
||||||
|
widget_btn = self._create_widget_button(
|
||||||
# Plugin widgets section
|
f"{widget_info.icon} {widget_info.name}",
|
||||||
plugin_header = QLabel("Plugin Widgets")
|
widget_info.description,
|
||||||
plugin_header.setStyleSheet(f"""
|
lambda wid=widget_info.id: self._add_registered_widget(wid)
|
||||||
color: {c['text_primary']};
|
)
|
||||||
font-weight: {EU_TYPOGRAPHY['weight_bold']};
|
layout.addWidget(widget_btn)
|
||||||
font-size: 14px;
|
else:
|
||||||
margin-top: 24px;
|
# No widgets available
|
||||||
padding-bottom: 8px;
|
no_widgets = QLabel("No widgets available")
|
||||||
border-bottom: 1px solid {c['border_default']};
|
no_widgets.setStyleSheet(f"""
|
||||||
""")
|
color: {c['text_muted']};
|
||||||
layout.addWidget(plugin_header)
|
font-size: 14px;
|
||||||
|
font-style: italic;
|
||||||
plugin_info = QLabel("Install plugins from the Plugin Store to add more widgets here.")
|
margin-top: 24px;
|
||||||
plugin_info.setStyleSheet(f"color: {c['text_muted']}; font-size: 12px; font-style: italic;")
|
""")
|
||||||
plugin_info.setWordWrap(True)
|
no_widgets.setAlignment(Qt.AlignmentFlag.AlignCenter)
|
||||||
layout.addWidget(plugin_info)
|
layout.addWidget(no_widgets)
|
||||||
|
|
||||||
|
# Install info
|
||||||
|
install_info = QLabel("Install plugins from the Plugin Store to add widgets here.")
|
||||||
|
install_info.setStyleSheet(f"color: {c['text_muted']}; font-size: 12px;")
|
||||||
|
install_info.setWordWrap(True)
|
||||||
|
install_info.setAlignment(Qt.AlignmentFlag.AlignCenter)
|
||||||
|
layout.addWidget(install_info)
|
||||||
|
|
||||||
layout.addStretch()
|
layout.addStretch()
|
||||||
|
|
||||||
|
|
@ -1732,13 +1732,17 @@ class OverlayWindow(QMainWindow):
|
||||||
|
|
||||||
return tab
|
return tab
|
||||||
|
|
||||||
def _add_clock_widget(self):
|
def _add_registered_widget(self, widget_id: str):
|
||||||
"""Add a clock widget to the overlay."""
|
"""Add a registered widget to the overlay."""
|
||||||
try:
|
try:
|
||||||
from core.widget_system import ClockWidget
|
from core.widget_registry import get_widget_registry
|
||||||
|
registry = get_widget_registry()
|
||||||
|
|
||||||
# Create widget with self as parent
|
# Create widget using registry
|
||||||
widget = ClockWidget(parent=self)
|
widget = registry.create_widget(widget_id)
|
||||||
|
if not widget:
|
||||||
|
print(f"[Overlay] Failed to create widget: {widget_id}")
|
||||||
|
return
|
||||||
|
|
||||||
# Position near center of screen
|
# Position near center of screen
|
||||||
screen = QApplication.primaryScreen().geometry()
|
screen = QApplication.primaryScreen().geometry()
|
||||||
|
|
@ -1756,38 +1760,8 @@ class OverlayWindow(QMainWindow):
|
||||||
self._active_widgets = []
|
self._active_widgets = []
|
||||||
self._active_widgets.append(widget)
|
self._active_widgets.append(widget)
|
||||||
|
|
||||||
print(f"[Overlay] Clock widget added at ({x}, {y})")
|
print(f"[Overlay] Widget {widget_id} added at ({x}, {y})")
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(f"[Overlay] Error adding clock widget: {e}")
|
print(f"[Overlay] Error adding widget {widget_id}: {e}")
|
||||||
import traceback
|
|
||||||
traceback.print_exc()
|
|
||||||
|
|
||||||
def _add_system_monitor_widget(self):
|
|
||||||
"""Add a system monitor widget to the overlay."""
|
|
||||||
try:
|
|
||||||
from core.widget_system import SystemMonitorWidget
|
|
||||||
|
|
||||||
# Create widget with self as parent
|
|
||||||
widget = SystemMonitorWidget(parent=self)
|
|
||||||
|
|
||||||
# Position below the clock
|
|
||||||
screen = QApplication.primaryScreen().geometry()
|
|
||||||
x = (screen.width() - 200) // 2
|
|
||||||
y = (screen.height() - 100) // 2 + 120
|
|
||||||
widget.move(x, y)
|
|
||||||
|
|
||||||
# Show and raise
|
|
||||||
widget.show()
|
|
||||||
widget.raise_()
|
|
||||||
widget.activateWindow()
|
|
||||||
|
|
||||||
# Store reference to prevent garbage collection
|
|
||||||
if not hasattr(self, '_active_widgets'):
|
|
||||||
self._active_widgets = []
|
|
||||||
self._active_widgets.append(widget)
|
|
||||||
|
|
||||||
print(f"[Overlay] System monitor widget added at ({x}, {y})")
|
|
||||||
except Exception as e:
|
|
||||||
print(f"[Overlay] Error adding system monitor widget: {e}")
|
|
||||||
import traceback
|
import traceback
|
||||||
traceback.print_exc()
|
traceback.print_exc()
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,99 @@
|
||||||
|
"""
|
||||||
|
EU-Utility - Widget Registry
|
||||||
|
|
||||||
|
Allows plugins to register widgets that appear in the Widgets tab.
|
||||||
|
"""
|
||||||
|
|
||||||
|
from typing import Dict, List, Callable, Optional
|
||||||
|
from dataclasses import dataclass
|
||||||
|
from PyQt6.QtWidgets import QWidget
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class WidgetInfo:
|
||||||
|
"""Information about a registered widget."""
|
||||||
|
id: str
|
||||||
|
name: str
|
||||||
|
description: str
|
||||||
|
icon: str # emoji or icon name
|
||||||
|
creator: Callable[[], QWidget] # Function that creates the widget
|
||||||
|
plugin_id: str # Which plugin registered this
|
||||||
|
|
||||||
|
|
||||||
|
class WidgetRegistry:
|
||||||
|
"""Registry for plugin-provided widgets."""
|
||||||
|
|
||||||
|
_instance = None
|
||||||
|
|
||||||
|
def __new__(cls):
|
||||||
|
if cls._instance is None:
|
||||||
|
cls._instance = super().__new__(cls)
|
||||||
|
cls._instance._widgets: Dict[str, WidgetInfo] = {}
|
||||||
|
return cls._instance
|
||||||
|
|
||||||
|
def register_widget(
|
||||||
|
self,
|
||||||
|
widget_id: str,
|
||||||
|
name: str,
|
||||||
|
description: str,
|
||||||
|
icon: str,
|
||||||
|
creator: Callable[[], QWidget],
|
||||||
|
plugin_id: str = "unknown"
|
||||||
|
):
|
||||||
|
"""Register a widget.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
widget_id: Unique identifier for this widget type
|
||||||
|
name: Display name
|
||||||
|
description: Short description shown in UI
|
||||||
|
icon: Emoji or icon name
|
||||||
|
creator: Function that returns a QWidget instance
|
||||||
|
plugin_id: ID of the plugin registering this widget
|
||||||
|
"""
|
||||||
|
self._widgets[widget_id] = WidgetInfo(
|
||||||
|
id=widget_id,
|
||||||
|
name=name,
|
||||||
|
description=description,
|
||||||
|
icon=icon,
|
||||||
|
creator=creator,
|
||||||
|
plugin_id=plugin_id
|
||||||
|
)
|
||||||
|
print(f"[WidgetRegistry] Registered widget: {name} (from {plugin_id})")
|
||||||
|
|
||||||
|
def unregister_widget(self, widget_id: str):
|
||||||
|
"""Unregister a widget."""
|
||||||
|
if widget_id in self._widgets:
|
||||||
|
del self._widgets[widget_id]
|
||||||
|
print(f"[WidgetRegistry] Unregistered widget: {widget_id}")
|
||||||
|
|
||||||
|
def get_widget(self, widget_id: str) -> Optional[WidgetInfo]:
|
||||||
|
"""Get widget info by ID."""
|
||||||
|
return self._widgets.get(widget_id)
|
||||||
|
|
||||||
|
def get_all_widgets(self) -> List[WidgetInfo]:
|
||||||
|
"""Get all registered widgets."""
|
||||||
|
return list(self._widgets.values())
|
||||||
|
|
||||||
|
def get_widgets_by_plugin(self, plugin_id: str) -> List[WidgetInfo]:
|
||||||
|
"""Get all widgets registered by a specific plugin."""
|
||||||
|
return [w for w in self._widgets.values() if w.plugin_id == plugin_id]
|
||||||
|
|
||||||
|
def create_widget(self, widget_id: str) -> Optional[QWidget]:
|
||||||
|
"""Create an instance of a registered widget."""
|
||||||
|
info = self._widgets.get(widget_id)
|
||||||
|
if info:
|
||||||
|
try:
|
||||||
|
return info.creator()
|
||||||
|
except Exception as e:
|
||||||
|
print(f"[WidgetRegistry] Error creating widget {widget_id}: {e}")
|
||||||
|
return None
|
||||||
|
|
||||||
|
def clear(self):
|
||||||
|
"""Clear all registered widgets."""
|
||||||
|
self._widgets.clear()
|
||||||
|
|
||||||
|
|
||||||
|
# Global registry instance
|
||||||
|
def get_widget_registry() -> WidgetRegistry:
|
||||||
|
"""Get the global widget registry."""
|
||||||
|
return WidgetRegistry()
|
||||||
Loading…
Reference in New Issue