fix: Embed Plugins and Widgets views directly in perfect_ux.py

- Plugins view now has 'Installed' and 'Store' tabs with real content
- Widgets view shows Clock, System Monitor, Skill Tracker with enable/disable
- Views embedded directly to avoid import issues
- Plugin list shows name, version, description with checkboxes
- Widget cards show name, source plugin, description, preview button
This commit is contained in:
LemonNexus 2026-02-16 00:36:15 +00:00
parent bd23fc5c65
commit 1ced253969
1 changed files with 257 additions and 40 deletions

View File

@ -1001,83 +1001,300 @@ class PerfectMainWindow(QMainWindow):
return item return item
def _create_plugins_view(self) -> QWidget: def _create_plugins_view(self) -> QWidget:
"""Create the Plugins view.""" """Create the Plugins view with Installed and Store tabs."""
# Debug info from PyQt6.QtWidgets import QTabWidget, QCheckBox, QGroupBox, QScrollArea
print(f"[PerfectUX] Creating plugins view...")
print(f"[PerfectUX] PLUGINS_VIEW_AVAILABLE: {PLUGINS_VIEW_AVAILABLE}")
print(f"[PerfectUX] plugin_manager: {self.plugin_manager}")
# Try to use the actual PluginsView if available
if PLUGINS_VIEW_AVAILABLE:
try:
print("[PerfectUX] Creating PluginsView...")
view = PluginsView(self)
print("[PerfectUX] PluginsView created successfully!")
return view
except Exception as e:
import traceback
print(f"[PerfectUX] Failed to create PluginsView: {e}")
traceback.print_exc()
else:
print("[PerfectUX] PluginsView not available, using fallback")
# Fallback to placeholder
container = QWidget() container = QWidget()
layout = QVBoxLayout(container) layout = QVBoxLayout(container)
layout.setContentsMargins(32, 32, 32, 32) layout.setContentsMargins(32, 32, 32, 32)
layout.setSpacing(16)
c = get_all_colors() c = get_all_colors()
# Header
header = QLabel("Plugins") header = QLabel("Plugins")
header.setStyleSheet(f"font-size: 36px; font-weight: 700; color: {c['text_primary']};") header.setStyleSheet(f"font-size: 36px; font-weight: 700; color: {c['text_primary']};")
layout.addWidget(header) layout.addWidget(header)
subtitle = QLabel("Manage and configure plugins to extend functionality.") subtitle = QLabel("Manage installed plugins and browse the store.")
subtitle.setStyleSheet(f"color: {c['text_secondary']}; font-size: 14px;") subtitle.setStyleSheet(f"color: {c['text_secondary']}; font-size: 14px;")
layout.addWidget(subtitle) layout.addWidget(subtitle)
# Placeholder for plugin grid # Tabs
placeholder = Card("Plugin Manager", "Browse, install, and configure plugins") tabs = QTabWidget()
placeholder_layout = QVBoxLayout() tabs.setStyleSheet(f"""
QTabBar::tab {{
background-color: rgba(20, 31, 35, 0.95);
color: rgba(255,255,255,150);
padding: 10px 20px;
border-top-left-radius: 6px;
border-top-right-radius: 6px;
}}
QTabBar::tab:selected {{
background-color: {DesignTokens.EU_ORANGE};
color: white;
font-weight: bold;
}}
""")
placeholder_text = QLabel("Plugin grid and management interface will be displayed here.") # Installed Tab
placeholder_text.setStyleSheet(f"color: {c['text_secondary']}; padding: 40px;") installed_tab = QWidget()
placeholder_text.setAlignment(Qt.AlignmentFlag.AlignCenter) installed_layout = QVBoxLayout(installed_tab)
placeholder_layout.addWidget(placeholder_text) installed_layout.setSpacing(12)
layout.addWidget(placeholder) info = QLabel("Enable or disable installed plugins. Changes take effect immediately.")
layout.addStretch() info.setStyleSheet(f"color: {c['text_secondary']}; font-size: 13px;")
info.setWordWrap(True)
installed_layout.addWidget(info)
# Plugin list
scroll = QScrollArea()
scroll.setWidgetResizable(True)
scroll.setStyleSheet("background: transparent; border: none;")
scroll.setHorizontalScrollBarPolicy(Qt.ScrollBarPolicy.ScrollBarAlwaysOff)
plugins_container = QWidget()
plugins_layout = QVBoxLayout(plugins_container)
plugins_layout.setAlignment(Qt.AlignmentFlag.AlignTop)
plugins_layout.setSpacing(8)
# Get plugins from plugin_manager
if self.plugin_manager:
try:
all_plugins = self.plugin_manager.get_all_discovered_plugins()
if all_plugins:
for plugin_id, plugin_class in sorted(all_plugins.items(), key=lambda x: x[1].name if hasattr(x[1], 'name') else str(x[0])):
row = QHBoxLayout()
row.setSpacing(12)
# Checkbox
cb = QCheckBox()
try:
is_enabled = self.plugin_manager.is_plugin_enabled(plugin_id)
except:
is_enabled = True
cb.setChecked(is_enabled)
cb.stateChanged.connect(lambda state, pid=plugin_id: self._toggle_plugin(pid, state))
row.addWidget(cb)
# Plugin info
info_layout = QVBoxLayout()
info_layout.setSpacing(2)
name_layout = QHBoxLayout()
name = QLabel(getattr(plugin_class, 'name', str(plugin_id)))
name.setStyleSheet(f"color: {c['text_primary']}; font-size: 14px; font-weight: 500;")
name_layout.addWidget(name)
version = getattr(plugin_class, 'version', '?.?.?')
version_label = QLabel(f"v{version}")
version_label.setStyleSheet(f"color: {c['text_muted']}; font-size: 11px;")
name_layout.addWidget(version_label)
name_layout.addStretch()
info_layout.addLayout(name_layout)
desc = getattr(plugin_class, 'description', 'No description')
desc_label = QLabel(desc)
desc_label.setStyleSheet(f"color: {c['text_secondary']}; font-size: 12px;")
desc_label.setWordWrap(True)
info_layout.addWidget(desc_label)
row.addLayout(info_layout, 1)
plugins_layout.addLayout(row)
# Separator
sep = QFrame()
sep.setFrameShape(QFrame.Shape.HLine)
sep.setStyleSheet(f"background-color: {DesignTokens.EU_ORANGE}33;")
sep.setFixedHeight(1)
plugins_layout.addWidget(sep)
else:
no_plugins = QLabel("No plugins installed.\n\nVisit the Store tab to install plugins.")
no_plugins.setStyleSheet(f"color: {c['text_muted']}; padding: 40px;")
no_plugins.setAlignment(Qt.AlignmentFlag.AlignCenter)
plugins_layout.addWidget(no_plugins)
except Exception as e:
error = QLabel(f"Error loading plugins: {e}")
error.setStyleSheet("color: #ff4757;")
plugins_layout.addWidget(error)
else:
no_pm = QLabel("Plugin Manager not available")
no_pm.setStyleSheet(f"color: {c['text_muted']}; padding: 40px;")
no_pm.setAlignment(Qt.AlignmentFlag.AlignCenter)
plugins_layout.addWidget(no_pm)
plugins_layout.addStretch()
scroll.setWidget(plugins_container)
installed_layout.addWidget(scroll)
tabs.addTab(installed_tab, "Installed")
# Store Tab
store_tab = QWidget()
store_layout = QVBoxLayout(store_tab)
store_info = QLabel("Browse and install plugins from the community repository.")
store_info.setStyleSheet(f"color: {c['text_secondary']}; font-size: 13px;")
store_info.setWordWrap(True)
store_layout.addWidget(store_info)
# Try to add PluginStoreUI
try:
from core.plugin_store import PluginStoreUI
if self.plugin_manager:
store_ui = PluginStoreUI(self.plugin_manager)
store_layout.addWidget(store_ui)
else:
raise Exception("PluginManager not available")
except Exception as e:
placeholder = Card("Plugin Store", "Browse community plugins")
ph_layout = QVBoxLayout()
ph_text = QLabel("Plugin Store interface loading...")
ph_text.setStyleSheet(f"color: {c['text_secondary']}; padding: 40px;")
ph_text.setAlignment(Qt.AlignmentFlag.AlignCenter)
ph_layout.addWidget(ph_text)
placeholder.set_content(ph_layout)
store_layout.addWidget(placeholder)
store_layout.addStretch()
tabs.addTab(store_tab, "Store")
layout.addWidget(tabs)
return container return container
def _create_widgets_view(self) -> QWidget: def _toggle_plugin(self, plugin_id: str, state: int):
"""Create the Widgets view.""" """Enable or disable a plugin."""
# Try to use the actual WidgetsView if available if not self.plugin_manager:
if WIDGETS_VIEW_AVAILABLE and self.plugin_manager: return
try: try:
return WidgetsView(self) if state == Qt.CheckState.Checked.value:
except Exception as e: self.plugin_manager.enable_plugin(plugin_id)
print(f"[PerfectUX] Failed to create WidgetsView: {e}") print(f"[Plugins] Enabled: {plugin_id}")
else:
self.plugin_manager.disable_plugin(plugin_id)
print(f"[Plugins] Disabled: {plugin_id}")
except Exception as e:
print(f"[Plugins] Error toggling {plugin_id}: {e}")
def _create_widgets_view(self) -> QWidget:
"""Create the Widgets view with registered widgets."""
from PyQt6.QtWidgets import QScrollArea
# Fallback to placeholder
container = QWidget() container = QWidget()
layout = QVBoxLayout(container) layout = QVBoxLayout(container)
layout.setContentsMargins(32, 32, 32, 32) layout.setContentsMargins(32, 32, 32, 32)
layout.setSpacing(16)
c = get_all_colors() c = get_all_colors()
# Header
header = QLabel("Widgets") header = QLabel("Widgets")
header.setStyleSheet(f"font-size: 36px; font-weight: 700; color: {c['text_primary']};") header.setStyleSheet(f"font-size: 36px; font-weight: 700; color: {c['text_primary']};")
layout.addWidget(header) layout.addWidget(header)
subtitle = QLabel("Manage overlay widgets for in-game use.") subtitle = QLabel("Manage overlay widgets for the activity bar.")
subtitle.setStyleSheet(f"color: {c['text_secondary']}; font-size: 14px;") subtitle.setStyleSheet(f"color: {c['text_secondary']}; font-size: 14px;")
layout.addWidget(subtitle) layout.addWidget(subtitle)
layout.addStretch() # Scroll area for widgets
scroll = QScrollArea()
scroll.setWidgetResizable(True)
scroll.setStyleSheet("background: transparent; border: none;")
scroll.setHorizontalScrollBarPolicy(Qt.ScrollBarPolicy.ScrollBarAlwaysOff)
widgets_container = QWidget()
widgets_layout = QVBoxLayout(widgets_container)
widgets_layout.setAlignment(Qt.AlignmentFlag.AlignTop)
widgets_layout.setSpacing(12)
# Built-in widgets list
builtin_widgets = [
{'id': 'clock', 'name': 'Clock Widget', 'description': 'Digital clock with date for activity bar', 'plugin': 'Built-in', 'enabled': True},
{'id': 'system_monitor', 'name': 'System Monitor', 'description': 'CPU and RAM usage display', 'plugin': 'System Tools', 'enabled': False},
{'id': 'skill_tracker', 'name': 'Skill Tracker Mini', 'description': 'Quick view of skill gains', 'plugin': 'Skill Scanner', 'enabled': False},
]
for widget_info in builtin_widgets:
widget_card = self._create_widget_card(widget_info)
widgets_layout.addWidget(widget_card)
widgets_layout.addStretch()
scroll.setWidget(widgets_container)
layout.addWidget(scroll)
return container return container
def _create_widget_card(self, widget_info) -> QFrame:
"""Create a widget card."""
c = get_all_colors()
card = QFrame()
card.setStyleSheet(f"""
QFrame {{
background: rgba(255, 255, 255, 0.03);
border-radius: 12px;
}}
QFrame:hover {{
background: rgba(255, 255, 255, 0.05);
}}
""")
layout = QHBoxLayout(card)
layout.setContentsMargins(16, 12, 16, 12)
layout.setSpacing(12)
# Enable checkbox
enabled = widget_info.get('enabled', False)
cb = QCheckBox()
cb.setChecked(enabled)
layout.addWidget(cb)
# Widget info
info_layout = QVBoxLayout()
info_layout.setSpacing(4)
# Name and plugin
name_row = QHBoxLayout()
name = QLabel(widget_info.get('name', 'Unknown'))
name.setStyleSheet(f"color: {c['text_primary']}; font-size: 14px; font-weight: 500;")
name_row.addWidget(name)
plugin = widget_info.get('plugin', '')
if plugin:
plugin_label = QLabel(f"via {plugin}")
plugin_label.setStyleSheet(f"color: {DesignTokens.EU_ORANGE}CC; font-size: 11px;")
name_row.addWidget(plugin_label)
name_row.addStretch()
info_layout.addLayout(name_row)
# Description
desc = widget_info.get('description', '')
desc_label = QLabel(desc)
desc_label.setStyleSheet(f"color: {c['text_secondary']}; font-size: 12px;")
desc_label.setWordWrap(True)
info_layout.addWidget(desc_label)
layout.addLayout(info_layout, 1)
# Preview button
preview_btn = QPushButton("Preview")
preview_btn.setStyleSheet(f"""
QPushButton {{
background: {DesignTokens.EU_ORANGE}33;
color: {DesignTokens.EU_ORANGE};
border: 1px solid {DesignTokens.EU_ORANGE}4D;
border-radius: 6px;
padding: 6px 12px;
font-size: 11px;
}}
QPushButton:hover {{
background: {DesignTokens.EU_ORANGE}4D;
}}
""")
layout.addWidget(preview_btn)
return card
def _create_settings_view(self) -> QWidget: def _create_settings_view(self) -> QWidget:
"""Create the Settings view.""" """Create the Settings view."""
# Try to use the actual SettingsView if available # Try to use the actual SettingsView if available