feat: Redesign Plugins Settings tab with categorization
IMPROVED PLUGINS SETTINGS UI:
1. Visual Improvements:
- Added header with plugin management info
- Added color-coded legend (Core/Test/Other)
- Styled plugin rows with hover effects
- Version badges with orange accent color
- Scrollable plugin list for large numbers
- Better spacing and visual hierarchy
2. Plugin Categorization:
- Core Plugins (teal): skill_scanner, loot_tracker, mining_helper,
chat_logger, global_tracker, nexus_search, universal_search,
calculator, settings, dashboard
- Test Plugins (orange): game_reader_test, log_parser_test
- Other Plugins (gray): All remaining plugins
3. Naming Convention:
- Core plugins prefixed with 'Core-'
- Test plugins prefixed with 'Test-'
- Other plugins have no prefix
4. Technical Changes:
- Added QScrollArea import
- New _add_plugin_row() helper method
- Grouped plugins by category
- Styled checkboxes with EU theme
- Added author attribution display
This commit is contained in:
parent
219d0847b2
commit
db0eb5bf65
|
|
@ -18,7 +18,8 @@ try:
|
||||||
QMainWindow, QWidget, QVBoxLayout, QHBoxLayout,
|
QMainWindow, QWidget, QVBoxLayout, QHBoxLayout,
|
||||||
QLabel, QPushButton, QStackedWidget, QSystemTrayIcon,
|
QLabel, QPushButton, QStackedWidget, QSystemTrayIcon,
|
||||||
QMenu, QApplication, QFrame, QListWidget, QListWidgetItem,
|
QMenu, QApplication, QFrame, QListWidget, QListWidgetItem,
|
||||||
QButtonGroup, QSplitter, QSizePolicy, QCheckBox, QTabWidget
|
QButtonGroup, QSplitter, QSizePolicy, QCheckBox, QTabWidget,
|
||||||
|
QScrollArea
|
||||||
)
|
)
|
||||||
from PyQt6.QtCore import Qt, QTimer, pyqtSignal, QSize, QPropertyAnimation, QEasingCurve, QParallelAnimationGroup
|
from PyQt6.QtCore import Qt, QTimer, pyqtSignal, QSize, QPropertyAnimation, QEasingCurve, QParallelAnimationGroup
|
||||||
from PyQt6.QtGui import QAction, QIcon, QColor, QFont, QKeySequence, QShortcut
|
from PyQt6.QtGui import QAction, QIcon, QColor, QFont, QKeySequence, QShortcut
|
||||||
|
|
@ -751,59 +752,256 @@ class OverlayWindow(QMainWindow):
|
||||||
dialog.exec()
|
dialog.exec()
|
||||||
|
|
||||||
def _create_plugins_settings_tab(self) -> QWidget:
|
def _create_plugins_settings_tab(self) -> QWidget:
|
||||||
"""Create plugins settings tab."""
|
"""Create plugins settings tab with improved UI and categorization."""
|
||||||
c = get_all_colors()
|
c = get_all_colors()
|
||||||
|
|
||||||
tab = QWidget()
|
tab = QWidget()
|
||||||
layout = QVBoxLayout(tab)
|
layout = QVBoxLayout(tab)
|
||||||
layout.setSpacing(16)
|
layout.setSpacing(16)
|
||||||
|
layout.setContentsMargins(16, 16, 16, 16)
|
||||||
|
|
||||||
info = QLabel("Enable or disable plugins:")
|
# Header with info
|
||||||
info.setStyleSheet(f"color: {c['text_secondary']};")
|
header_frame = QFrame()
|
||||||
layout.addWidget(info)
|
header_frame.setStyleSheet(f"""
|
||||||
|
QFrame {{
|
||||||
|
background-color: {c['bg_secondary']};
|
||||||
|
border-left: 3px solid {c['accent_primary']};
|
||||||
|
border-radius: 4px;
|
||||||
|
padding: 12px;
|
||||||
|
}}
|
||||||
|
""")
|
||||||
|
header_layout = QVBoxLayout(header_frame)
|
||||||
|
header_layout.setSpacing(4)
|
||||||
|
|
||||||
# Plugin list
|
info_title = QLabel("Plugin Management")
|
||||||
|
info_title.setStyleSheet(f"color: {c['text_primary']}; font-weight: bold; font-size: 13px;")
|
||||||
|
header_layout.addWidget(info_title)
|
||||||
|
|
||||||
|
info_desc = QLabel("Enable or disable plugins. Changes take effect after restarting the overlay.")
|
||||||
|
info_desc.setStyleSheet(f"color: {c['text_secondary']}; font-size: 11px;")
|
||||||
|
info_desc.setWordWrap(True)
|
||||||
|
header_layout.addWidget(info_desc)
|
||||||
|
|
||||||
|
layout.addWidget(header_frame)
|
||||||
|
|
||||||
|
# Legend
|
||||||
|
legend_frame = QFrame()
|
||||||
|
legend_layout = QHBoxLayout(legend_frame)
|
||||||
|
legend_layout.setSpacing(16)
|
||||||
|
|
||||||
|
core_label = QLabel("● Core")
|
||||||
|
core_label.setStyleSheet("color: #4ecdc4; font-size: 11px; font-weight: bold;")
|
||||||
|
legend_layout.addWidget(core_label)
|
||||||
|
|
||||||
|
test_label = QLabel("● Test")
|
||||||
|
test_label.setStyleSheet("color: #ff8c42; font-size: 11px; font-weight: bold;")
|
||||||
|
legend_layout.addWidget(test_label)
|
||||||
|
|
||||||
|
other_label = QLabel("● Other")
|
||||||
|
other_label.setStyleSheet("color: #a0aec0; font-size: 11px;")
|
||||||
|
legend_layout.addWidget(other_label)
|
||||||
|
|
||||||
|
legend_layout.addStretch()
|
||||||
|
layout.addWidget(legend_frame)
|
||||||
|
|
||||||
|
# Plugin list container
|
||||||
self.settings_checkboxes = {}
|
self.settings_checkboxes = {}
|
||||||
|
|
||||||
if self.plugin_manager:
|
if self.plugin_manager:
|
||||||
all_plugins = self.plugin_manager.get_all_discovered_plugins()
|
all_plugins = self.plugin_manager.get_all_discovered_plugins()
|
||||||
|
|
||||||
# Sort by name with error handling
|
# Categorize plugins
|
||||||
def get_plugin_name(item):
|
core_plugins = []
|
||||||
try:
|
test_plugins = []
|
||||||
return getattr(item[1], 'name', item[0])
|
other_plugins = []
|
||||||
except:
|
|
||||||
return item[0]
|
|
||||||
|
|
||||||
sorted_plugins = sorted(all_plugins.items(), key=get_plugin_name)
|
for plugin_id, plugin_class in all_plugins.items():
|
||||||
|
|
||||||
for plugin_id, plugin_class in sorted_plugins:
|
|
||||||
try:
|
try:
|
||||||
row = QHBoxLayout()
|
|
||||||
|
|
||||||
# Safely get plugin attributes
|
|
||||||
name = getattr(plugin_class, 'name', plugin_id.split('.')[-1])
|
name = getattr(plugin_class, 'name', plugin_id.split('.')[-1])
|
||||||
version = getattr(plugin_class, 'version', '?.?.?')
|
if 'test' in plugin_id.lower() or name.lower().endswith('test'):
|
||||||
description = getattr(plugin_class, 'description', 'No description')
|
test_plugins.append((plugin_id, plugin_class))
|
||||||
|
elif plugin_id.startswith(('core.', 'plugins.skill_scanner', 'plugins.loot_tracker',
|
||||||
cb = QCheckBox(f"{name} (v{version})")
|
'plugins.mining_helper', 'plugins.chat_logger',
|
||||||
cb.setChecked(self.plugin_manager.is_plugin_enabled(plugin_id))
|
'plugins.global_tracker', 'plugins.nexus_search',
|
||||||
cb.setStyleSheet(f"color: {c['text_primary']};")
|
'plugins.universal_search', 'plugins.calculator',
|
||||||
self.settings_checkboxes[plugin_id] = cb
|
'plugins.settings', 'plugins.dashboard')):
|
||||||
row.addWidget(cb)
|
core_plugins.append((plugin_id, plugin_class))
|
||||||
|
else:
|
||||||
desc = QLabel(description)
|
other_plugins.append((plugin_id, plugin_class))
|
||||||
desc.setStyleSheet(f"color: {c['text_muted']}; font-size: {EU_TYPOGRAPHY['size_xs']};")
|
except:
|
||||||
row.addWidget(desc, 1)
|
other_plugins.append((plugin_id, plugin_class))
|
||||||
|
|
||||||
layout.addLayout(row)
|
# Sort each category
|
||||||
except Exception as e:
|
def get_name(item):
|
||||||
print(f"[Overlay] Error creating settings for {plugin_id}: {e}")
|
try:
|
||||||
continue
|
return getattr(item[1], 'name', item[0]).lower()
|
||||||
|
except:
|
||||||
|
return item[0].lower()
|
||||||
|
|
||||||
|
core_plugins.sort(key=get_name)
|
||||||
|
test_plugins.sort(key=get_name)
|
||||||
|
other_plugins.sort(key=get_name)
|
||||||
|
|
||||||
|
# Create scroll area for plugins
|
||||||
|
scroll = QScrollArea()
|
||||||
|
scroll.setWidgetResizable(True)
|
||||||
|
scroll.setFrameShape(QFrame.Shape.NoFrame)
|
||||||
|
scroll.setStyleSheet(f"""
|
||||||
|
QScrollArea {{
|
||||||
|
background-color: transparent;
|
||||||
|
border: none;
|
||||||
|
}}
|
||||||
|
QScrollBar:vertical {{
|
||||||
|
background-color: {c['bg_secondary']};
|
||||||
|
width: 10px;
|
||||||
|
border-radius: 5px;
|
||||||
|
}}
|
||||||
|
QScrollBar::handle:vertical {{
|
||||||
|
background-color: {c['accent_primary']};
|
||||||
|
border-radius: 5px;
|
||||||
|
min-height: 30px;
|
||||||
|
}}
|
||||||
|
""")
|
||||||
|
|
||||||
|
plugins_container = QWidget()
|
||||||
|
plugins_layout = QVBoxLayout(plugins_container)
|
||||||
|
plugins_layout.setSpacing(8)
|
||||||
|
plugins_layout.setAlignment(Qt.AlignmentFlag.AlignTop)
|
||||||
|
|
||||||
|
# Add Core Plugins section
|
||||||
|
if core_plugins:
|
||||||
|
core_header = QLabel("CORE PLUGINS")
|
||||||
|
core_header.setStyleSheet(f"""
|
||||||
|
color: #4ecdc4;
|
||||||
|
font-weight: bold;
|
||||||
|
font-size: 10px;
|
||||||
|
padding: 8px 4px 4px 4px;
|
||||||
|
border-bottom: 1px solid {c['border_color']};
|
||||||
|
""")
|
||||||
|
plugins_layout.addWidget(core_header)
|
||||||
|
|
||||||
|
for plugin_id, plugin_class in core_plugins:
|
||||||
|
self._add_plugin_row(plugins_layout, plugin_id, plugin_class, c, "Core")
|
||||||
|
|
||||||
|
# Add Test Plugins section
|
||||||
|
if test_plugins:
|
||||||
|
test_header = QLabel("TEST PLUGINS")
|
||||||
|
test_header.setStyleSheet(f"""
|
||||||
|
color: #ff8c42;
|
||||||
|
font-weight: bold;
|
||||||
|
font-size: 10px;
|
||||||
|
padding: 16px 4px 4px 4px;
|
||||||
|
border-bottom: 1px solid {c['border_color']};
|
||||||
|
""")
|
||||||
|
plugins_layout.addWidget(test_header)
|
||||||
|
|
||||||
|
for plugin_id, plugin_class in test_plugins:
|
||||||
|
self._add_plugin_row(plugins_layout, plugin_id, plugin_class, c, "Test")
|
||||||
|
|
||||||
|
# Add Other Plugins section
|
||||||
|
if other_plugins:
|
||||||
|
other_header = QLabel("OTHER PLUGINS")
|
||||||
|
other_header.setStyleSheet(f"""
|
||||||
|
color: {c['text_muted']};
|
||||||
|
font-weight: bold;
|
||||||
|
font-size: 10px;
|
||||||
|
padding: 16px 4px 4px 4px;
|
||||||
|
border-bottom: 1px solid {c['border_color']};
|
||||||
|
""")
|
||||||
|
plugins_layout.addWidget(other_header)
|
||||||
|
|
||||||
|
for plugin_id, plugin_class in other_plugins:
|
||||||
|
self._add_plugin_row(plugins_layout, plugin_id, plugin_class, c, None)
|
||||||
|
|
||||||
|
plugins_layout.addStretch()
|
||||||
|
scroll.setWidget(plugins_container)
|
||||||
|
layout.addWidget(scroll, 1) # Stretch factor 1
|
||||||
|
|
||||||
layout.addStretch()
|
|
||||||
return tab
|
return tab
|
||||||
|
|
||||||
|
def _add_plugin_row(self, layout, plugin_id, plugin_class, colors, prefix):
|
||||||
|
"""Add a plugin row to the layout."""
|
||||||
|
try:
|
||||||
|
row_widget = QFrame()
|
||||||
|
row_widget.setStyleSheet(f"""
|
||||||
|
QFrame {{
|
||||||
|
background-color: {colors['bg_secondary']};
|
||||||
|
border-radius: 4px;
|
||||||
|
padding: 2px;
|
||||||
|
}}
|
||||||
|
QFrame:hover {{
|
||||||
|
background-color: {colors['bg_hover']};
|
||||||
|
}}
|
||||||
|
""")
|
||||||
|
row_layout = QHBoxLayout(row_widget)
|
||||||
|
row_layout.setSpacing(12)
|
||||||
|
row_layout.setContentsMargins(10, 8, 10, 8)
|
||||||
|
|
||||||
|
# Get plugin attributes
|
||||||
|
name = getattr(plugin_class, 'name', plugin_id.split('.')[-1])
|
||||||
|
version = getattr(plugin_class, 'version', '?.?.?')
|
||||||
|
description = getattr(plugin_class, 'description', 'No description')
|
||||||
|
author = getattr(plugin_class, 'author', 'Unknown')
|
||||||
|
|
||||||
|
# Add prefix to name
|
||||||
|
display_name = f"{prefix}-{name}" if prefix else name
|
||||||
|
|
||||||
|
# Checkbox
|
||||||
|
cb = QCheckBox(f"{display_name}")
|
||||||
|
cb.setChecked(self.plugin_manager.is_plugin_enabled(plugin_id))
|
||||||
|
cb.setStyleSheet(f"""
|
||||||
|
QCheckBox {{
|
||||||
|
color: {colors['text_primary']};
|
||||||
|
font-weight: bold;
|
||||||
|
spacing: 8px;
|
||||||
|
}}
|
||||||
|
QCheckBox::indicator {{
|
||||||
|
width: 16px;
|
||||||
|
height: 16px;
|
||||||
|
border-radius: 3px;
|
||||||
|
border: 2px solid {colors['accent_primary']};
|
||||||
|
}}
|
||||||
|
QCheckBox::indicator:checked {{
|
||||||
|
background-color: {colors['accent_primary']};
|
||||||
|
}}
|
||||||
|
""")
|
||||||
|
self.settings_checkboxes[plugin_id] = cb
|
||||||
|
row_layout.addWidget(cb)
|
||||||
|
|
||||||
|
# Version badge
|
||||||
|
version_label = QLabel(f"v{version}")
|
||||||
|
version_label.setStyleSheet(f"""
|
||||||
|
color: {colors['accent_primary']};
|
||||||
|
font-size: 9px;
|
||||||
|
font-weight: bold;
|
||||||
|
background-color: {colors['bg_primary']};
|
||||||
|
padding: 2px 6px;
|
||||||
|
border-radius: 3px;
|
||||||
|
""")
|
||||||
|
row_layout.addWidget(version_label)
|
||||||
|
|
||||||
|
# Description
|
||||||
|
desc_label = QLabel(description)
|
||||||
|
desc_label.setStyleSheet(f"""
|
||||||
|
color: {colors['text_muted']};
|
||||||
|
font-size: 11px;
|
||||||
|
""")
|
||||||
|
desc_label.setWordWrap(True)
|
||||||
|
row_layout.addWidget(desc_label, 1)
|
||||||
|
|
||||||
|
# Author (small)
|
||||||
|
author_label = QLabel(f"by {author}")
|
||||||
|
author_label.setStyleSheet(f"""
|
||||||
|
color: {colors['text_secondary']};
|
||||||
|
font-size: 9px;
|
||||||
|
""")
|
||||||
|
row_layout.addWidget(author_label)
|
||||||
|
|
||||||
|
layout.addWidget(row_widget)
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
print(f"[Overlay] Error creating settings for {plugin_id}: {e}")
|
||||||
|
|
||||||
def _create_appearance_settings_tab(self) -> QWidget:
|
def _create_appearance_settings_tab(self) -> QWidget:
|
||||||
"""Create appearance settings tab."""
|
"""Create appearance settings tab."""
|
||||||
c = get_all_colors()
|
c = get_all_colors()
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue