fix: Box-in-box UI, add Settings button to header
FIXES: - Removed margins causing 'box in a box' effect - Removed inner container border (window has OS frame) - Window now fills properly without nested boxes NEW: - Added Settings button to header (always accessible) - Settings dialog shows all available plugins - Check/uncheck to enable/disable - Shows message when no plugins enabled - Save & Apply reloads plugins immediately
This commit is contained in:
parent
bcd4574b7f
commit
7f6547f8de
|
|
@ -55,11 +55,18 @@ class OverlayWindow(QMainWindow):
|
|||
"""Configure window - resizable and shows in taskbar."""
|
||||
self.setWindowTitle("EU-Utility")
|
||||
|
||||
# Resizable window (no FramelessWindowHint), stays on top
|
||||
# Resizable window, stays on top
|
||||
self.setWindowFlags(
|
||||
Qt.WindowType.WindowStaysOnTopHint
|
||||
)
|
||||
|
||||
# Apply dark background to window itself
|
||||
self.setStyleSheet(f"""
|
||||
QMainWindow {{
|
||||
background-color: {EU_COLORS['bg_dark']};
|
||||
}}
|
||||
""")
|
||||
|
||||
self.setMinimumSize(600, 400)
|
||||
self.resize(850, 600)
|
||||
self._center_window()
|
||||
|
|
@ -72,69 +79,80 @@ class OverlayWindow(QMainWindow):
|
|||
self.move(x, y)
|
||||
|
||||
def _setup_ui(self):
|
||||
"""Setup clean EU-styled UI."""
|
||||
"""Setup clean EU-styled UI - fills window, no box-in-box."""
|
||||
central = QWidget()
|
||||
self.setCentralWidget(central)
|
||||
|
||||
# NO MARGINS - fill entire window
|
||||
layout = QVBoxLayout(central)
|
||||
layout.setContentsMargins(20, 20, 20, 20)
|
||||
layout.setContentsMargins(0, 0, 0, 0)
|
||||
layout.setSpacing(0)
|
||||
|
||||
# Main container with orange window border like Skills window
|
||||
# Main container - NO BORDER (window already has frame), fills window
|
||||
self.container = QFrame()
|
||||
self.container.setObjectName("euContainer")
|
||||
self.container.setStyleSheet(f"""
|
||||
#euContainer {{
|
||||
background-color: {EU_COLORS['bg_dark']};
|
||||
border: 1px solid {EU_COLORS['border_window']};
|
||||
border-radius: 8px;
|
||||
border: none;
|
||||
}}
|
||||
""")
|
||||
|
||||
shadow = QGraphicsDropShadowEffect()
|
||||
shadow.setBlurRadius(30)
|
||||
shadow.setColor(QColor(0, 0, 0, 150))
|
||||
shadow.setOffset(0, 8)
|
||||
self.container.setGraphicsEffect(shadow)
|
||||
|
||||
container_layout = QVBoxLayout(self.container)
|
||||
container_layout.setContentsMargins(0, 0, 0, 0)
|
||||
container_layout.setSpacing(0)
|
||||
|
||||
# Header with centered title - CLEAN (no weird lines)
|
||||
# Header with settings button
|
||||
header = QWidget()
|
||||
header.setObjectName("header")
|
||||
header.setStyleSheet(f"""
|
||||
QWidget {{
|
||||
QWidget#header {{
|
||||
background-color: {EU_COLORS['bg_header']};
|
||||
border-top-left-radius: 8px;
|
||||
border-top-right-radius: 8px;
|
||||
border-bottom: 1px solid {EU_COLORS['border_medium']};
|
||||
}}
|
||||
""")
|
||||
header_layout = QHBoxLayout(header)
|
||||
header_layout.setContentsMargins(15, 12, 15, 12)
|
||||
header_layout.setContentsMargins(15, 8, 15, 8)
|
||||
header_layout.setSpacing(10)
|
||||
|
||||
# App icon
|
||||
app_icon = QLabel()
|
||||
app_icon_pixmap = self.icon_manager.get_pixmap("target", size=20)
|
||||
app_icon_pixmap = self.icon_manager.get_pixmap("target", size=18)
|
||||
app_icon.setPixmap(app_icon_pixmap)
|
||||
app_icon.setFixedSize(20, 20)
|
||||
app_icon.setFixedSize(18, 18)
|
||||
header_layout.addWidget(app_icon)
|
||||
|
||||
# Centered title
|
||||
title = QLabel("EU-UTILITY")
|
||||
# Title
|
||||
title = QLabel("EU-Utility")
|
||||
title.setStyleSheet(f"""
|
||||
color: {EU_COLORS['text_primary']};
|
||||
font-size: 14px;
|
||||
font-size: 13px;
|
||||
font-weight: bold;
|
||||
letter-spacing: 2px;
|
||||
""")
|
||||
header_layout.addWidget(title)
|
||||
|
||||
header_layout.addStretch()
|
||||
|
||||
# Settings button (always accessible)
|
||||
settings_btn = QPushButton("Settings")
|
||||
settings_btn.setStyleSheet(f"""
|
||||
QPushButton {{
|
||||
background-color: {EU_COLORS['bg_panel']};
|
||||
color: {EU_COLORS['text_secondary']};
|
||||
border: 1px solid {EU_COLORS['border_subtle']};
|
||||
border-radius: 4px;
|
||||
padding: 4px 12px;
|
||||
font-size: 11px;
|
||||
}}
|
||||
QPushButton:hover {{
|
||||
background-color: {EU_COLORS['bg_hover']};
|
||||
border-color: {EU_COLORS['accent_orange']};
|
||||
color: {EU_COLORS['text_primary']};
|
||||
}}
|
||||
""")
|
||||
settings_btn.clicked.connect(self._open_settings)
|
||||
header_layout.addWidget(settings_btn)
|
||||
|
||||
# View toggle buttons
|
||||
view_group = QButtonGroup(self)
|
||||
view_group.setExclusive(True)
|
||||
|
|
@ -142,7 +160,7 @@ class OverlayWindow(QMainWindow):
|
|||
self.icon_view_btn = QPushButton("Grid")
|
||||
self.icon_view_btn.setCheckable(True)
|
||||
self.icon_view_btn.setChecked(True)
|
||||
self.icon_view_btn.setFixedSize(50, 24)
|
||||
self.icon_view_btn.setFixedSize(45, 22)
|
||||
self.icon_view_btn.setStyleSheet(self._view_toggle_style())
|
||||
self.icon_view_btn.clicked.connect(lambda: self._set_view_mode("icons"))
|
||||
header_layout.addWidget(self.icon_view_btn)
|
||||
|
|
@ -336,6 +354,19 @@ class OverlayWindow(QMainWindow):
|
|||
"""Load plugins into sidebar and stack - FIXED indexing."""
|
||||
plugins_list = list(self.plugin_manager.get_all_plugins().items())
|
||||
|
||||
# Show message if no plugins enabled
|
||||
if not plugins_list:
|
||||
# Add placeholder message
|
||||
placeholder = QLabel("No plugins enabled\n\nClick Settings to enable plugins")
|
||||
placeholder.setAlignment(Qt.AlignmentFlag.AlignCenter)
|
||||
placeholder.setStyleSheet(f"""
|
||||
color: {EU_COLORS['text_muted']};
|
||||
font-size: 14px;
|
||||
padding: 40px;
|
||||
""")
|
||||
self.plugin_stack.addWidget(placeholder)
|
||||
return
|
||||
|
||||
for idx, (plugin_id, plugin) in enumerate(plugins_list):
|
||||
# Get icon name
|
||||
icon_name = get_plugin_icon_name(plugin.name)
|
||||
|
|
@ -534,6 +565,150 @@ class OverlayWindow(QMainWindow):
|
|||
self.tray_icon.hide()
|
||||
QApplication.quit()
|
||||
|
||||
def _open_settings(self):
|
||||
"""Open Settings dialog - works even when Settings plugin not loaded."""
|
||||
from PyQt6.QtWidgets import QDialog, QVBoxLayout, QTabWidget, QListWidget, QListWidgetItem, QCheckBox, QHBoxLayout
|
||||
|
||||
dialog = QDialog(self)
|
||||
dialog.setWindowTitle("EU-Utility Settings")
|
||||
dialog.setMinimumSize(500, 400)
|
||||
dialog.setStyleSheet(f"""
|
||||
QDialog {{
|
||||
background-color: {EU_COLORS['bg_dark']};
|
||||
color: white;
|
||||
}}
|
||||
QLabel {{
|
||||
color: white;
|
||||
}}
|
||||
QTabWidget::pane {{
|
||||
background-color: {EU_COLORS['bg_panel']};
|
||||
border: 1px solid {EU_COLORS['border_medium']};
|
||||
border-radius: 6px;
|
||||
}}
|
||||
QTabBar::tab {{
|
||||
background-color: {EU_COLORS['bg_header']};
|
||||
color: {EU_COLORS['text_secondary']};
|
||||
padding: 10px 20px;
|
||||
border-top-left-radius: 6px;
|
||||
border-top-right-radius: 6px;
|
||||
}}
|
||||
QTabBar::tab:selected {{
|
||||
background-color: {EU_COLORS['accent_orange']};
|
||||
color: white;
|
||||
font-weight: bold;
|
||||
}}
|
||||
""")
|
||||
|
||||
layout = QVBoxLayout(dialog)
|
||||
|
||||
tabs = QTabWidget()
|
||||
|
||||
# Plugins tab
|
||||
plugins_tab = QWidget()
|
||||
plugins_layout = QVBoxLayout(plugins_tab)
|
||||
|
||||
info = QLabel("Check plugins to enable them:")
|
||||
info.setStyleSheet(f"color: {EU_COLORS['text_muted']};")
|
||||
plugins_layout.addWidget(info)
|
||||
|
||||
self.settings_checkboxes = {}
|
||||
|
||||
if self.plugin_manager:
|
||||
all_plugins = self.plugin_manager.get_all_discovered_plugins()
|
||||
sorted_plugins = sorted(all_plugins.items(), key=lambda x: x[1].name)
|
||||
|
||||
for plugin_id, plugin_class in sorted_plugins:
|
||||
row = QHBoxLayout()
|
||||
|
||||
cb = QCheckBox(f"{plugin_class.name} (v{plugin_class.version})")
|
||||
cb.setChecked(self.plugin_manager.is_plugin_enabled(plugin_id))
|
||||
cb.setStyleSheet("color: white;")
|
||||
self.settings_checkboxes[plugin_id] = cb
|
||||
row.addWidget(cb)
|
||||
|
||||
desc = QLabel(plugin_class.description)
|
||||
desc.setStyleSheet(f"color: {EU_COLORS['text_muted']}; font-size: 11px;")
|
||||
row.addWidget(desc, 1)
|
||||
|
||||
plugins_layout.addLayout(row)
|
||||
|
||||
plugins_layout.addStretch()
|
||||
|
||||
# Buttons
|
||||
btn_layout = QHBoxLayout()
|
||||
|
||||
save_btn = QPushButton("Save & Apply")
|
||||
save_btn.setStyleSheet(f"""
|
||||
QPushButton {{
|
||||
background-color: {EU_COLORS['accent_orange']};
|
||||
color: white;
|
||||
padding: 10px 20px;
|
||||
border: none;
|
||||
border-radius: 4px;
|
||||
font-weight: bold;
|
||||
}}
|
||||
""")
|
||||
save_btn.clicked.connect(lambda: self._save_plugin_settings(dialog))
|
||||
btn_layout.addWidget(save_btn)
|
||||
|
||||
btn_layout.addStretch()
|
||||
plugins_layout.addLayout(btn_layout)
|
||||
|
||||
tabs.addTab(plugins_tab, "Plugins")
|
||||
|
||||
# Add info tab
|
||||
info_tab = QWidget()
|
||||
info_layout = QVBoxLayout(info_tab)
|
||||
info_text = QLabel(
|
||||
"EU-Utility v2.0\n\n"
|
||||
"Loaded plugins will appear in the sidebar.\n"
|
||||
"Enable plugins above to use them.\n\n"
|
||||
"Hotkeys:\n"
|
||||
"Ctrl+Shift+U - Toggle overlay\n"
|
||||
"Ctrl+Shift+H - Hide all overlays"
|
||||
)
|
||||
info_text.setStyleSheet("color: white;")
|
||||
info_layout.addWidget(info_text)
|
||||
info_layout.addStretch()
|
||||
tabs.addTab(info_tab, "About")
|
||||
|
||||
layout.addWidget(tabs)
|
||||
dialog.exec()
|
||||
|
||||
def _save_plugin_settings(self, dialog):
|
||||
"""Save plugin enable/disable settings."""
|
||||
if not self.plugin_manager:
|
||||
return
|
||||
|
||||
for plugin_id, cb in self.settings_checkboxes.items():
|
||||
if cb.isChecked():
|
||||
self.plugin_manager.enable_plugin(plugin_id)
|
||||
else:
|
||||
self.plugin_manager.disable_plugin(plugin_id)
|
||||
|
||||
# Reload plugins in UI
|
||||
self._reload_plugins()
|
||||
dialog.accept()
|
||||
|
||||
def _reload_plugins(self):
|
||||
"""Reload plugins in UI after enabling/disabling."""
|
||||
# Clear existing
|
||||
while self.plugin_stack.count() > 0:
|
||||
widget = self.plugin_stack.widget(0)
|
||||
self.plugin_stack.removeWidget(widget)
|
||||
|
||||
self.plugin_list.clear()
|
||||
self.plugin_buttons = []
|
||||
|
||||
# Clear icon grid
|
||||
while self.icon_grid_layout.count():
|
||||
item = self.icon_grid_layout.takeAt(0)
|
||||
if item.widget():
|
||||
item.widget().deleteLater()
|
||||
|
||||
# Reload
|
||||
self._load_plugins()
|
||||
|
||||
def keyPressEvent(self, event):
|
||||
"""Handle ESC key."""
|
||||
if event.key() == Qt.Key.Key_Escape:
|
||||
|
|
|
|||
Loading…
Reference in New Issue