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:
parent
bd23fc5c65
commit
1ced253969
|
|
@ -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:
|
||||||
|
self.plugin_manager.enable_plugin(plugin_id)
|
||||||
|
print(f"[Plugins] Enabled: {plugin_id}")
|
||||||
|
else:
|
||||||
|
self.plugin_manager.disable_plugin(plugin_id)
|
||||||
|
print(f"[Plugins] Disabled: {plugin_id}")
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(f"[PerfectUX] Failed to create WidgetsView: {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
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue