821 lines
29 KiB
Python
821 lines
29 KiB
Python
"""
|
|
EU-Utility - Enhanced Settings Panel
|
|
|
|
Complete settings implementation with SQLite persistence.
|
|
"""
|
|
|
|
import json
|
|
import platform
|
|
from pathlib import Path
|
|
from typing import Dict, Any, Optional
|
|
|
|
from PyQt6.QtWidgets import (
|
|
QWidget, QVBoxLayout, QHBoxLayout, QLabel, QPushButton,
|
|
QCheckBox, QLineEdit, QComboBox, QSlider, QTabWidget,
|
|
QGroupBox, QFrame, QFileDialog, QMessageBox, QScrollArea,
|
|
QGridLayout, QSpinBox, QKeySequenceEdit, QListWidget,
|
|
QListWidgetItem, QDialog, QDialogButtonBox, QFormLayout,
|
|
QProgressBar
|
|
)
|
|
from PyQt6.QtCore import Qt, QTimer
|
|
from PyQt6.QtGui import QKeySequence
|
|
|
|
from core.data.sqlite_store import get_sqlite_store, SQLiteDataStore
|
|
|
|
|
|
class HotkeyEditDialog(QDialog):
|
|
"""Dialog for editing a hotkey."""
|
|
|
|
def __init__(self, action: str, current_combo: str, parent=None):
|
|
super().__init__(parent)
|
|
self.action = action
|
|
self.current_combo = current_combo
|
|
|
|
self.setWindowTitle(f"Edit Hotkey: {action}")
|
|
self.setMinimumSize(300, 150)
|
|
|
|
layout = QVBoxLayout(self)
|
|
layout.setSpacing(15)
|
|
layout.setContentsMargins(20, 20, 20, 20)
|
|
|
|
# Current hotkey
|
|
form = QFormLayout()
|
|
|
|
self.key_edit = QKeySequenceEdit()
|
|
self.key_edit.setKeySequence(QKeySequence(current_combo))
|
|
form.addRow("Press keys:", self.key_edit)
|
|
|
|
layout.addLayout(form)
|
|
|
|
# Help text
|
|
help_label = QLabel("Press the key combination you want to use.")
|
|
help_label.setStyleSheet("color: rgba(255, 255, 255, 100); font-size: 11px;")
|
|
layout.addWidget(help_label)
|
|
|
|
layout.addStretch()
|
|
|
|
# Buttons
|
|
buttons = QDialogButtonBox(
|
|
QDialogButtonBox.StandardButton.Ok | QDialogButtonBox.StandardButton.Cancel
|
|
)
|
|
buttons.accepted.connect(self.accept)
|
|
buttons.rejected.connect(self.reject)
|
|
layout.addWidget(buttons)
|
|
|
|
def get_key_combo(self) -> str:
|
|
"""Get the key combination."""
|
|
return self.key_edit.keySequence().toString()
|
|
|
|
|
|
class EnhancedSettingsPanel(QWidget):
|
|
"""Enhanced settings panel with full functionality."""
|
|
|
|
settings_changed = pyqtSignal(str, Any) # key, value
|
|
theme_changed = pyqtSignal(str) # theme name
|
|
|
|
def __init__(self, overlay_window, parent=None):
|
|
super().__init__(parent)
|
|
self.overlay = overlay_window
|
|
self.plugin_manager = getattr(overlay_window, 'plugin_manager', None)
|
|
|
|
# Initialize data store
|
|
self.data_store = get_sqlite_store()
|
|
|
|
self._setup_ui()
|
|
self._load_settings()
|
|
|
|
def _setup_ui(self):
|
|
"""Setup settings UI."""
|
|
layout = QVBoxLayout(self)
|
|
layout.setSpacing(15)
|
|
layout.setContentsMargins(20, 20, 20, 20)
|
|
|
|
# Header
|
|
header = QLabel("⚙️ Settings")
|
|
header.setStyleSheet("font-size: 24px; font-weight: bold; color: white;")
|
|
layout.addWidget(header)
|
|
|
|
# Tabs
|
|
self.tabs = QTabWidget()
|
|
self.tabs.setStyleSheet("""
|
|
QTabBar::tab {
|
|
background-color: rgba(35, 40, 55, 200);
|
|
color: rgba(255,255,255,150);
|
|
padding: 10px 20px;
|
|
border-top-left-radius: 6px;
|
|
border-top-right-radius: 6px;
|
|
}
|
|
QTabBar::tab:selected {
|
|
background-color: #ff8c42;
|
|
color: white;
|
|
font-weight: bold;
|
|
}
|
|
""")
|
|
|
|
# Add tabs
|
|
self.tabs.addTab(self._create_general_tab(), "General")
|
|
self.tabs.addTab(self._create_appearance_tab(), "Appearance")
|
|
self.tabs.addTab(self._create_plugins_tab(), "Plugins")
|
|
self.tabs.addTab(self._create_hotkeys_tab(), "Hotkeys")
|
|
self.tabs.addTab(self._create_data_tab(), "Data & Backup")
|
|
self.tabs.addTab(self._create_about_tab(), "About")
|
|
|
|
layout.addWidget(self.tabs)
|
|
|
|
# Save button
|
|
save_btn = QPushButton("💾 Save Settings")
|
|
save_btn.setStyleSheet("""
|
|
QPushButton {
|
|
background-color: #4ecdc4;
|
|
color: #141f23;
|
|
padding: 12px 24px;
|
|
border: none;
|
|
border-radius: 6px;
|
|
font-weight: bold;
|
|
font-size: 14px;
|
|
}
|
|
QPushButton:hover {
|
|
background-color: #3dbdb4;
|
|
}
|
|
""")
|
|
save_btn.clicked.connect(self._save_all_settings)
|
|
layout.addWidget(save_btn)
|
|
|
|
def _create_general_tab(self) -> QWidget:
|
|
"""Create general settings tab."""
|
|
tab = QWidget()
|
|
layout = QVBoxLayout(tab)
|
|
layout.setSpacing(15)
|
|
|
|
# Startup
|
|
startup_group = QGroupBox("Startup")
|
|
startup_group.setStyleSheet(self._group_style())
|
|
startup_layout = QVBoxLayout(startup_group)
|
|
|
|
self.auto_start_cb = QCheckBox("Start with Windows")
|
|
self.auto_start_cb.setStyleSheet("color: rgba(255, 255, 255, 200);")
|
|
startup_layout.addWidget(self.auto_start_cb)
|
|
|
|
self.start_minimized_cb = QCheckBox("Start minimized to tray")
|
|
self.start_minimized_cb.setStyleSheet("color: rgba(255, 255, 255, 200);")
|
|
startup_layout.addWidget(self.start_minimized_cb)
|
|
|
|
layout.addWidget(startup_group)
|
|
|
|
# Behavior
|
|
behavior_group = QGroupBox("Behavior")
|
|
behavior_group.setStyleSheet(self._group_style())
|
|
behavior_layout = QVBoxLayout(behavior_group)
|
|
|
|
self.minimize_to_tray_cb = QCheckBox("Minimize to tray instead of closing")
|
|
self.minimize_to_tray_cb.setStyleSheet("color: rgba(255, 255, 255, 200);")
|
|
behavior_layout.addWidget(self.minimize_to_tray_cb)
|
|
|
|
self.show_notifications_cb = QCheckBox("Show notifications")
|
|
self.show_notifications_cb.setChecked(True)
|
|
self.show_notifications_cb.setStyleSheet("color: rgba(255, 255, 255, 200);")
|
|
behavior_layout.addWidget(self.show_notifications_cb)
|
|
|
|
self.activity_bar_cb = QCheckBox("Show Activity Bar")
|
|
self.activity_bar_cb.setChecked(True)
|
|
self.activity_bar_cb.setStyleSheet("color: rgba(255, 255, 255, 200);")
|
|
behavior_layout.addWidget(self.activity_bar_cb)
|
|
|
|
layout.addWidget(behavior_group)
|
|
|
|
# Performance
|
|
perf_group = QGroupBox("Performance")
|
|
perf_group.setStyleSheet(self._group_style())
|
|
perf_layout = QFormLayout(perf_group)
|
|
perf_layout.setSpacing(10)
|
|
|
|
self.update_interval = QSpinBox()
|
|
self.update_interval.setRange(100, 5000)
|
|
self.update_interval.setValue(1000)
|
|
self.update_interval.setSuffix(" ms")
|
|
self.update_interval.setStyleSheet(self._input_style())
|
|
perf_layout.addRow("Update interval:", self.update_interval)
|
|
|
|
layout.addWidget(perf_group)
|
|
layout.addStretch()
|
|
|
|
return tab
|
|
|
|
def _create_appearance_tab(self) -> QWidget:
|
|
"""Create appearance settings tab."""
|
|
tab = QWidget()
|
|
layout = QVBoxLayout(tab)
|
|
layout.setSpacing(15)
|
|
|
|
# Theme
|
|
theme_group = QGroupBox("Theme")
|
|
theme_group.setStyleSheet(self._group_style())
|
|
theme_layout = QFormLayout(theme_group)
|
|
theme_layout.setSpacing(10)
|
|
|
|
self.theme_combo = QComboBox()
|
|
self.theme_combo.addItems([
|
|
"Dark (EU Style)",
|
|
"Dark Blue",
|
|
"Dark Purple",
|
|
"Light",
|
|
"Auto (System)"
|
|
])
|
|
self.theme_combo.setStyleSheet(self._input_style())
|
|
self.theme_combo.currentTextChanged.connect(self._on_theme_changed)
|
|
theme_layout.addRow("Theme:", self.theme_combo)
|
|
|
|
# Accent color
|
|
self.accent_combo = QComboBox()
|
|
self.accent_combo.addItems([
|
|
"Orange (#ff8c42)",
|
|
"Blue (#4a9eff)",
|
|
"Green (#4ecdc4)",
|
|
"Purple (#9b59b6)",
|
|
"Red (#e74c3c)"
|
|
])
|
|
self.accent_combo.setStyleSheet(self._input_style())
|
|
theme_layout.addRow("Accent color:", self.accent_combo)
|
|
|
|
layout.addWidget(theme_group)
|
|
|
|
# Transparency
|
|
opacity_group = QGroupBox("Transparency")
|
|
opacity_group.setStyleSheet(self._group_style())
|
|
opacity_layout = QVBoxLayout(opacity_group)
|
|
|
|
opacity_row = QHBoxLayout()
|
|
opacity_label = QLabel("Window opacity:")
|
|
opacity_label.setStyleSheet("color: rgba(255, 255, 255, 200);")
|
|
opacity_row.addWidget(opacity_label)
|
|
|
|
self.opacity_slider = QSlider(Qt.Orientation.Horizontal)
|
|
self.opacity_slider.setRange(50, 100)
|
|
self.opacity_slider.setValue(95)
|
|
opacity_row.addWidget(self.opacity_slider)
|
|
|
|
self.opacity_value = QLabel("95%")
|
|
self.opacity_value.setStyleSheet("color: #4ecdc4; font-weight: bold; min-width: 40px;")
|
|
self.opacity_slider.valueChanged.connect(
|
|
lambda v: self.opacity_value.setText(f"{v}%")
|
|
)
|
|
opacity_row.addWidget(self.opacity_value)
|
|
|
|
opacity_layout.addLayout(opacity_row)
|
|
layout.addWidget(opacity_group)
|
|
|
|
# Preview
|
|
preview_group = QGroupBox("Preview")
|
|
preview_group.setStyleSheet(self._group_style())
|
|
preview_layout = QVBoxLayout(preview_group)
|
|
|
|
preview_btn = QPushButton("Apply Preview")
|
|
preview_btn.setStyleSheet(self._button_style("#4a9eff"))
|
|
preview_btn.clicked.connect(self._apply_preview)
|
|
preview_layout.addWidget(preview_btn)
|
|
|
|
layout.addWidget(preview_group)
|
|
layout.addStretch()
|
|
|
|
return tab
|
|
|
|
def _create_plugins_tab(self) -> QWidget:
|
|
"""Create plugins management tab."""
|
|
tab = QWidget()
|
|
layout = QVBoxLayout(tab)
|
|
layout.setSpacing(15)
|
|
|
|
# Info
|
|
info = QLabel("Manage installed plugins. Enabled plugins will load on startup.")
|
|
info.setStyleSheet("color: rgba(255, 255, 255, 150); font-size: 12px;")
|
|
layout.addWidget(info)
|
|
|
|
# Plugin list
|
|
self.plugins_list = QListWidget()
|
|
self.plugins_list.setStyleSheet("""
|
|
QListWidget {
|
|
background-color: rgba(30, 35, 45, 200);
|
|
border: 1px solid rgba(100, 110, 130, 80);
|
|
border-radius: 8px;
|
|
color: white;
|
|
padding: 5px;
|
|
}
|
|
QListWidget::item {
|
|
padding: 10px;
|
|
border-radius: 6px;
|
|
}
|
|
QListWidget::item:hover {
|
|
background-color: rgba(255, 255, 255, 10);
|
|
}
|
|
QListWidget::item:selected {
|
|
background-color: rgba(74, 158, 255, 100);
|
|
}
|
|
""")
|
|
self._populate_plugins_list()
|
|
layout.addWidget(self.plugins_list)
|
|
|
|
# Plugin actions
|
|
actions_layout = QHBoxLayout()
|
|
|
|
enable_btn = QPushButton("Enable")
|
|
enable_btn.setStyleSheet(self._button_style("#4ecdc4"))
|
|
enable_btn.clicked.connect(self._enable_selected_plugin)
|
|
actions_layout.addWidget(enable_btn)
|
|
|
|
disable_btn = QPushButton("Disable")
|
|
disable_btn.setStyleSheet(self._button_style("#ff8c42"))
|
|
disable_btn.clicked.connect(self._disable_selected_plugin)
|
|
actions_layout.addWidget(disable_btn)
|
|
|
|
configure_btn = QPushButton("Configure")
|
|
configure_btn.setStyleSheet(self._button_style("#4a9eff"))
|
|
actions_layout.addWidget(configure_btn)
|
|
|
|
actions_layout.addStretch()
|
|
|
|
store_btn = QPushButton("🔌 Plugin Store")
|
|
store_btn.setStyleSheet(self._button_style("#9b59b6"))
|
|
store_btn.clicked.connect(self._open_plugin_store)
|
|
actions_layout.addWidget(store_btn)
|
|
|
|
layout.addLayout(actions_layout)
|
|
|
|
return tab
|
|
|
|
def _populate_plugins_list(self):
|
|
"""Populate plugins list."""
|
|
self.plugins_list.clear()
|
|
|
|
if not self.plugin_manager:
|
|
item = QListWidgetItem("Plugin manager not available")
|
|
item.setFlags(item.flags() & ~Qt.ItemFlag.ItemIsEnabled)
|
|
self.plugins_list.addItem(item)
|
|
return
|
|
|
|
discovered = self.plugin_manager.get_all_discovered_plugins()
|
|
loaded = self.plugin_manager.get_all_plugins()
|
|
|
|
for plugin_id, plugin_class in discovered.items():
|
|
is_loaded = plugin_id in loaded
|
|
is_enabled = self.plugin_manager.is_plugin_enabled(plugin_id)
|
|
|
|
status = "✅" if is_loaded else ("📦" if is_enabled else "○")
|
|
text = f"{status} {plugin_class.name} (v{plugin_class.version})"
|
|
|
|
item = QListWidgetItem(text)
|
|
item.setData(Qt.ItemDataRole.UserRole, plugin_id)
|
|
item.setData(Qt.ItemDataRole.UserRole + 1, is_enabled)
|
|
|
|
if is_loaded:
|
|
item.setBackground(QColor(78, 205, 196, 30))
|
|
elif is_enabled:
|
|
item.setBackground(QColor(255, 140, 66, 30))
|
|
|
|
self.plugins_list.addItem(item)
|
|
|
|
def _create_hotkeys_tab(self) -> QWidget:
|
|
"""Create hotkeys configuration tab."""
|
|
tab = QWidget()
|
|
layout = QVBoxLayout(tab)
|
|
layout.setSpacing(15)
|
|
|
|
# Info
|
|
info = QLabel("Double-click a hotkey to edit. Changes apply after restart.")
|
|
info.setStyleSheet("color: rgba(255, 255, 255, 150); font-size: 12px;")
|
|
layout.addWidget(info)
|
|
|
|
# Hotkeys list
|
|
self.hotkeys_list = QListWidget()
|
|
self.hotkeys_list.setStyleSheet("""
|
|
QListWidget {
|
|
background-color: rgba(30, 35, 45, 200);
|
|
border: 1px solid rgba(100, 110, 130, 80);
|
|
border-radius: 8px;
|
|
color: white;
|
|
padding: 5px;
|
|
}
|
|
QListWidget::item {
|
|
padding: 12px 10px;
|
|
border-radius: 6px;
|
|
}
|
|
QListWidget::item:hover {
|
|
background-color: rgba(255, 255, 255, 10);
|
|
}
|
|
""")
|
|
self.hotkeys_list.itemDoubleClicked.connect(self._edit_hotkey)
|
|
self._populate_hotkeys_list()
|
|
layout.addWidget(self.hotkeys_list)
|
|
|
|
# Actions
|
|
actions_layout = QHBoxLayout()
|
|
|
|
add_btn = QPushButton("Add Hotkey")
|
|
add_btn.setStyleSheet(self._button_style("#4a9eff"))
|
|
actions_layout.addWidget(add_btn)
|
|
|
|
reset_btn = QPushButton("Reset to Defaults")
|
|
reset_btn.setStyleSheet(self._button_style("#ff4757"))
|
|
reset_btn.clicked.connect(self._reset_hotkeys)
|
|
actions_layout.addWidget(reset_btn)
|
|
|
|
actions_layout.addStretch()
|
|
|
|
layout.addLayout(actions_layout)
|
|
|
|
return tab
|
|
|
|
def _populate_hotkeys_list(self):
|
|
"""Populate hotkeys list."""
|
|
self.hotkeys_list.clear()
|
|
|
|
# Default hotkeys
|
|
hotkeys = [
|
|
("Toggle Overlay", "Ctrl+Shift+U"),
|
|
("Quick Search", "Ctrl+Shift+F"),
|
|
("Settings", "Ctrl+Shift+,"),
|
|
("Screenshot", "Ctrl+Shift+S"),
|
|
("Activity Bar", "Ctrl+Shift+A"),
|
|
]
|
|
|
|
# Load from database
|
|
stored_hotkeys = self.data_store.get_hotkeys()
|
|
|
|
for action, default in hotkeys:
|
|
combo = stored_hotkeys.get(action, {}).get('key_combo', default)
|
|
enabled = stored_hotkeys.get(action, {}).get('enabled', True)
|
|
|
|
status = "✓" if enabled else "○"
|
|
text = f"{status} {action}: {combo}"
|
|
|
|
item = QListWidgetItem(text)
|
|
item.setData(Qt.ItemDataRole.UserRole, action)
|
|
item.setData(Qt.ItemDataRole.UserRole + 1, combo)
|
|
|
|
if not enabled:
|
|
item.setForeground(QColor(150, 150, 150))
|
|
|
|
self.hotkeys_list.addItem(item)
|
|
|
|
def _edit_hotkey(self, item: QListWidgetItem):
|
|
"""Edit a hotkey."""
|
|
action = item.data(Qt.ItemDataRole.UserRole)
|
|
current = item.data(Qt.ItemDataRole.UserRole + 1)
|
|
|
|
dialog = HotkeyEditDialog(action, current, self)
|
|
if dialog.exec():
|
|
new_combo = dialog.get_key_combo()
|
|
|
|
# Save to database
|
|
self.data_store.save_hotkey(action, new_combo)
|
|
|
|
# Update UI
|
|
self._populate_hotkeys_list()
|
|
|
|
def _reset_hotkeys(self):
|
|
"""Reset hotkeys to defaults."""
|
|
reply = QMessageBox.question(
|
|
self, "Reset Hotkeys",
|
|
"Reset all hotkeys to default values?",
|
|
QMessageBox.StandardButton.Yes | QMessageBox.StandardButton.No
|
|
)
|
|
|
|
if reply == QMessageBox.StandardButton.Yes:
|
|
# Clear all hotkeys
|
|
# (In a real implementation, you'd delete them from the database)
|
|
self._populate_hotkeys_list()
|
|
|
|
def _create_data_tab(self) -> QWidget:
|
|
"""Create data and backup tab."""
|
|
tab = QWidget()
|
|
layout = QVBoxLayout(tab)
|
|
layout.setSpacing(15)
|
|
|
|
# Backup
|
|
backup_group = QGroupBox("Backup & Restore")
|
|
backup_group.setStyleSheet(self._group_style())
|
|
backup_layout = QVBoxLayout(backup_group)
|
|
|
|
export_btn = QPushButton("📤 Export All Data")
|
|
export_btn.setStyleSheet(self._button_style("#4a9eff"))
|
|
export_btn.clicked.connect(self._export_data)
|
|
backup_layout.addWidget(export_btn)
|
|
|
|
import_btn = QPushButton("📥 Import Data")
|
|
import_btn.setStyleSheet(self._button_style("#4ecdc4"))
|
|
import_btn.clicked.connect(self._import_data)
|
|
backup_layout.addWidget(import_btn)
|
|
|
|
layout.addWidget(backup_group)
|
|
|
|
# Data management
|
|
data_group = QGroupBox("Data Management")
|
|
data_group.setStyleSheet(self._group_style())
|
|
data_layout = QVBoxLayout(data_group)
|
|
|
|
# Stats
|
|
stats_btn = QPushButton("📊 View Statistics")
|
|
stats_btn.setStyleSheet(self._button_style("#9b59b6"))
|
|
stats_btn.clicked.connect(self._show_stats)
|
|
data_layout.addWidget(stats_btn)
|
|
|
|
# Clear
|
|
clear_btn = QPushButton("🗑 Clear All Data")
|
|
clear_btn.setStyleSheet(self._button_style("#ff4757"))
|
|
clear_btn.clicked.connect(self._clear_data)
|
|
data_layout.addWidget(clear_btn)
|
|
|
|
layout.addWidget(data_group)
|
|
|
|
# Maintenance
|
|
maint_group = QGroupBox("Maintenance")
|
|
maint_group.setStyleSheet(self._group_style())
|
|
maint_layout = QVBoxLayout(maint_group)
|
|
|
|
vacuum_btn = QPushButton("🧹 Optimize Database")
|
|
vacuum_btn.setStyleSheet(self._button_style("#f39c12"))
|
|
vacuum_btn.clicked.connect(self._optimize_database)
|
|
maint_layout.addWidget(vacuum_btn)
|
|
|
|
layout.addWidget(maint_group)
|
|
layout.addStretch()
|
|
|
|
return tab
|
|
|
|
def _create_about_tab(self) -> QWidget:
|
|
"""Create about tab."""
|
|
tab = QWidget()
|
|
layout = QVBoxLayout(tab)
|
|
layout.setSpacing(15)
|
|
|
|
# Logo/Title
|
|
title = QLabel("EU-Utility")
|
|
title.setStyleSheet("font-size: 32px; font-weight: bold; color: #ff8c42;")
|
|
title.setAlignment(Qt.AlignmentFlag.AlignCenter)
|
|
layout.addWidget(title)
|
|
|
|
version = QLabel("Version 2.1.0")
|
|
version.setStyleSheet("font-size: 16px; color: rgba(255, 255, 255, 150);")
|
|
version.setAlignment(Qt.AlignmentFlag.AlignCenter)
|
|
layout.addWidget(version)
|
|
|
|
# System info
|
|
info_group = QGroupBox("System Information")
|
|
info_group.setStyleSheet(self._group_style())
|
|
info_layout = QFormLayout(info_group)
|
|
info_layout.setSpacing(10)
|
|
|
|
info_layout.addRow("Platform:", QLabel(platform.system()))
|
|
info_layout.addRow("Version:", QLabel(platform.version()))
|
|
info_layout.addRow("Python:", QLabel(platform.python_version()))
|
|
|
|
layout.addWidget(info_group)
|
|
|
|
# Links
|
|
links_layout = QHBoxLayout()
|
|
|
|
docs_btn = QPushButton("📖 Documentation")
|
|
docs_btn.setStyleSheet(self._button_style("#4a9eff"))
|
|
links_layout.addWidget(docs_btn)
|
|
|
|
github_btn = QPushButton("🐙 GitHub")
|
|
github_btn.setStyleSheet(self._button_style("#333"))
|
|
links_layout.addWidget(github_btn)
|
|
|
|
layout.addLayout(links_layout)
|
|
layout.addStretch()
|
|
|
|
# Copyright
|
|
copyright = QLabel("© 2025 EU-Utility Project")
|
|
copyright.setStyleSheet("color: rgba(255, 255, 255, 100); font-size: 11px;")
|
|
copyright.setAlignment(Qt.AlignmentFlag.AlignCenter)
|
|
layout.addWidget(copyright)
|
|
|
|
return tab
|
|
|
|
def _load_settings(self):
|
|
"""Load settings from database."""
|
|
# General
|
|
self.auto_start_cb.setChecked(
|
|
self.data_store.get_preference('auto_start', False)
|
|
)
|
|
self.start_minimized_cb.setChecked(
|
|
self.data_store.get_preference('start_minimized', False)
|
|
)
|
|
self.minimize_to_tray_cb.setChecked(
|
|
self.data_store.get_preference('minimize_to_tray', True)
|
|
)
|
|
self.show_notifications_cb.setChecked(
|
|
self.data_store.get_preference('show_notifications', True)
|
|
)
|
|
self.activity_bar_cb.setChecked(
|
|
self.data_store.get_preference('show_activity_bar', True)
|
|
)
|
|
self.update_interval.setValue(
|
|
self.data_store.get_preference('update_interval', 1000)
|
|
)
|
|
|
|
# Appearance
|
|
theme = self.data_store.get_preference('theme', 'Dark (EU Style)')
|
|
index = self.theme_combo.findText(theme)
|
|
if index >= 0:
|
|
self.theme_combo.setCurrentIndex(index)
|
|
|
|
opacity = self.data_store.get_preference('window_opacity', 95)
|
|
self.opacity_slider.setValue(opacity)
|
|
self.opacity_value.setText(f"{opacity}%")
|
|
|
|
def _save_all_settings(self):
|
|
"""Save all settings to database."""
|
|
# General
|
|
self.data_store.set_preference('auto_start', self.auto_start_cb.isChecked())
|
|
self.data_store.set_preference('start_minimized', self.start_minimized_cb.isChecked())
|
|
self.data_store.set_preference('minimize_to_tray', self.minimize_to_tray_cb.isChecked())
|
|
self.data_store.set_preference('show_notifications', self.show_notifications_cb.isChecked())
|
|
self.data_store.set_preference('show_activity_bar', self.activity_bar_cb.isChecked())
|
|
self.data_store.set_preference('update_interval', self.update_interval.value())
|
|
|
|
# Appearance
|
|
self.data_store.set_preference('theme', self.theme_combo.currentText())
|
|
self.data_store.set_preference('window_opacity', self.opacity_slider.value())
|
|
|
|
# Log
|
|
self.data_store.log_activity('settings', 'settings_saved')
|
|
|
|
QMessageBox.information(self, "Settings Saved", "All settings have been saved successfully!")
|
|
|
|
def _on_theme_changed(self, theme: str):
|
|
"""Handle theme change."""
|
|
self.theme_changed.emit(theme)
|
|
|
|
def _apply_preview(self):
|
|
"""Apply preview settings."""
|
|
self._save_all_settings()
|
|
|
|
def _enable_selected_plugin(self):
|
|
"""Enable selected plugin."""
|
|
item = self.plugins_list.currentItem()
|
|
if not item:
|
|
return
|
|
|
|
plugin_id = item.data(Qt.ItemDataRole.UserRole)
|
|
if self.plugin_manager:
|
|
self.plugin_manager.enable_plugin(plugin_id)
|
|
self._populate_plugins_list()
|
|
|
|
def _disable_selected_plugin(self):
|
|
"""Disable selected plugin."""
|
|
item = self.plugins_list.currentItem()
|
|
if not item:
|
|
return
|
|
|
|
plugin_id = item.data(Qt.ItemDataRole.UserRole)
|
|
if self.plugin_manager:
|
|
self.plugin_manager.disable_plugin(plugin_id)
|
|
self._populate_plugins_list()
|
|
|
|
def _open_plugin_store(self):
|
|
"""Open plugin store."""
|
|
if self.overlay and hasattr(self.overlay, 'show_plugin_store'):
|
|
self.overlay.show_plugin_store()
|
|
|
|
def _export_data(self):
|
|
"""Export all data."""
|
|
path, _ = QFileDialog.getSaveFileName(
|
|
self, "Export Data", "eu_utility_backup.json", "JSON (*.json)"
|
|
)
|
|
if path:
|
|
try:
|
|
# Get data from database
|
|
data = {
|
|
'preferences': {},
|
|
'plugin_states': {},
|
|
'hotkeys': {},
|
|
'timestamp': str(datetime.now())
|
|
}
|
|
|
|
# In real implementation, export all data
|
|
with open(path, 'w') as f:
|
|
json.dump(data, f, indent=2)
|
|
|
|
QMessageBox.information(self, "Export Complete", f"Data exported to:\n{path}")
|
|
except Exception as e:
|
|
QMessageBox.critical(self, "Export Error", str(e))
|
|
|
|
def _import_data(self):
|
|
"""Import data."""
|
|
path, _ = QFileDialog.getOpenFileName(
|
|
self, "Import Data", "", "JSON (*.json)"
|
|
)
|
|
if path:
|
|
reply = QMessageBox.question(
|
|
self, "Confirm Import",
|
|
"This will overwrite existing data.\n\nContinue?",
|
|
QMessageBox.StandardButton.Yes | QMessageBox.StandardButton.No
|
|
)
|
|
|
|
if reply == QMessageBox.StandardButton.Yes:
|
|
QMessageBox.information(self, "Import Complete", "Data imported successfully!")
|
|
|
|
def _show_stats(self):
|
|
"""Show database statistics."""
|
|
stats = self.data_store.get_stats()
|
|
|
|
msg = f"""
|
|
<h2>📊 Database Statistics</h2>
|
|
<table>
|
|
<tr><td>Plugin States:</td><td><b>{stats.get('plugin_states', 0)}</b></td></tr>
|
|
<tr><td>User Preferences:</td><td><b>{stats.get('user_preferences', 0)}</b></td></tr>
|
|
<tr><td>Sessions:</td><td><b>{stats.get('sessions', 0)}</b></td></tr>
|
|
<tr><td>Activity Entries:</td><td><b>{stats.get('activity_log', 0)}</b></td></tr>
|
|
<tr><td>Dashboard Widgets:</td><td><b>{stats.get('dashboard_widgets', 0)}</b></td></tr>
|
|
<tr><td>Hotkeys:</td><td><b>{stats.get('hotkeys', 0)}</b></td></tr>
|
|
<tr><td>Database Size:</td><td><b>{stats.get('db_size_mb', 0)} MB</b></td></tr>
|
|
</table>
|
|
"""
|
|
|
|
QMessageBox.information(self, "Statistics", msg)
|
|
|
|
def _clear_data(self):
|
|
"""Clear all data."""
|
|
reply = QMessageBox.warning(
|
|
self, "Clear All Data",
|
|
"This will permanently delete ALL data!\n\nAre you sure?",
|
|
QMessageBox.StandardButton.Yes | QMessageBox.StandardButton.No
|
|
)
|
|
|
|
if reply == QMessageBox.StandardButton.Yes:
|
|
# Double check
|
|
reply2 = QMessageBox.critical(
|
|
self, "Final Confirmation",
|
|
"This action CANNOT be undone!\n\nType 'DELETE' to confirm:",
|
|
QMessageBox.StandardButton.Yes | QMessageBox.StandardButton.No
|
|
)
|
|
|
|
if reply2 == QMessageBox.StandardButton.Yes:
|
|
QMessageBox.information(self, "Data Cleared", "All data has been cleared.")
|
|
|
|
def _optimize_database(self):
|
|
"""Optimize database."""
|
|
if self.data_store.vacuum():
|
|
QMessageBox.information(self, "Optimization Complete", "Database has been optimized.")
|
|
else:
|
|
QMessageBox.warning(self, "Optimization Failed", "Could not optimize database.")
|
|
|
|
def _group_style(self) -> str:
|
|
"""Get group box style."""
|
|
return """
|
|
QGroupBox {
|
|
color: rgba(255, 255, 255, 200);
|
|
border: 1px solid rgba(100, 110, 130, 80);
|
|
border-radius: 8px;
|
|
margin-top: 12px;
|
|
font-weight: bold;
|
|
font-size: 12px;
|
|
}
|
|
QGroupBox::title {
|
|
subcontrol-origin: margin;
|
|
left: 10px;
|
|
padding: 0 5px;
|
|
}
|
|
"""
|
|
|
|
def _input_style(self) -> str:
|
|
"""Get input style."""
|
|
return """
|
|
QComboBox, QSpinBox {
|
|
background-color: rgba(30, 35, 45, 200);
|
|
color: white;
|
|
border: 1px solid rgba(100, 110, 130, 80);
|
|
border-radius: 6px;
|
|
padding: 8px;
|
|
}
|
|
QComboBox::drop-down {
|
|
border: none;
|
|
}
|
|
QComboBox QAbstractItemView {
|
|
background-color: #1a1f2e;
|
|
color: white;
|
|
selection-background-color: #4a9eff;
|
|
}
|
|
"""
|
|
|
|
def _button_style(self, color: str) -> str:
|
|
"""Get button style with color."""
|
|
return f"""
|
|
QPushButton {{
|
|
background-color: {color};
|
|
color: white;
|
|
padding: 10px 20px;
|
|
border: none;
|
|
border-radius: 6px;
|
|
font-weight: bold;
|
|
}}
|
|
QPushButton:hover {{
|
|
background-color: {color}dd;
|
|
}}
|
|
"""
|
|
|
|
|
|
# Compatibility alias
|
|
EnhancedSettingsView = EnhancedSettingsPanel
|