From db0eb5bf656510b53d63fab3f4efe3f104112892 Mon Sep 17 00:00:00 2001 From: LemonNexus Date: Sat, 14 Feb 2026 19:14:22 +0000 Subject: [PATCH] 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 --- core/overlay_window.py | 270 +++++++++++++++++++++++++++++++++++------ 1 file changed, 234 insertions(+), 36 deletions(-) diff --git a/core/overlay_window.py b/core/overlay_window.py index dafc777..5d0aa7b 100644 --- a/core/overlay_window.py +++ b/core/overlay_window.py @@ -18,7 +18,8 @@ try: QMainWindow, QWidget, QVBoxLayout, QHBoxLayout, QLabel, QPushButton, QStackedWidget, QSystemTrayIcon, 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.QtGui import QAction, QIcon, QColor, QFont, QKeySequence, QShortcut @@ -751,59 +752,256 @@ class OverlayWindow(QMainWindow): dialog.exec() def _create_plugins_settings_tab(self) -> QWidget: - """Create plugins settings tab.""" + """Create plugins settings tab with improved UI and categorization.""" c = get_all_colors() tab = QWidget() layout = QVBoxLayout(tab) layout.setSpacing(16) + layout.setContentsMargins(16, 16, 16, 16) - info = QLabel("Enable or disable plugins:") - info.setStyleSheet(f"color: {c['text_secondary']};") - layout.addWidget(info) + # Header with info + header_frame = QFrame() + 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 = {} if self.plugin_manager: all_plugins = self.plugin_manager.get_all_discovered_plugins() - # Sort by name with error handling - def get_plugin_name(item): - try: - return getattr(item[1], 'name', item[0]) - except: - return item[0] + # Categorize plugins + core_plugins = [] + test_plugins = [] + other_plugins = [] - sorted_plugins = sorted(all_plugins.items(), key=get_plugin_name) - - for plugin_id, plugin_class in sorted_plugins: + for plugin_id, plugin_class in all_plugins.items(): try: - row = QHBoxLayout() - - # Safely get plugin attributes name = getattr(plugin_class, 'name', plugin_id.split('.')[-1]) - version = getattr(plugin_class, 'version', '?.?.?') - description = getattr(plugin_class, 'description', 'No description') - - cb = QCheckBox(f"{name} (v{version})") - cb.setChecked(self.plugin_manager.is_plugin_enabled(plugin_id)) - cb.setStyleSheet(f"color: {c['text_primary']};") - self.settings_checkboxes[plugin_id] = cb - row.addWidget(cb) - - desc = QLabel(description) - desc.setStyleSheet(f"color: {c['text_muted']}; font-size: {EU_TYPOGRAPHY['size_xs']};") - row.addWidget(desc, 1) - - layout.addLayout(row) - except Exception as e: - print(f"[Overlay] Error creating settings for {plugin_id}: {e}") - continue + if 'test' in plugin_id.lower() or name.lower().endswith('test'): + test_plugins.append((plugin_id, plugin_class)) + elif plugin_id.startswith(('core.', 'plugins.skill_scanner', 'plugins.loot_tracker', + 'plugins.mining_helper', 'plugins.chat_logger', + 'plugins.global_tracker', 'plugins.nexus_search', + 'plugins.universal_search', 'plugins.calculator', + 'plugins.settings', 'plugins.dashboard')): + core_plugins.append((plugin_id, plugin_class)) + else: + other_plugins.append((plugin_id, plugin_class)) + except: + other_plugins.append((plugin_id, plugin_class)) + + # Sort each category + def get_name(item): + try: + 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 + 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: """Create appearance settings tab.""" c = get_all_colors()