diff --git a/UI_TRANSFORMATION_SUMMARY.md b/UI_TRANSFORMATION_SUMMARY.md new file mode 100644 index 0000000..46ee421 --- /dev/null +++ b/UI_TRANSFORMATION_SUMMARY.md @@ -0,0 +1,96 @@ +# UI/UX Excellence Transformation - Summary + +## Overview +Successfully transformed EU-Utility's UI to be professional, polished, and completely emoji-free. + +## Changes Made + +### 1. SVG Icons Created (assets/icons/) +- `dashboard.svg` - Grid-based dashboard icon +- `plugins.svg` - Monitor/plugins icon +- `widgets.svg` - Widget grid icon +- `settings.svg` - Gear/cog icon (Phosphor style) +- `search.svg` - Magnifying glass icon +- `clock.svg` - Clock/time icon +- `menu.svg` - Hamburger menu icon +- `close.svg` - X close icon +- `minimize.svg` - Minimize dash icon +- `pin.svg` - Star/pin icon +- `check.svg` - Checkmark icon +- `warning.svg` - Triangle warning icon +- `info.svg` - Information circle icon +- `more.svg` - Three dots/more icon + +All icons are: +- 32px optimized SVG files +- Monochrome (white stroke) +- Phosphor Icons style +- Consistent 2px stroke width +- Clean, minimalist design + +### 2. Files Updated - Emojis Removed + +#### core/perfect_ux.py +- NavigationRail: Replaced text emojis (◆, 🔌, 🎨, ⚙️) with SVG icons +- Button: Added icon support via `icon` parameter +- Activity items: Replaced emoji status icons with SVG icons (check, info, more) +- Quick Actions: Replaced emoji buttons with SVG icons (camera, package, globe, bar-chart) +- Added glassmorphism effects to Surface component +- Orange left border (3px) on active navigation items +- EU color scheme: dark blue (#141f23), orange accent (#ff8c42) + +#### core/activity_bar.py +- Start button: Replaced ⊞ emoji with grid SVG icon +- Plugin buttons: Now use icon_name attribute with SVG icons +- Clock: Added clock SVG icon next to time display +- Context menu: Removed emoji from "Settings" and "Hide" actions +- Drawer items: Now display plugin icons + +#### core/ui/dashboard_view.py +- Header: Added dashboard SVG icon +- Plugin Store button: Replaced 🔌 emoji with shopping-bag SVG icon +- Plugin Widgets section: Removed 🔌 emoji from label +- Updated styling to match EU color palette + +#### core/ui/search_view.py +- Header: Added search SVG icon, removed 🔍 emoji +- Hint text: Removed 💡 emoji +- Updated border colors to use EU orange accent + +#### core/ui/settings_view.py +- Header: Added settings SVG icon, removed ⚙️ emoji +- Tab labels: Removed emojis (🔌, 📦, ⌨️, 💾, 🔄) +- Button labels: Removed emojis (📤, 📥, 🗑, 🔍) +- Updated styling to EU color palette + +### 3. Design System Improvements + +#### Color Palette +- Primary Background: #141f23 (EU dark blue) +- Accent Color: #ff8c42 (EU orange) +- Surface: rgba(20, 31, 35, 0.95) with glassmorphism +- Borders: rgba(255, 140, 66, 0.1) subtle orange tint + +#### Spacing (8dp Grid) +- XS: 4px +- S: 8px +- M: 16px +- L: 24px +- XL: 32px + +#### Active State Indicators +- Orange left border (3px) on active navigation items +- Background highlight on hover +- Smooth transitions (150-350ms) + +### 4. Integration +- All UI components now use `icon_manager.get_icon()` and `icon_manager.get_pixmap()` +- Consistent 24px icon size in navigation +- Consistent 20px icon size in buttons +- Tooltips for all icon-only buttons + +## Verification +- All main UI files are now emoji-free +- 50 total SVG icons in assets/icons/ +- Professional, consistent appearance throughout +- EU brand colors applied consistently diff --git a/core/tray_icon.py b/core/tray_icon.py index c9464e7..bed03c4 100644 --- a/core/tray_icon.py +++ b/core/tray_icon.py @@ -6,8 +6,8 @@ Simple, responsive system tray icon. """ from PyQt6.QtWidgets import QSystemTrayIcon, QMenu, QApplication, QWidget -from PyQt6.QtGui import QAction, QIcon, QColor, QPainter, QFont -from PyQt6.QtCore import pyqtSignal +from PyQt6.QtGui import QAction, QIcon, QColor, QPainter, QFont, QPixmap +from PyQt6.QtCore import pyqtSignal, Qt class TrayIcon(QWidget): diff --git a/core/ui/settings_panel.py b/core/ui/settings_panel.py index 73fdfaf..95c2247 100644 --- a/core/ui/settings_panel.py +++ b/core/ui/settings_panel.py @@ -8,6 +8,7 @@ import json import platform from pathlib import Path from typing import Dict, Any, Optional +from datetime import datetime from PyQt6.QtWidgets import ( QWidget, QVBoxLayout, QHBoxLayout, QLabel, QPushButton, diff --git a/core/ui/settings_view.py b/core/ui/settings_view.py index 8cc36ac..920e3b8 100644 --- a/core/ui/settings_view.py +++ b/core/ui/settings_view.py @@ -12,6 +12,8 @@ from PyQt6.QtWidgets import ( ) from PyQt6.QtCore import Qt +from core.icon_manager import get_icon_manager + class SettingsView(QWidget): """Main settings interface - built into the framework.""" @@ -21,25 +23,37 @@ class SettingsView(QWidget): self.overlay = overlay_window self.settings = overlay_window.settings if hasattr(overlay_window, 'settings') else {} self.plugin_manager = overlay_window.plugin_manager if hasattr(overlay_window, 'plugin_manager') else None + self.icon_manager = get_icon_manager() self._setup_ui() def _setup_ui(self): """Create the settings UI.""" layout = QVBoxLayout(self) - layout.setSpacing(15) - layout.setContentsMargins(20, 20, 20, 20) + layout.setSpacing(16) + layout.setContentsMargins(24, 24, 24, 24) - # Header - header = QLabel("⚙️ Settings") + # Header with icon + header_layout = QHBoxLayout() + header_layout.setSpacing(12) + + header_icon = QLabel() + header_pixmap = self.icon_manager.get_pixmap("settings", size=28) + header_icon.setPixmap(header_pixmap) + header_layout.addWidget(header_icon) + + header = QLabel("Settings") header.setStyleSheet("font-size: 24px; font-weight: bold; color: white;") - layout.addWidget(header) + header_layout.addWidget(header) + header_layout.addStretch() + + layout.addLayout(header_layout) # Tabs self.tabs = QTabWidget() self.tabs.setStyleSheet(""" QTabBar::tab { - background-color: rgba(35, 40, 55, 200); + background-color: rgba(20, 31, 35, 0.95); color: rgba(255,255,255,150); padding: 10px 20px; border-top-left-radius: 6px; @@ -54,11 +68,11 @@ class SettingsView(QWidget): # Add tabs self.tabs.addTab(self._create_general_tab(), "General") - self.tabs.addTab(self._create_plugin_store_tab(), "🔌 Plugin Store") - self.tabs.addTab(self._create_plugins_tab(), "📦 My Plugins") - self.tabs.addTab(self._create_hotkeys_tab(), "⌨️ Hotkeys") - self.tabs.addTab(self._create_data_tab(), "💾 Data & Backup") - self.tabs.addTab(self._create_updates_tab(), "🔄 Updates") + self.tabs.addTab(self._create_plugin_store_tab(), "Plugin Store") + self.tabs.addTab(self._create_plugins_tab(), "My Plugins") + self.tabs.addTab(self._create_hotkeys_tab(), "Hotkeys") + self.tabs.addTab(self._create_data_tab(), "Data & Backup") + self.tabs.addTab(self._create_updates_tab(), "Updates") layout.addWidget(self.tabs) @@ -66,7 +80,7 @@ class SettingsView(QWidget): """Create general settings tab.""" tab = QWidget() layout = QVBoxLayout(tab) - layout.setSpacing(15) + layout.setSpacing(16) # Appearance appear_group = QGroupBox("Appearance") @@ -190,7 +204,7 @@ class SettingsView(QWidget): # Separator sep = QFrame() sep.setFrameShape(QFrame.Shape.HLine) - sep.setStyleSheet("background-color: rgba(100, 110, 130, 40);") + sep.setStyleSheet("background-color: rgba(255, 140, 66, 0.1);") sep.setFixedHeight(1) self.plugins_layout.addWidget(sep) @@ -210,7 +224,7 @@ class SettingsView(QWidget): """Create hotkeys configuration tab.""" tab = QWidget() layout = QVBoxLayout(tab) - layout.setSpacing(15) + layout.setSpacing(16) info = QLabel("Configure keyboard shortcuts. Changes apply on restart.") info.setStyleSheet("color: rgba(255,255,255,150);") @@ -234,9 +248,9 @@ class SettingsView(QWidget): input_field = QLineEdit(default) input_field.setStyleSheet(""" QLineEdit { - background-color: rgba(30, 35, 45, 200); + background-color: rgba(20, 31, 35, 0.95); color: white; - border: 1px solid rgba(100, 110, 130, 80); + border: 1px solid rgba(255, 140, 66, 0.2); padding: 5px; min-width: 150px; } @@ -254,19 +268,19 @@ class SettingsView(QWidget): """Create data and backup tab.""" tab = QWidget() layout = QVBoxLayout(tab) - layout.setSpacing(15) + layout.setSpacing(16) # Backup section 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 = QPushButton("Export All Data") + export_btn.setStyleSheet(self._button_style("#ff8c42")) export_btn.clicked.connect(self._export_data) backup_layout.addWidget(export_btn) - import_btn = QPushButton("📥 Import Data") + import_btn = QPushButton("Import Data") import_btn.setStyleSheet(self._button_style("#4ecdc4")) import_btn.clicked.connect(self._import_data) backup_layout.addWidget(import_btn) @@ -278,7 +292,7 @@ class SettingsView(QWidget): cleanup_group.setStyleSheet(self._group_style()) cleanup_layout = QVBoxLayout(cleanup_group) - clear_btn = QPushButton("🗑 Clear All Data") + clear_btn = QPushButton("Clear All Data") clear_btn.setStyleSheet(self._button_style("#ff4757")) clear_btn.clicked.connect(self._clear_data) cleanup_layout.addWidget(clear_btn) @@ -292,7 +306,7 @@ class SettingsView(QWidget): """Create auto-updater settings tab.""" tab = QWidget() layout = QVBoxLayout(tab) - layout.setSpacing(15) + layout.setSpacing(16) # Auto-update settings update_group = QGroupBox("Automatic Updates") @@ -311,7 +325,7 @@ class SettingsView(QWidget): layout.addWidget(update_group) # Manual check - check_btn = QPushButton("🔍 Check for Updates Now") + check_btn = QPushButton("Check for Updates Now") check_btn.setStyleSheet(self._button_style("#ff8c42")) check_btn.clicked.connect(self._check_updates) layout.addWidget(check_btn) @@ -355,7 +369,7 @@ class SettingsView(QWidget): return """ QGroupBox { color: rgba(255,255,255,200); - border: 1px solid rgba(100, 110, 130, 80); + border: 1px solid rgba(255, 140, 66, 0.2); border-radius: 6px; margin-top: 10px; font-weight: bold; diff --git a/core/widgets/dashboard_widgets.py b/core/widgets/dashboard_widgets.py index b528363..a56caf5 100644 --- a/core/widgets/dashboard_widgets.py +++ b/core/widgets/dashboard_widgets.py @@ -5,10 +5,16 @@ System Status, Quick Actions, Recent Activity, and Plugin Grid widgets. """ import os -import psutil from datetime import datetime from typing import Dict, List, Callable, Optional +try: + import psutil + HAS_PSUTIL = True +except ImportError: + HAS_PSUTIL = False + psutil = None + from PyQt6.QtWidgets import ( QWidget, QVBoxLayout, QHBoxLayout, QLabel, QPushButton, QProgressBar, QFrame, QGridLayout, QSizePolicy, QScrollArea, @@ -214,6 +220,14 @@ class SystemStatusWidget(DashboardWidget): def _update_stats(self): """Update system statistics.""" + if not HAS_PSUTIL: + # Fallback when psutil is not available + self.cpu_value.setText("N/A") + self.ram_value.setText("N/A") + self.disk_value.setText("N/A") + self._update_services() + return + try: # CPU cpu_percent = psutil.cpu_percent(interval=0.1)