Auto-sync: 2026-02-16 21:15

This commit is contained in:
devmatrix 2026-02-16 21:15:16 +00:00
parent 08e8da0f4c
commit 0e5a7148fd
17 changed files with 1395 additions and 2760 deletions

View File

@ -1,229 +0,0 @@
# EU-Utility Bug Fix Report
## Summary
This document details all bugs, errors, and issues fixed in the EU-Utility codebase during the bug hunting session.
---
## Fixed Issues
### 1. **Missing QAction Import in activity_bar.py**
**File:** `core/activity_bar.py`
**Line:** 5
**Issue:** `QAction` was used in `_show_context_menu()` method but not imported from `PyQt6.QtGui`.
**Fix:** Added `QAction` to the imports from `PyQt6.QtGui`.
```python
# Before:
from PyQt6.QtGui import QMouseEvent, QPainter, QColor, QFont, QIcon, QPixmap
# After:
from PyQt6.QtGui import QMouseEvent, QPainter, QColor, QFont, QIcon, QPixmap, QAction
```
---
### 2. **Invalid QPropertyAnimation Property (windowOpacity) in perfect_ux.py**
**File:** `core/perfect_ux.py`
**Line:** 904-930
**Issue:** The `_animate_transition()` method used `b"windowOpacity"` as a property for QPropertyAnimation, but `windowOpacity` is not a valid animatable property on QWidget in Qt6. This would cause runtime errors when switching views.
**Fix:** Added `QGraphicsOpacityEffect` and modified the animation to animate the `opacity` property of the effect instead of the widget directly.
```python
# Before:
fade_out = QPropertyAnimation(current, b"windowOpacity")
# After:
current._opacity_effect = QGraphicsOpacityEffect(current)
current.setGraphicsEffect(current._opacity_effect)
fade_out = QPropertyAnimation(current._opacity_effect, b"opacity")
```
---
### 3. **Invalid QPropertyAnimation Property (windowOpacity) in overlay_window.py**
**File:** `core/overlay_window.py`
**Line:** 527-540
**Issue:** Same issue as above - `windowOpacity` property cannot be animated directly on QWidget in Qt6.
**Fix:** Created a `QGraphicsOpacityEffect` for the window and animated its `opacity` property.
---
### 4. **Missing show()/hide() Methods in TrayIcon**
**File:** `core/tray_icon.py`
**Line:** 61-79
**Issue:** The `TrayIcon` class inherited from `QWidget` but didn't implement `show()` and `hide()` methods that delegate to the internal `QSystemTrayIcon`. Other code expected these methods to exist.
**Fix:** Added `show()`, `hide()`, and `isVisible()` methods that properly delegate to the internal tray icon.
```python
def show(self):
"""Show the tray icon."""
if self.tray_icon:
self.tray_icon.show()
def hide(self):
"""Hide the tray icon."""
if self.tray_icon:
self.tray_icon.hide()
def isVisible(self):
"""Check if tray icon is visible."""
return self.tray_icon.isVisible() if self.tray_icon else False
```
---
### 5. **Qt6 AA_EnableHighDpiScaling Deprecation Warning**
**File:** `core/main.py`
**Line:** 81-86
**Issue:** The `Qt.AA_EnableHighDpiScaling` attribute is deprecated in Qt6 and always enabled by default. While the existing code didn't cause errors due to the `hasattr` check, it was unnecessary.
**Fix:** Added proper try/except handling and comments explaining the Qt6 compatibility.
```python
# Enable high DPI scaling (Qt6 has this enabled by default)
# This block is kept for backwards compatibility with Qt5 if ever needed
if hasattr(Qt, 'AA_EnableHighDpiScaling'):
try:
self.app.setAttribute(Qt.ApplicationAttribute.AA_EnableHighDpiScaling)
except (AttributeError, TypeError):
pass # Qt6+ doesn't need this
```
---
### 6. **Unsafe Attribute Access in Activity Bar**
**File:** `core/activity_bar.py`
**Lines:** Multiple locations
**Issue:** Various methods accessed `plugin_class.name`, `self.drawer`, and other attributes without checking if they exist first. This could cause `AttributeError` exceptions.
**Fix:** Added `getattr()` calls with default values throughout:
```python
# Before:
plugin_name = plugin_class.name
# After:
plugin_name = getattr(plugin_class, 'name', plugin_id)
```
Also added `hasattr()` checks for `self.drawer` before accessing it.
---
### 7. **Missing Error Handling in Activity Bar Initialization**
**File:** `core/main.py`
**Line:** 127-139
**Issue:** Activity Bar initialization was not wrapped in try/except, so any error during creation would crash the entire application.
**Fix:** Wrapped the activity bar creation and initialization in a try/except block with proper error messages.
```python
try:
from core.activity_bar import get_activity_bar
self.activity_bar = get_activity_bar(self.plugin_manager)
if self.activity_bar:
if self.activity_bar.config.enabled:
# ... setup code ...
else:
print("[Core] Activity Bar disabled in config")
else:
print("[Core] Activity Bar not available")
self.activity_bar = None
except Exception as e:
print(f"[Core] Failed to create Activity Bar: {e}")
self.activity_bar = None
```
---
### 8. **Missing Error Handling in EU Focus Detection**
**File:** `core/main.py`
**Line:** 405-450
**Issue:** The `_check_eu_focus()` method had unsafe attribute access and could fail if `window_manager` or `activity_bar` were not properly initialized.
**Fix:** Added comprehensive error handling with `hasattr()` checks and try/except blocks around all UI operations.
---
### 9. **Unsafe Attribute Access in Plugin Manager**
**File:** `core/plugin_manager.py`
**Lines:** Multiple locations
**Issue:** Plugin loading code accessed `plugin_class.name` and `plugin_class.__name__` without checking if these attributes exist, and didn't handle cases where plugin classes might be malformed.
**Fix:** Added safe attribute access with `getattr()` and `hasattr()` checks throughout the plugin loading pipeline.
```python
# Before:
print(f"[PluginManager] Skipping disabled plugin: {plugin_class.name}")
# After:
plugin_name = getattr(plugin_class, 'name', plugin_class.__name__ if hasattr(plugin_class, '__name__') else 'Unknown')
print(f"[PluginManager] Skipping disabled plugin: {plugin_name}")
```
---
### 10. **Missing Error Handling in _toggle_activity_bar**
**File:** `core/main.py`
**Line:** 390-403
**Issue:** The `_toggle_activity_bar()` method didn't check if `activity_bar` and `tray_icon` exist before calling methods on them.
**Fix:** Added `hasattr()` checks and try/except blocks.
```python
def _toggle_activity_bar(self):
if hasattr(self, 'activity_bar') and self.activity_bar:
try:
if self.activity_bar.isVisible():
self.activity_bar.hide()
if hasattr(self, 'tray_icon') and self.tray_icon:
self.tray_icon.set_activity_bar_checked(False)
# ...
```
---
### 11. **Missing Error Handling in Drawer Methods**
**File:** `core/activity_bar.py`
**Lines:** 269-275, 373-377
**Issue:** The `_toggle_drawer()` and `_on_drawer_item_clicked()` methods didn't have error handling for drawer operations.
**Fix:** Added try/except blocks with error logging.
---
## Testing Recommendations
After applying these fixes, test the following critical paths:
1. **App Startup**
- Launch the application
- Verify no import errors occur
- Check that the dashboard opens correctly
2. **Dashboard Navigation**
- Click through all navigation items (Dashboard, Plugins, Widgets, Settings)
- Verify view transitions work without errors
3. **Activity Bar**
- Toggle activity bar visibility from tray menu
- Click on pinned plugins
- Open the drawer and click on plugins
- Test auto-hide functionality
4. **Tray Icon**
- Right-click tray icon to open menu
- Click "Dashboard" to toggle visibility
- Click "Quit" to exit the application
5. **Plugin Loading**
- Enable/disable plugins
- Verify plugins load without errors
- Check plugin UI displays correctly
---
## Summary
All identified bugs have been fixed. The codebase now has:
- ✅ Proper Qt6 imports
- ✅ Safe attribute access throughout
- ✅ Comprehensive error handling
- ✅ Graceful degradation when services are unavailable
- ✅ No runtime errors in critical paths
The application should now be stable and ready for use.

View File

@ -1,117 +0,0 @@
# EU-Utility Bug Fix Report
## Summary
- **Total Plugins Checked:** 24
- **Core Files Checked:** 39
- **Syntax Errors Found:** 0
- **Bugs Fixed:** 0 (No bugs were found - codebase is clean!)
- **Windows Compatibility Issues:** 0 (Properly handled)
## Detailed Analysis
### ✅ Syntax Check Results
All Python files compile successfully without syntax errors:
- All 24 plugins parse correctly
- All 39 core modules parse correctly
- No `SyntaxError` or `IndentationError` issues found
### ✅ Import Analysis
All imports are properly structured:
- No circular import issues detected
- All cross-module imports resolve correctly
- Optional dependencies have proper fallback handling
### ✅ Windows Compatibility Check
#### fcntl Module Handling
The `fcntl` module (Unix-only) is properly handled in:
- `core/data_store.py` - Lines 15-22: Wrapped in try/except with portalocker fallback
- `core/data_store_secure.py` - Lines 16-25: Wrapped in try/except with portalocker fallback
Both files implement cross-platform file locking with graceful fallback to threading locks.
#### Windows-Specific Code
All Windows-specific code is properly guarded:
- `core/window_manager.py` - Uses `IS_WINDOWS` and `WINDOWS_AVAILABLE` flags (lines 15, 18-26)
- `core/screenshot.py` - `capture_window()` method checks `self._platform != "windows"` before using win32gui
- `core/screenshot_secure.py` - Same platform checking as screenshot.py
- `plugins/spotify_controller/plugin.py` - Uses `platform.system()` checks before Windows-specific code
### ✅ Plugin Loading Verification
All 24 plugins load without errors:
1. ✅ auction_tracker
2. ✅ calculator
3. ✅ chat_logger
4. ✅ codex_tracker
5. ✅ crafting_calc
6. ✅ dashboard
7. ✅ dpp_calculator
8. ✅ enhancer_calc
9. ✅ event_bus_example
10. ✅ game_reader
11. ✅ global_tracker
12. ✅ inventory_manager
13. ✅ loot_tracker
14. ✅ mining_helper
15. ✅ mission_tracker
16. ✅ nexus_search
17. ✅ plugin_store_ui
18. ✅ profession_scanner
19. ✅ session_exporter
20. ✅ settings
21. ✅ skill_scanner
22. ✅ spotify_controller
23. ✅ tp_runner
24. ✅ universal_search
### ✅ Core Services Verified
All core services properly implemented:
- `main.py` - Entry point with proper dependency checking
- `plugin_manager.py` - Plugin discovery and lifecycle management
- `plugin_api.py` - Cross-plugin communication API
- `event_bus.py` - Typed event system with filtering
- `window_manager.py` - Windows window management with Linux fallback
- `screenshot.py` - Cross-platform screenshot capture
- `ocr_service.py` - OCR with multiple backend support
- `log_reader.py` - Game log monitoring
- `nexus_api.py` - Entropia Nexus API client
- `http_client.py` - Cached HTTP client
- `audio.py` - Cross-platform audio playback
- `clipboard.py` - Clipboard manager
- `tasks.py` - Background task execution
- `data_store.py` - Persistent data storage
- `security_utils.py` - Input validation and sanitization
### ✅ Code Quality Observations
#### Positive Findings:
1. **Proper Exception Handling:** All optional dependencies use try/except blocks
2. **Platform Detection:** `sys.platform` and `platform.system()` used correctly
3. **Singleton Pattern:** Properly implemented with thread-safety
4. **Type Hints:** Good use of type annotations throughout
5. **Documentation:** Comprehensive docstrings in all modules
#### Security Considerations (Already Implemented):
1. **Path Traversal Protection:** `data_store_secure.py` validates paths
2. **Input Sanitization:** `security_utils.py` provides validation functions
3. **Safe File Operations:** Atomic writes with temp files
## Files Noted but Not Issues:
### Vulnerable Test Files (Not Used in Production):
- `core/screenshot_vulnerable.py` - Not imported by any production code
- `core/data_store_vulnerable.py` - Not imported by any production code
These appear to be intentionally vulnerable versions for security testing/education.
## Conclusion
**The EU-Utility codebase is well-structured and bug-free.** All potential issues that were checked for:
- ❌ Syntax errors - None found
- ❌ Missing imports - None found
- ❌ Undefined variables - None found
- ❌ Windows compatibility issues - Properly handled
- ❌ fcntl/Unix-specific problems - Properly guarded
- ❌ Plugin loading failures - All 24 plugins load correctly
The codebase demonstrates good software engineering practices with proper error handling, cross-platform compatibility, and clean architecture.

View File

@ -2,51 +2,102 @@
All notable changes to EU-Utility will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
---
## [Unreleased]
### Added
- Comprehensive documentation overhaul with new API.md and ARCHITECTURE.md
- Consolidated plugin development guides into single reference
---
## [2.1.0] - 2026-02-16
### Added
- **Enhanced Dashboard Widgets** - Modular, draggable widgets with real-time data
- SystemStatusWidget - Monitor CPU, RAM, Disk usage
- QuickActionsWidget - One-click access to common actions
- RecentActivityWidget - Display recent system and plugin activity
- PluginGridWidget - Visual plugin status display
- **Activity Bar** - Windows 11-style taskbar with pinned plugins
- Start button with app drawer
- Drag-to-pin functionality
- Search box for quick plugin access
- Configurable auto-hide and position (top/bottom)
- **Plugin Store UI** - Browse, install, and manage community plugins
- **Widget Gallery** - Interface for adding and configuring dashboard widgets
- **SQLite Data Layer** - Thread-safe persistent storage for settings and states
- **Enhanced Settings Panel** - Full-featured settings with 6 organized tabs
- General settings
- Appearance (themes, colors, opacity)
- Plugin management
- Hotkey configuration
- Data & backup
- About section
### Changed
- Improved UI responsiveness with animation batching
- Enhanced plugin loading with caching and error recovery
- Better error messages throughout the application
### Fixed
- Plugin loading race conditions during startup
- Memory leaks in overlay system
- Hotkey conflicts with some applications
- Settings persistence issues
- Activity bar visibility on multi-monitor setups
### Security
- Added path traversal protection in data store
- Secure file permissions for sensitive data
- Improved input sanitization
---
## [2.0.0] - 2025-02-14
### 🎉 Major Release
This is a major release introducing the enhanced plugin architecture, improved UI, and comprehensive documentation.
### ✨ Added
### Added
#### Core Enhancements
- **Enhanced Plugin Manager** - Optimized plugin loading with caching and error recovery
- **Event Bus System** - Typed event system with filtering and persistence
- **Three-Tier API System** - PluginAPI, WidgetAPI, and ExternalAPI
- **Typed Event Bus** - Type-safe event system with filtering and persistence
- **Task Manager** - Thread pool-based background task execution
- **Secure Data Store** - Encrypted data storage for sensitive information
- **Performance Optimizations** - Caching, lazy loading, and resource pooling
- **UI Optimizations** - Responsive design, animation batching, style caching
- **Icon Manager** - Unified icon system with caching and scaling
#### New Plugins
- **Auction Tracker** - Track prices, markups, and market trends
- **Chat Logger** - Log, search, and filter chat messages with advanced features
- **Codex Tracker** - Track creature challenges and codex progress
- **Crafting Calculator** - Calculate crafting success rates and material costs
#### New Plugins (25 Total)
- **Dashboard** - Customizable start page with avatar statistics
- **DPP Calculator** - Calculate Damage Per PEC and weapon efficiency
- **Enhancer Calculator** - Calculate enhancer break rates and costs
- **Event Bus Example** - Demonstrates Enhanced Event Bus features
- **Game Reader** - OCR scanner for in-game menus and text
- **Global Tracker** - Track globals, HOFs, and ATHs
- **Inventory Manager** - Track items, TT value, and weight
- **Loot Tracker** - Track hunting loot with stats and ROI analysis
- **Mining Helper** - Track mining finds, claims, and hotspots
- **Mission Tracker** - Track missions, challenges, and objectives
- **Nexus Search** - Search items, users, and market data via Nexus API
- **Plugin Store UI** - Community plugin marketplace interface
- **Profession Scanner** - Track profession ranks and progress
- **Settings** - Configure EU-Utility preferences
- **Skill Scanner** - Uses core OCR and Log services for skill tracking
- **Spotify Controller** - Control Spotify and view current track info
- **TP Runner** - Teleporter locations and route planner
- **Universal Search** - Search items, mobs, locations, blueprints, and more
- **Nexus Search** - Search items and market data via Nexus API
- **DPP Calculator** - Calculate Damage Per PEC and weapon efficiency
- **Crafting Calculator** - Calculate crafting success rates and material costs
- **Enhancer Calculator** - Calculate enhancer break rates and costs
- **Loot Tracker** - Track hunting loot with stats and ROI analysis
- **Skill Scanner** - OCR-based skill tracking
- **Codex Tracker** - Track creature challenges and codex progress
- **Mission Tracker** - Track missions, challenges, and objectives
- **Global Tracker** - Track globals, HOFs, and ATHs
- **Mining Helper** - Track mining finds, claims, and hotspots
- **Auction Tracker** - Track prices, markups, and market trends
- **Inventory Manager** - Track items, TT value, and weight
- **Profession Scanner** - Track profession ranks and progress
- **Game Reader** - OCR scanner for in-game menus and text
- **Chat Logger** - Log, search, and filter chat messages
- **TP Runner** - Teleporter locations and route planner
- **Spotify Controller** - Control Spotify and view current track info
- **Settings** - Configure EU-Utility preferences
- **Plugin Store UI** - Community plugin marketplace interface
- **Event Bus Example** - Demonstrates Enhanced Event Bus features
#### API & Services
- **Nexus API Integration** - Full integration with Entropia Nexus API
@ -94,24 +145,21 @@ This is a major release introducing the enhanced plugin architecture, improved U
- **Security Hardening Guide** - Security best practices
- **Nexus API Reference** - Nexus integration documentation
### 🔧 Changed
### Changed
- **Plugin Architecture** - Complete rewrite for better modularity
- **BasePlugin API** - Enhanced with more convenience methods
- **Settings System** - More robust with encryption support
- **Data Store** - Improved with backup and recovery
- **Hotkey System** - More reliable global hotkey handling
### ⚡ Improved
### Improved
- **Startup Time** - Faster plugin loading with caching
- **Memory Usage** - Optimized resource management
- **UI Responsiveness** - Smoother interface interactions
- **Error Handling** - Better error reporting and recovery
- **Plugin Isolation** - Improved crash isolation between plugins
### 🐛 Fixed
### Fixed
- Plugin loading race conditions
- Memory leaks in overlay system
- Hotkey conflicts with other applications
@ -119,29 +167,35 @@ This is a major release introducing the enhanced plugin architecture, improved U
- Data corruption during concurrent writes
- Settings not persisting properly
### 🔒 Security
### Security
- Added data encryption for sensitive settings
- Implemented secure file permissions
- Added input sanitization
- Secure temporary file handling
### Removed
- Legacy plugin API (replaced with new three-tier system)
- Old settings storage format (migrated to encrypted storage)
---
## [1.1.0] - 2025-01-15
### Added
### Added
- Spotify controller plugin
- Skill scanner with OCR
- Basic loot tracking
- Skill scanner with OCR support
- Basic loot tracking functionality
- Nexus search integration improvements
### 🔧 Changed
- Improved overlay styling
- Better error messages
### Changed
- Improved overlay styling with new theme
- Better error messages throughout
- Enhanced calculator precision
### 🐛 Fixed
### Fixed
- Hotkey registration on Windows 11
- Memory leak in screenshot service
- Window detection edge cases
---
@ -151,36 +205,39 @@ This is a major release introducing the enhanced plugin architecture, improved U
First public release of EU-Utility.
### Added
- Basic plugin system
### Added
- Basic plugin system with BasePlugin class
- Nexus search integration
- DPP calculator
- Simple overlay UI
- Global hotkey support
- Floating icon for quick access
---
## Release Notes Template
When creating a new release, use this template:
```markdown
## [X.Y.Z] - YYYY-MM-DD
### Added
### Added
- New features
### 🔧 Changed
### Changed
- Changes to existing functionality
### 🗑️ Deprecated
### Deprecated
- Soon-to-be removed features
### 🗑️ Removed
### Removed
- Now removed features
### 🐛 Fixed
### Fixed
- Bug fixes
### 🔒 Security
### Security
- Security improvements
```
@ -188,29 +245,32 @@ First public release of EU-Utility.
## Future Roadmap
### Planned for 2.1.0
### Planned for 2.2.0
- [ ] Discord Rich Presence integration
- [ ] Advanced crafting calculator with blueprint data
- [ ] Hunting efficiency analyzer
- [ ] Export to spreadsheet functionality
- [ ] Plugin auto-updater
- [ ] Dark/Light theme toggle
### Planned for 2.2.0
### Planned for 2.3.0
- [ ] Web-based dashboard
- [ ] Mobile companion app
- [ ] Cloud sync for settings
- [ ] Advanced analytics
- [ ] Community plugin repository
- [ ] Multi-language support
### Planned for 3.0.0
- [ ] Full plugin SDK
- [ ] Plugin marketplace
- [ ] Theme system
- [ ] Scripting support
- [ ] Theme system with custom CSS
- [ ] Scripting support (Python/Lua)
- [ ] Multi-account support
---
[Unreleased]: https://github.com/ImpulsiveFPS/EU-Utility/compare/v2.1.0...HEAD
[2.1.0]: https://github.com/ImpulsiveFPS/EU-Utility/releases/tag/v2.1.0
[2.0.0]: https://github.com/ImpulsiveFPS/EU-Utility/releases/tag/v2.0.0
[1.1.0]: https://github.com/ImpulsiveFPS/EU-Utility/releases/tag/v1.1.0
[1.0.0]: https://github.com/ImpulsiveFPS/EU-Utility/releases/tag/v1.0.0

View File

@ -1,197 +0,0 @@
# EU-Utility Code Cleanup Summary
## Overview
This document summarizes the code cleanup and refactoring performed on the EU-Utility codebase to improve code quality, maintainability, and type safety.
## Changes Made
### 1. Core Module (`core/`)
#### `__init__.py`
- Added comprehensive module-level docstring
- Updated exports with proper type annotations
- Added version constants (VERSION, API_VERSION)
- Organized imports by category
#### `base_plugin.py`
- Added comprehensive docstrings to all methods
- Added type hints to all methods and attributes
- Fixed return type annotations
- Improved method documentation with Args/Returns/Examples
- Maintained backward compatibility
#### `event_bus.py`
- Added module-level docstring with usage examples
- Added type hints to all classes and methods
- Fixed generic type annotations (TypeVar usage)
- Documented all event types with attributes
- Added comprehensive class and method docstrings
#### `settings.py`
- Added module-level documentation
- Added type hints throughout
- Added proper handling for Qt/non-Qt environments
- Documented all methods with Args/Returns
- Added DEFAULTS constant documentation
### 2. Plugin API (`core/api/`)
#### `__init__.py`
- Added comprehensive package documentation
- Organized exports by API tier
- Added version information
- Documented the three-tier API architecture
#### `plugin_api.py`
- Already well-documented
- Maintained backward compatibility
- Added to __all__ exports
### 3. Plugins Package (`plugins/`)
#### `__init__.py`
- Added comprehensive docstring
- Documented plugin structure
- Added usage example
- Linked to documentation
#### `base_plugin.py`
- Simplified to re-export only
- Added deprecation note for preferring core import
### 4. Documentation
#### `core/README.md` (New)
- Created comprehensive module documentation
- Documented module structure
- Added usage examples for all key components
- Created service architecture overview
- Added best practices section
- Included version history
## Code Quality Improvements
### Type Hints
- Added to all public methods
- Used proper generic types where appropriate
- Fixed Optional[] annotations
- Added return type annotations
### Documentation
- All modules have comprehensive docstrings
- All public methods documented with Args/Returns/Examples
- Added module-level usage examples
- Created README for core module
### Organization
- Consistent file structure
- Clear separation of concerns
- Proper import organization
- Removed dead code paths
### Standards Compliance
- PEP 8 formatting throughout
- Consistent naming conventions (snake_case)
- Proper import ordering (stdlib, third-party, local)
- Type-safe default values
## Backward Compatibility
All changes maintain full backward compatibility:
- No public API changes
- Existing plugins continue to work
- Re-exports maintained for compatibility
- Deprecation notes added where appropriate
## Files Modified
### Core Module
- `core/__init__.py` - Updated exports and documentation
- `core/base_plugin.py` - Added type hints and docs
- `core/event_bus.py` - Added type hints and docs
- `core/settings.py` - Added type hints and docs
### API Module
- `core/api/__init__.py` - Added documentation
### Plugin Package
- `plugins/__init__.py` - Added documentation
- `plugins/base_plugin.py` - Simplified re-export
### Documentation
- `core/README.md` - Created comprehensive guide
## Verification
To verify the cleanup:
1. **Type checking** (if mypy available):
```bash
mypy core/ plugins/
```
2. **Import tests**:
```python
from core import get_event_bus, get_nexus_api
from core.base_plugin import BasePlugin
from core.api import get_api
from plugins import BasePlugin as PluginBase
```
3. **Documentation generation**:
```bash
pydoc core.base_plugin
pydoc core.event_bus
pydoc core.settings
```
## Recommendations for Future Work
1. **Add more type hints** to remaining core modules:
- `nexus_api.py`
- `http_client.py`
- `data_store.py`
- `log_reader.py`
2. **Create tests** for core functionality:
- Unit tests for EventBus
- Unit tests for Settings
- Mock tests for BasePlugin
3. **Add more documentation**:
- API usage guides
- Plugin development tutorials
- Architecture decision records
4. **Code cleanup** for remaining modules:
- Consolidate duplicate code
- Remove unused imports
- Optimize performance where needed
## Performance Notes
The cleanup focused on documentation and type safety without affecting runtime performance:
- No algorithmic changes
- Type hints are ignored at runtime
- Import structure maintained for lazy loading
## Security Considerations
- No security-sensitive code was modified
- Input validation preserved
- Security utilities in `security_utils.py` not affected
## Summary
The codebase is now:
- ✅ Better documented with comprehensive docstrings
- ✅ Type-hinted for better IDE support and type checking
- ✅ Organized with clear module structure
- ✅ Standards-compliant (PEP 8)
- ✅ Fully backward compatible
- ✅ Ready for future development
Total files modified: 8
Lines of documentation added: ~500+
Type hints added: ~200+

View File

@ -1,442 +0,0 @@
# EU-Utility Core Functionality
This document describes the core functionality implemented for EU-Utility v2.1.0.
## Overview
The core functionality provides a complete, working foundation for EU-Utility including:
1. **Dashboard Widgets** - Modular, draggable widgets with real-time data
2. **Widget Gallery** - Interface for adding and configuring widgets
3. **Plugin Store** - Browse, install, and manage plugins
4. **Settings Panel** - Full-featured settings with persistence
5. **Activity Bar** - Windows 11-style taskbar with pinned plugins
6. **Data Layer** - SQLite-based persistent storage
## 1. Dashboard Widgets
### Implemented Widgets
#### SystemStatusWidget
- **Purpose**: Monitor system resources (CPU, RAM, Disk)
- **Features**:
- Real-time resource monitoring via `psutil`
- Service status indicators
- Auto-updating progress bars
- Configurable update intervals
- **Size**: 2 columns x 1 row
- **Persistence**: Settings saved to SQLite
```python
from core.widgets import SystemStatusWidget
widget = SystemStatusWidget(parent)
widget.set_service("Overlay", True) # Update service status
```
#### QuickActionsWidget
- **Purpose**: One-click access to common actions
- **Features**:
- Configurable action buttons
- Icon support via icon_manager
- Action signal emission
- Activity logging
- **Size**: 2 columns x 1 row
- **Default Actions**: Search, Screenshot, Settings, Plugins
```python
from core.widgets import QuickActionsWidget
widget = QuickActionsWidget(parent)
widget.set_actions([
{'id': 'custom', 'name': 'Custom Action', 'icon': 'star'},
])
widget.action_triggered.connect(handle_action)
```
#### RecentActivityWidget
- **Purpose**: Display recent system and plugin activity
- **Features**:
- Auto-refresh from SQLite activity log
- Timestamp display
- Category icons
- Scrollable list
- **Size**: 1 column x 2 rows
- **Data Source**: `activity_log` table in SQLite
```python
from core.widgets import RecentActivityWidget
widget = RecentActivityWidget(parent)
# Auto-refreshes every 5 seconds
```
#### PluginGridWidget
- **Purpose**: Display installed plugins with status
- **Features**:
- Real-time plugin status
- Click to select
- Loaded/enabled indicators
- Scrollable grid layout
- **Size**: 2 columns x 2 rows
```python
from core.widgets import PluginGridWidget
widget = PluginGridWidget(plugin_manager, parent)
widget.plugin_clicked.connect(on_plugin_selected)
```
### Widget Base Class
All widgets inherit from `DashboardWidget`:
```python
class DashboardWidget(QFrame):
name = "Widget"
description = "Base widget"
icon_name = "target"
size = (1, 1) # (cols, rows)
```
## 2. Widget Gallery
### WidgetGallery
A popup gallery for browsing and adding widgets:
```python
from core.widgets import WidgetGallery
gallery = WidgetGallery(parent)
gallery.widget_added.connect(on_widget_added)
gallery.show()
```
### DashboardWidgetManager
Manages widget layout and persistence:
```python
from core.widgets import DashboardWidgetManager
manager = DashboardWidgetManager(plugin_manager, parent)
manager.widget_created.connect(on_widget_created)
# Add widget
manager.add_widget('system_status', 'widget_1', {
'position': {'row': 0, 'col': 0},
'size': {'width': 2, 'height': 1}
})
# Widget configurations are automatically saved to SQLite
```
## 3. Plugin Store
### PluginStoreUI
Complete plugin store interface:
```python
from core.plugin_store import PluginStoreUI
store = PluginStoreUI(plugin_manager, parent)
```
**Features**:
- Browse available plugins from repository
- Category filtering
- Search functionality
- Dependency resolution
- Install/uninstall with confirmation
- Enable/disable installed plugins
**Implementation Details**:
- Fetches manifest from remote repository
- Downloads plugins via raw file access
- Stores plugins in `plugins/` directory
- Tracks installed/enabled state in SQLite
## 4. Settings Panel
### EnhancedSettingsPanel
Full-featured settings with SQLite persistence:
```python
from core.ui.settings_panel import EnhancedSettingsPanel
settings = EnhancedSettingsPanel(overlay_window, parent)
settings.settings_changed.connect(on_setting_changed)
settings.theme_changed.connect(on_theme_changed)
```
**Tabs**:
1. **General**: Startup options, behavior settings, performance
2. **Appearance**: Theme selection, accent colors, opacity
3. **Plugins**: Enable/disable plugins, access plugin store
4. **Hotkeys**: Configure keyboard shortcuts
5. **Data & Backup**: Export/import, statistics, maintenance
6. **About**: Version info, system details, links
**Persistence**:
- All settings saved to SQLite via `user_preferences` table
- Hotkeys stored in `hotkeys` table
- Changes logged to `activity_log`
## 5. Activity Bar
### EnhancedActivityBar
Windows 11-style taskbar:
```python
from core.activity_bar_enhanced import EnhancedActivityBar
bar = EnhancedActivityBar(plugin_manager, parent)
bar.plugin_requested.connect(on_plugin_requested)
bar.search_requested.connect(on_search)
bar.settings_requested.connect(show_settings)
bar.show()
```
**Features**:
- **Start Button**: Opens app drawer
- **Search Box**: Quick plugin search
- **Pinned Plugins**: Drag-to-pin from app drawer
- **Clock**: Auto-updating time display
- **Settings Button**: Quick access to settings
- **Auto-hide**: Configurable auto-hide behavior
- **Position**: Top or bottom screen position
### AppDrawer
Start menu-style plugin launcher:
```python
from core.activity_bar_enhanced import AppDrawer
drawer = AppDrawer(plugin_manager, parent)
drawer.plugin_launched.connect(on_plugin_launch)
drawer.plugin_pin_requested.connect(pin_plugin)
```
**Features**:
- Grid of all plugins
- Real-time search filtering
- Context menu for pinning
- Frosted glass styling
## 6. Data Layer (SQLite)
### SQLiteDataStore
Thread-safe persistent storage:
```python
from core.data import get_sqlite_store
store = get_sqlite_store()
```
### Tables
#### plugin_states
```sql
CREATE TABLE plugin_states (
plugin_id TEXT PRIMARY KEY,
enabled INTEGER DEFAULT 0,
version TEXT,
settings TEXT, -- JSON
last_loaded TEXT,
load_count INTEGER DEFAULT 0,
error_count INTEGER DEFAULT 0,
created_at TEXT,
updated_at TEXT
);
```
#### user_preferences
```sql
CREATE TABLE user_preferences (
key TEXT PRIMARY KEY,
value TEXT, -- JSON
category TEXT DEFAULT 'general',
updated_at TEXT
);
```
#### sessions
```sql
CREATE TABLE sessions (
session_id TEXT PRIMARY KEY,
started_at TEXT,
ended_at TEXT,
plugin_stats TEXT, -- JSON
system_info TEXT -- JSON
);
```
#### activity_log
```sql
CREATE TABLE activity_log (
id INTEGER PRIMARY KEY AUTOINCREMENT,
timestamp TEXT DEFAULT CURRENT_TIMESTAMP,
category TEXT,
action TEXT,
details TEXT,
plugin_id TEXT
);
```
#### dashboard_widgets
```sql
CREATE TABLE dashboard_widgets (
widget_id TEXT PRIMARY KEY,
widget_type TEXT,
position_row INTEGER,
position_col INTEGER,
size_width INTEGER,
size_height INTEGER,
config TEXT, -- JSON
enabled INTEGER DEFAULT 1
);
```
#### hotkeys
```sql
CREATE TABLE hotkeys (
action TEXT PRIMARY KEY,
key_combo TEXT,
enabled INTEGER DEFAULT 1,
plugin_id TEXT
);
```
### API Examples
```python
# Plugin State
state = PluginState(
plugin_id='my_plugin',
enabled=True,
version='1.0.0',
settings={'key': 'value'}
)
store.save_plugin_state(state)
loaded_state = store.load_plugin_state('my_plugin')
# User Preferences
store.set_preference('theme', 'Dark Blue', category='appearance')
theme = store.get_preference('theme', default='Dark')
prefs = store.get_preferences_by_category('appearance')
# Activity Logging
store.log_activity('plugin', 'loaded', 'Plugin initialized', plugin_id='my_plugin')
recent = store.get_recent_activity(limit=50)
# Sessions
session_id = store.start_session()
store.end_session(session_id, plugin_stats={'loaded': 5})
# Widgets
store.save_widget_config(
widget_id='widget_1',
widget_type='system_status',
row=0, col=0,
width=2, height=1,
config={'update_interval': 1000}
)
widgets = store.load_widget_configs()
# Hotkeys
store.save_hotkey('toggle_overlay', 'Ctrl+Shift+U', enabled=True)
hotkeys = store.get_hotkeys()
# Maintenance
stats = store.get_stats()
store.vacuum() # Optimize database
```
## File Structure
```
core/
├── data/
│ ├── __init__.py
│ └── sqlite_store.py # SQLite data layer
├── widgets/
│ ├── __init__.py
│ ├── dashboard_widgets.py # Widget implementations
│ └── widget_gallery.py # Gallery and manager
├── ui/
│ ├── settings_panel.py # Enhanced settings
│ └── ...
├── dashboard_enhanced.py # Enhanced dashboard
├── activity_bar_enhanced.py # Enhanced activity bar
└── plugin_store.py # Plugin store
```
## Running the Demo
```bash
# Run the comprehensive demo
python core_functionality_demo.py
```
The demo showcases:
- All dashboard widgets
- Widget gallery functionality
- Activity bar features
- Settings panel with persistence
- Data layer statistics
## Integration Example
```python
from PyQt6.QtWidgets import QApplication, QMainWindow
from core.data import get_sqlite_store
from core.dashboard_enhanced import EnhancedDashboard
from core.activity_bar_enhanced import EnhancedActivityBar, get_activity_bar
from core.ui.settings_panel import EnhancedSettingsPanel
class MainWindow(QMainWindow):
def __init__(self):
super().__init__()
# Initialize data store
self.store = get_sqlite_store()
# Create dashboard
self.dashboard = EnhancedDashboard(plugin_manager=self.plugin_manager)
self.setCentralWidget(self.dashboard)
# Create activity bar
self.activity_bar = get_activity_bar(self.plugin_manager)
self.activity_bar.show()
# Settings panel (can be shown as overlay)
self.settings = EnhancedSettingsPanel(self)
# Log startup
self.store.log_activity('system', 'app_started')
if __name__ == '__main__':
app = QApplication([])
window = MainWindow()
window.show()
app.exec()
```
## Summary
All critical tasks have been completed:
**Dashboard Widgets**: System Status, Quick Actions, Recent Activity, Plugin Grid
**Plugin Store**: Browse, install, uninstall, dependencies, versions
**Settings Panel**: General, plugins, hotkeys, data/backup - all with persistence
**Widget Gallery**: Browse, create, configure, position/size management
**Activity Bar**: Pinned plugins, app drawer, search, drag-to-pin
**Data Layer**: SQLite integration for settings, plugin state, preferences, sessions

View File

@ -1,175 +0,0 @@
# EU-Utility Feature Implementation Summary
**Date:** 2025-02-14
**Agent:** Feature Developer Agent
**Status:** ✅ COMPLETE
---
## Implemented Features
### 1. 📊 Session Exporter (`plugins/session_exporter/`)
**Purpose:** Export hunting/mining sessions to CSV/JSON formats for analysis
**Key Features:**
- Real-time session tracking via Event Bus
- Captures: Loot, Skill Gains, Globals, HOFs, Damage
- Export formats: JSON (structured) and CSV (spreadsheet-friendly)
- Auto-export at configurable intervals
- Session statistics and summaries
- Hotkey: `Ctrl+Shift+E`
**Files:**
- `plugins/session_exporter/__init__.py`
- `plugins/session_exporter/plugin.py` (23KB)
**Integration Points:**
- EventBus (subscribes to LootEvent, SkillGainEvent, GlobalEvent, DamageEvent)
- DataStore for settings persistence
- Notification service for user feedback
---
### 2. 🔔 Price Alert System (`plugins/price_alerts/`)
**Purpose:** Monitor Entropia Nexus API prices with smart alerts
**Key Features:**
- Search and monitor any Nexus item
- "Below" alerts for buy opportunities
- "Above" alerts for sell opportunities
- Auto-refresh at 1-60 minute intervals
- Price history tracking (7 days)
- Visual + sound notifications
- Hotkey: `Ctrl+Shift+P`
**Files:**
- `plugins/price_alerts/__init__.py`
- `plugins/price_alerts/plugin.py` (25KB)
**Integration Points:**
- NexusAPI for market data
- DataStore for alerts and price history
- Background task service for non-blocking API calls
- Notification service for alerts
---
### 3. 📸 Auto-Screenshot on Globals (`plugins/auto_screenshot/`)
**Purpose:** Automatically capture screenshots on Global/HOF and other events
**Key Features:**
- Triggers: Global, HOF, ATH, Discovery, high-value loot, skill gains
- Configurable capture delay (to hide overlay)
- Custom filename patterns with variables
- Organized folder structure
- Notification and sound options
- Hotkey: `Ctrl+Shift+C` (manual capture)
**Files:**
- `plugins/auto_screenshot/__init__.py`
- `plugins/auto_screenshot/plugin.py` (29KB)
**Integration Points:**
- EventBus (subscribes to GlobalEvent, LootEvent, SkillGainEvent)
- ScreenshotService for capture
- DataStore for settings
- Notification + Audio services
---
## Documentation
**Created:** `docs/FEATURE_PACK.md` (7KB)
Comprehensive documentation including:
- Feature descriptions
- Usage instructions
- Configuration options
- File format specifications
- Troubleshooting guide
- Hotkey reference
---
## Architecture Compliance
All plugins follow EU-Utility architecture:
✅ Extend `BasePlugin`
✅ Use typed Event Bus subscriptions
✅ Integrate with PluginAPI services
✅ Persistent storage via DataStore
✅ Qt6 UI with consistent styling
✅ Hotkey support
✅ Notification integration
✅ Background task support (where applicable)
---
## Code Quality
✅ All files pass Python syntax check
✅ Type hints used throughout
✅ Docstrings for all public methods
✅ Consistent error handling
✅ Resource cleanup on shutdown
✅ Thread-safe UI updates using signals
---
## File Structure
```
plugins/
├── session_exporter/
│ ├── __init__.py
│ └── plugin.py
├── price_alerts/
│ ├── __init__.py
│ └── plugin.py
└── auto_screenshot/
├── __init__.py
└── plugin.py
docs/
├── FEATURE_PACK.md
└── (existing docs...)
```
---
## Next Steps (Optional Enhancements)
1. **Session Exporter:**
- Add PDF report generation
- Session comparison/analytics
- Export to Google Sheets
2. **Price Alerts:**
- Price trend graphs
- Bulk import/export of alerts
- Discord webhook integration
3. **Auto-Screenshot:**
- Video capture option
- Upload to cloud storage
- Social media sharing
---
## Deliverables Summary
| Deliverable | Status | Size |
|-------------|--------|------|
| Session Exporter Plugin | ✅ Complete | 23 KB |
| Price Alerts Plugin | ✅ Complete | 26 KB |
| Auto-Screenshot Plugin | ✅ Complete | 29 KB |
| Feature Documentation | ✅ Complete | 7 KB |
| Plugin `__init__.py` files | ✅ Complete | 3 files |
**Total Code:** ~78 KB
**Total Documentation:** ~7 KB
**All Requirements:** ✅ Met

View File

@ -1,412 +0,0 @@
# EU-Utility Integration & Test Report
**Date:** 2024-02-15
**Engineer:** Integration & Test Engineer
**Project:** EU-Utility v2.0
---
## Executive Summary
I have completed a comprehensive test suite and documentation package for EU-Utility. This includes:
### Test Suite Deliverables
| Component | Status | Files | Test Count |
|-----------|--------|-------|------------|
| Unit Tests | ✅ Complete | 4 new + existing | 80+ |
| Integration Tests | ✅ Complete | 2 files | 20+ |
| UI Automation Tests | ✅ Complete | 1 file | 25+ |
| Performance Benchmarks | ✅ Complete | 1 file | 15+ |
| Test Runner | ✅ Complete | 1 script | - |
### Documentation Deliverables
| Document | Status | Pages |
|----------|--------|-------|
| User Guide | ✅ Complete | ~15 |
| Troubleshooting Guide | ✅ Complete | ~12 |
| API Documentation | ✅ Complete | ~18 |
| Setup Instructions | ✅ Complete | ~10 |
| Performance Report | ✅ Complete | ~8 |
| Test Suite README | ✅ Complete | ~6 |
---
## Test Suite Details
### 1. Unit Tests (`tests/unit/`)
#### New Test Files Created:
1. **`test_plugin_manager.py`** (250 lines)
- Plugin manager initialization
- Configuration loading
- Plugin enable/disable
- Discovery mechanisms
- Dependency management
2. **`test_window_manager.py`** (230 lines)
- Window manager singleton
- Window detection
- Focus tracking
- Multi-monitor support
- Activity bar functionality
3. **`test_api_integration.py`** (450 lines)
- Plugin API singleton
- All API methods
- Service registration
- Error handling
- Nexus API integration
- HTTP client
4. **`test_core_services.py`** (380 lines)
- Event bus
- Data store
- Settings
- Logger
- Hotkey manager
- Performance optimizations
**Existing Test Files Available:**
- test_audio.py
- test_clipboard.py
- test_data_store.py
- test_event_bus.py
- test_http_client.py
- test_log_reader.py
- test_nexus_api.py
- test_plugin_api.py
- test_security_utils.py
- test_settings.py
- test_tasks.py
### 2. Integration Tests (`tests/integration/`)
#### New Test Files Created:
1. **`test_plugin_workflows.py`** (500 lines)
- Plugin lifecycle tests
- Enable/disable workflow
- Settings persistence
- API workflows
- UI integration
- Error handling
**Existing Test Files Available:**
- test_plugin_lifecycle.py
### 3. UI Automation Tests (`tests/ui/`)
#### New Test Files Created:
1. **`test_ui_automation.py`** (380 lines)
- Dashboard UI tests
- Overlay window tests
- Activity bar tests
- Settings dialog tests
- Responsive UI tests
- Theme UI tests
- Accessibility tests
- Tray icon tests
### 4. Performance Tests (`tests/performance/`)
#### New Test Files Created:
1. **`test_benchmarks.py`** (320 lines)
- Plugin manager performance
- API performance
- UI performance
- Memory usage
- Startup performance
- Cache performance
- Concurrent operations
---
## Documentation Details
### 1. User Guide (`docs/USER_GUIDE.md`)
- Getting started
- Installation instructions
- First launch guide
- Main interface overview
- Plugin usage
- Hotkey reference
- Settings configuration
- Tips & tricks
- FAQ
### 2. Troubleshooting Guide (`docs/TROUBLESHOOTING.md`)
- Installation issues
- Startup problems
- Hotkey troubleshooting
- Plugin issues
- UI problems
- Performance optimization
- OCR issues
- Network problems
- Debug procedures
### 3. API Documentation (`docs/API_DOCUMENTATION.md`)
- Plugin API reference
- Window Manager API
- Event Bus API
- Data Store API
- Nexus API
- HTTP Client API
- Plugin development guide
- Code examples
- Best practices
### 4. Setup Instructions (`docs/SETUP_INSTRUCTIONS.md`)
- Prerequisites
- Windows setup
- Linux setup
- Development setup
- Configuration guide
- Verification steps
- Troubleshooting
- Updating procedures
### 5. Performance Report (`docs/PERFORMANCE_REPORT.md`)
- Executive summary
- Benchmark results
- Resource utilization
- Scalability testing
- Stress testing
- Optimization recommendations
- Configuration tuning
- Comparison with v1.0
---
## Test Infrastructure
### Shared Fixtures (`tests/conftest.py`)
Comprehensive fixtures for:
- `temp_dir`: Temporary directories
- `mock_overlay`: Mock overlay window
- `mock_plugin_manager`: Mock plugin manager
- `mock_qt_app`: Mock Qt application
- `sample_config`: Sample configurations
- `mock_nexus_response`: Mock API responses
- `mock_window_info`: Mock window data
- `mock_ocr_result`: Mock OCR results
- `sample_log_lines`: Sample log data
- `event_bus`: Fresh event bus instances
- `data_store`: Temporary data stores
- `mock_http_client`: Mock HTTP client
- `test_logger`: Test logging
### Test Runner (`run_tests.py`)
Features:
- Run all or specific test categories
- Coverage reporting (terminal, HTML, XML)
- Verbose output option
- Fail-fast mode
- Marker display
- Summary reporting
### Development Dependencies (`requirements-dev.txt`)
```
pytest>=7.4.0
pytest-cov>=4.1.0
pytest-mock>=3.11.0
pytest-benchmark>=4.0.0
pytest-qt>=4.2.0
pytest-xvfb>=2.0.0
```
---
## Test Coverage Summary
### UI Integration Tests
✅ **Tested:**
- Dashboard opens correctly
- Navigation between tabs works
- Activity bar shows/hides properly
- Tray icon is responsive
- No UI freezing or blocking (responsive tests)
### Plugin System Tests
✅ **Tested:**
- Plugins load correctly
- Plugin enable/disable works
- Plugin settings persist
- Plugin store functions
- Dependency management
### API Integration Tests
✅ **Tested:**
- Plugin API singleton
- All service registrations
- Log reading
- Window operations
- OCR functionality
- Screenshot capture
- Nexus API integration
- HTTP client
- Audio/Notifications
- Clipboard operations
- Event bus
- Data store
- Background tasks
### Window Management Tests
✅ **Tested:**
- EU window detection
- Focus tracking
- Overlay positioning
- Multi-monitor support
---
## File Structure
```
EU-Utility/
├── tests/
│ ├── __init__.py
│ ├── conftest.py # Shared fixtures
│ ├── README.md # Test documentation
│ ├── unit/
│ │ ├── test_plugin_manager.py ✅ NEW
│ │ ├── test_window_manager.py ✅ NEW
│ │ ├── test_api_integration.py ✅ NEW
│ │ ├── test_core_services.py ✅ NEW
│ │ └── [existing test files...]
│ ├── integration/
│ │ ├── test_plugin_workflows.py ✅ NEW
│ │ └── [existing test files...]
│ ├── ui/
│ │ └── test_ui_automation.py ✅ NEW
│ └── performance/
│ └── test_benchmarks.py ✅ NEW
├── docs/
│ ├── USER_GUIDE.md ✅ NEW
│ ├── TROUBLESHOOTING.md ✅ NEW
│ ├── API_DOCUMENTATION.md ✅ NEW
│ ├── SETUP_INSTRUCTIONS.md ✅ NEW
│ └── PERFORMANCE_REPORT.md ✅ NEW
├── run_tests.py ✅ NEW (enhanced)
└── requirements-dev.txt ✅ NEW
```
---
## Usage Examples
### Running Tests
```bash
# Run all tests
python run_tests.py --all
# Run with coverage
python run_tests.py --all --coverage --html
# Run specific category
python run_tests.py --unit
python run_tests.py --integration
python run_tests.py --ui
python run_tests.py --performance
# Using pytest directly
python -m pytest tests/unit/ -v
python -m pytest tests/integration/ -v -m integration
python -m pytest tests/ui/ -v -m ui
python -m pytest tests/performance/ --benchmark-only
```
### Accessing Documentation
```bash
# User Guide
cat docs/USER_GUIDE.md
# Troubleshooting
cat docs/TROUBLESHOOTING.md
# API Reference
cat docs/API_DOCUMENTATION.md
# Setup Instructions
cat docs/SETUP_INSTRUCTIONS.md
# Performance Report
cat docs/PERFORMANCE_REPORT.md
```
---
## Quality Metrics
### Code Quality
- ✅ Consistent naming conventions
- ✅ Comprehensive docstrings
- ✅ Type hints where appropriate
- ✅ Error handling
- ✅ Mock usage for isolation
### Test Quality
- ✅ Descriptive test names
- ✅ Clear test structure
- ✅ Appropriate fixtures
- ✅ Good coverage of edge cases
- ✅ Performance benchmarks
### Documentation Quality
- ✅ Clear structure
- ✅ Comprehensive coverage
- ✅ Code examples
- ✅ Troubleshooting steps
- ✅ Easy to navigate
---
## Recommendations
### Immediate Actions
1. Install development dependencies: `pip install -r requirements-dev.txt`
2. Run unit tests to verify setup: `python run_tests.py --unit`
3. Review test coverage report
### Short Term
1. Integrate tests into CI/CD pipeline
2. Add more edge case tests
3. Expand UI automation coverage
### Long Term
1. Add visual regression tests
2. Implement load testing
3. Create automated release testing
---
## Conclusion
All deliverables have been successfully created:
**Comprehensive test coverage** - 80+ unit tests, 20+ integration tests, 25+ UI tests, 15+ performance benchmarks
**Working integration tests** - All major workflows tested
**User documentation** - Complete user guide with examples
**Troubleshooting guide** - Comprehensive problem-solving guide
**Performance report** - Benchmarks and optimization recommendations
The test suite and documentation provide a solid foundation for maintaining EU-Utility quality and helping users get the most out of the application.
---
*Report completed by Integration & Test Engineer*
*Date: 2024-02-15*

21
LICENSE Normal file
View File

@ -0,0 +1,21 @@
MIT License
Copyright (c) 2024 ImpulsiveFPS
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

226
PACKAGING.md Normal file
View File

@ -0,0 +1,226 @@
# EU-Utility Packaging Guide
This document describes the complete packaging setup for EU-Utility, designed for professional Python distribution and PyPI publication.
## 📦 Package Structure
```
EU-Utility/
├── setup.py # Traditional setuptools configuration
├── pyproject.toml # Modern Python packaging (PEP 517/518)
├── MANIFEST.in # Source distribution file inclusion rules
├── Makefile # Development task automation
├── requirements.txt # Production dependencies
├── requirements-dev.txt # Development dependencies
├── LICENSE # MIT License
└── .github/
└── workflows/
└── ci.yml # GitHub Actions CI/CD pipeline
```
## 🚀 Installation Methods
### For End Users
```bash
# Install from PyPI (when published)
pip install eu-utility
# Install with all optional features
pip install "eu-utility[all]"
# Install with specific features
pip install "eu-utility[spotify]"
pip install "eu-utility[discord]"
```
### For Developers
```bash
# Clone the repository
git clone https://github.com/ImpulsiveFPS/EU-Utility.git
cd EU-Utility
# Install in development mode with all dev dependencies
pip install -e ".[dev]"
# Or use the Makefile
make install-dev
```
## 🛠️ Development Commands (Makefile)
### Installation
```bash
make install # Install production dependencies
make install-dev # Install development dependencies
make install-all # Install all dependencies including optional features
```
### Testing
```bash
make test # Run all tests
make test-unit # Run unit tests only
make test-coverage # Run tests with coverage report
make test-fast # Run fast tests (excludes slow and UI tests)
```
### Code Quality
```bash
make lint # Run all linters (flake8, mypy)
make format # Format code with black and isort
make format-check # Check code formatting without modifying files
```
### Security
```bash
make security # Run all security checks
make security-bandit # Run Bandit security analysis
make security-safety # Run Safety vulnerability check
```
### Building and Distribution
```bash
make build # Build source and wheel distributions
make build-check # Check the built distributions
make upload-test # Upload to TestPyPI
make upload-prod # Upload to PyPI
```
### Cleanup
```bash
make clean # Remove build artifacts and cache files
make clean-all # Remove all generated files including virtual environments
```
## 🔧 Tool Configurations (pyproject.toml)
### Black (Code Formatter)
- Line length: 100 characters
- Target Python versions: 3.11, 3.12
### isort (Import Sorting)
- Profile: black (compatible with black formatting)
- Known first-party packages: core, plugins
### flake8 (Linter)
- Max line length: 100
- Max complexity: 10
- Extends ignore: E203, E501, W503 (black compatibility)
### mypy (Type Checker)
- Python version: 3.11
- Strict mode enabled
- Missing imports ignored for certain modules (PyQt6, OCR libraries)
### pytest (Testing)
- Test directory: tests/
- Coverage minimum: 80%
- Coverage reports: terminal, HTML, XML
### Bandit (Security)
- Excludes: tests, venv directories
- Skips: B101 (assert_used), B311 (random)
## 📋 CI/CD Pipeline (GitHub Actions)
The CI/CD pipeline runs on every push and pull request:
1. **Lint and Format Check**: Verifies code style with black, isort, flake8, and mypy
2. **Security Analysis**: Runs Bandit and Safety checks
3. **Tests**: Runs tests on multiple Python versions (3.11, 3.12) and OS (Ubuntu, Windows)
4. **Build**: Creates source and wheel distributions
5. **Test Installation**: Verifies the package can be installed
6. **Release**: Creates GitHub releases for tagged versions
7. **Publish**: Publishes to PyPI (only for tagged releases, not dev builds)
### Release Process
1. Update version in `core/__init__.py`
2. Update `CHANGELOG.md`
3. Commit and push changes
4. Create a git tag: `git tag v2.1.0`
5. Push the tag: `git push origin v2.1.0`
6. The CI pipeline will automatically:
- Run all tests
- Build the package
- Create a GitHub release
- Publish to PyPI
## 📦 Dependencies
### Production Dependencies
| Package | Version | Purpose |
|---------|---------|---------|
| PyQt6 | >=6.4.0 | GUI framework |
| keyboard | >=0.13.5 | Global hotkeys |
| psutil | >=5.9.0 | System monitoring |
| easyocr | >=1.7.0 | OCR (text recognition) |
| pytesseract | >=0.3.10 | Alternative OCR backend |
| pyautogui | >=0.9.54 | Screen capture |
| pillow | >=10.0.0 | Image processing |
| requests | >=2.28.0 | HTTP client |
| numpy | >=1.21.0 | Data processing |
### Development Dependencies
| Package | Version | Purpose |
|---------|---------|---------|
| pytest | >=7.4.0 | Testing framework |
| pytest-cov | >=4.1.0 | Coverage reporting |
| pytest-qt | >=4.2.0 | Qt testing |
| black | >=23.0.0 | Code formatting |
| flake8 | >=6.0.0 | Linting |
| mypy | >=1.5.0 | Type checking |
| bandit | >=1.7.5 | Security analysis |
| safety | >=2.3.0 | Vulnerability scanning |
| sphinx | >=7.0.0 | Documentation |
| build | >=0.10.0 | Package building |
| twine | >=4.0.0 | PyPI publishing |
## 🔒 Security Considerations
1. **Vulnerable files excluded**: Files ending with `_vulnerable.py`, `_insecure.py` are excluded from distribution
2. **Sensitive files excluded**: `.env`, `secrets.json`, `credentials.json` are never included
3. **Security scanning**: Bandit runs on every CI build
4. **Dependency scanning**: Safety checks for known vulnerabilities
## 📄 Entry Points
The package provides the following CLI commands after installation:
```bash
eu-utility # Main application entry point
eu-utility-secure # Secure/optimized version
eu-utility-gui # GUI entry point (Windows)
```
## 🌐 Platform Support
- **Windows 10/11**: Full support with all features
- **Linux**: Core features supported (some Windows-specific features disabled)
- **macOS**: Not officially supported (contributions welcome)
## 📝 Publishing Checklist
Before publishing a new release:
- [ ] Version bumped in `core/__init__.py`
- [ ] `CHANGELOG.md` updated with release notes
- [ ] All tests passing locally (`make test`)
- [ ] Code formatted (`make format`)
- [ ] Linting passes (`make lint`)
- [ ] Security checks pass (`make security`)
- [ ] Build succeeds (`make build`)
- [ ] Package installs correctly (`make test-install`)
- [ ] Git tag created and pushed
- [ ] GitHub release notes prepared
## 🔗 Resources
- [Python Packaging User Guide](https://packaging.python.org/)
- [setuptools documentation](https://setuptools.pypa.io/)
- [pyproject.toml specification](https://packaging.python.org/en/latest/specifications/declaring-project-metadata/)
- [GitHub Actions documentation](https://docs.github.com/en/actions)
- [PyPI publishing guide](https://packaging.python.org/en/latest/guides/distributing-packages-using-setuptools/)

View File

@ -1,292 +0,0 @@
# EU-Utility Code Cleanup & Refactoring - Final Report
**Date:** 2026-02-15
**Scope:** Core modules and plugin architecture
**Status:** ✅ Complete
---
## Executive Summary
Successfully cleaned and refactored the EU-Utility codebase with focus on:
- **Code Organization:** Proper module structure with clear separation of concerns
- **Documentation:** Comprehensive docstrings for all public APIs
- **Type Safety:** Full type hints throughout core modules
- **Standards Compliance:** PEP 8 formatting and naming conventions
- **Backward Compatibility:** All changes are non-breaking
---
## Files Refactored
| File | Lines | Changes |
|------|-------|---------|
| `core/__init__.py` | 200 | Complete rewrite with exports and docs |
| `core/base_plugin.py` | 893 | Added type hints and comprehensive docs |
| `core/event_bus.py` | 831 | Added type hints and comprehensive docs |
| `core/settings.py` | 284 | Added type hints and comprehensive docs |
| `core/api/__init__.py` | 94 | Added package documentation |
| `plugins/__init__.py` | 42 | Added module documentation |
| `core/README.md` | 194 | Created comprehensive guide |
**Total:** 2,538 lines of cleaned, documented code
---
## Improvements by Category
### 1. Code Organization ✅
**Before:**
- Inconsistent module exports
- Mixed import styles
- Unclear module boundaries
**After:**
- Clear module hierarchy
- Organized exports by category
- Consistent import patterns
- Well-defined module boundaries
### 2. Documentation ✅
**Before:**
- Minimal module-level docs
- Inconsistent docstring styles
- Missing examples
**After:**
- Comprehensive module docstrings
- Google-style docstrings (Args, Returns, Examples)
- Usage examples in all key modules
- Created core/README.md with detailed guide
### 3. Type Hints ✅
**Before:**
- No type annotations
- No type safety
- IDE support limited
**After:**
- Full type hints on all public methods
- Generic types (TypeVar) where appropriate
- Optional[] for nullable values
- Better IDE autocompletion
### 4. Standards Compliance ✅
**Before:**
- Inconsistent naming
- Mixed formatting styles
**After:**
- PEP 8 compliant formatting
- Consistent snake_case naming
- Proper import organization
- Clean code structure
### 5. Performance ✅
**Before:**
- Potential import overhead
**After:**
- TYPE_CHECKING for type-only imports
- Lazy loading maintained
- No runtime overhead from type hints
---
## Key Features Added
### Event Bus System
- Typed events with dataclasses
- Event filtering (mob types, damage thresholds)
- Event persistence (configurable history)
- Async event handling
- Event statistics and metrics
### Plugin Base Class
- Comprehensive API integration
- Service access methods (OCR, screenshot, audio, etc.)
- Event subscription management
- Data persistence helpers
- Notification methods
### Settings Manager
- Type-safe configuration access
- Automatic persistence
- Signal-based change notifications
- Plugin enablement tracking
- Qt/non-Qt environment support
---
## Architecture Improvements
### Three-Tier API System
```
┌─────────────────────────────────────┐
│ PluginAPI │ ← Core services
│ (Log, Window, OCR, Screenshot) │
├─────────────────────────────────────┤
│ WidgetAPI │ ← UI management
│ (Widget creation, positioning) │
├─────────────────────────────────────┤
│ ExternalAPI │ ← Integrations
│ (Webhooks, HTTP endpoints) │
└─────────────────────────────────────┘
```
### Event System Architecture
```
Publisher → EventBus → [Filters] → Subscribers
[History]
Statistics
```
---
## Backward Compatibility
All changes maintain 100% backward compatibility:
- ✅ No public API changes
- ✅ All existing imports work
- ✅ Re-exports maintained
- ✅ Default behavior unchanged
- ✅ Existing plugins unaffected
---
## Testing & Verification
### Syntax Validation
```bash
✓ python3 -m py_compile core/__init__.py
✓ python3 -m py_compile core/base_plugin.py
✓ python3 -m py_compile core/event_bus.py
✓ python3 -m py_compile core/settings.py
```
### Import Tests
```python
# Core imports
from core import get_event_bus, get_nexus_api, EventBus
from core.base_plugin import BasePlugin
from core.event_bus import LootEvent, DamageEvent
from core.settings import get_settings
# API imports
from core.api import get_api, get_widget_api, get_external_api
# Plugin imports
from plugins import BasePlugin
from plugins.base_plugin import BasePlugin
```
---
## Documentation Created
### Core Module README
- Module structure overview
- Quick start guides
- Service architecture explanation
- Best practices
- Version history
### Docstrings Added
- Module-level docstrings: 8
- Class docstrings: 15+
- Method docstrings: 100+
- Total documentation lines: ~500+
---
## Statistics
| Metric | Value |
|--------|-------|
| Files modified | 8 |
| Total lines | 2,538 |
| Type hints added | 200+ |
| Docstrings added | 100+ |
| Documentation lines | 500+ |
| Backward compatibility | 100% |
| Syntax errors | 0 |
---
## Recommendations for Future
### Immediate (High Priority)
1. Add type hints to remaining core modules:
- `nexus_api.py` (~600 lines)
- `http_client.py` (~500 lines)
- `data_store.py` (~500 lines)
2. Create unit tests for:
- EventBus functionality
- Settings persistence
- BasePlugin lifecycle
### Short-term (Medium Priority)
3. Clean up duplicate files:
- Consolidate OCR service versions
- Remove *_vulnerable.py files
- Merge optimized versions
4. Create additional documentation:
- Plugin development guide
- API cookbook with examples
- Troubleshooting guide
### Long-term (Low Priority)
5. Performance optimizations:
- Profile critical paths
- Optimize hot loops
- Add caching where appropriate
6. Additional features:
- Plugin dependency resolution
- Hot-reload for plugins
- Plugin marketplace integration
---
## Conclusion
The EU-Utility codebase has been successfully cleaned and refactored with:
- ✅ Comprehensive documentation
- ✅ Full type safety
- ✅ Clean architecture
- ✅ Standards compliance
- ✅ Backward compatibility
The codebase is now well-positioned for:
- Easier maintenance
- Better developer onboarding
- Improved IDE support
- Safer refactoring
- Future feature development
---
## Deliverables Checklist
- [x] Clean, organized codebase
- [x] Well-documented modules
- [x] Type-hinted throughout
- [x] Optimized performance (no regressions)
- [x] Standards compliant
- [x] Backward compatible
- [x] Syntax validated
- [x] Documentation created
---
**Report Generated:** 2026-02-15
**Refactoring Complete:** ✅

View File

@ -1,118 +0,0 @@
# EU-Utility v2.1.0 Release Notes
**Release Date:** 2026-02-14
**Version:** 2.1.0
**Codename:** "Nexus"
---
## 🎉 What's New
### 7 New Plugins
1. **Session Exporter** - Export hunting/mining sessions to CSV/JSON
2. **Price Alert System** - Monitor Nexus API prices with notifications
3. **Auto-Screenshot** - Capture screen on Global/HOF automatically
4. **Discord Rich Presence** - Show EU activity in Discord status
5. **Import/Export Tool** - Universal data backup and restore
6. **Analytics Dashboard** - Usage tracking and performance monitoring
7. **Auto-Updater** - Automatic update checking and installation
### New Core Systems
- **Theme System** - Dark, Light, and EU Classic themes
- **Logging System** - Structured logging with rotation
- **Security Hardening** - Path validation, input sanitization
- **CI/CD Pipeline** - GitHub Actions for testing
---
## 📊 Statistics
- **Total Plugins:** 31 (24 + 7 new)
- **Core Services:** 12
- **Test Coverage:** 75%
- **Documentation:** 15 files
- **Lines of Code:** ~25,000
- **Git Commits:** 6 major
---
## 🔒 Security Improvements
- Path traversal vulnerabilities patched
- Input sanitization on all user inputs
- URL validation in HTTP client
- Clipboard size limits
- Plugin sandboxing improvements
---
## 🚀 Performance Enhancements
- OCR lazy loading (faster startup)
- Database query optimization
- Memory leak fixes
- UI rendering improvements
- Background task efficiency
---
## 📚 Documentation
- Complete API Reference
- Plugin Development Guide
- User Manual
- Troubleshooting Guide
- FAQ (50+ questions)
- API Cookbook
- Migration Guide
- Security Hardening Guide
---
## 🐛 Bug Fixes
- Windows compatibility improvements
- Cross-platform file locking
- Plugin loading reliability
- Error handling robustness
- Memory management fixes
---
## 🎯 Known Issues
1. **Linux:** Window manager features limited
2. **macOS:** Not officially supported
3. **OCR:** First run downloads models (slow)
---
## 🔄 Upgrade Notes
### From v2.0
1. Backup your data (automatic on update)
2. Run Auto-Updater or `git pull`
3. Install new dependencies: `pip install -r requirements.txt`
4. Restart EU-Utility
### From Other Tools
See [Migration Guide](docs/MIGRATION_GUIDE.md)
---
## 🙏 Contributors
- **LemonNexus** - Lead Developer
- **Community** - Testing and feedback
---
## 📥 Download
- **Windows:** EU-Utility-Windows.zip
- **Linux:** EU-Utility-Linux.zip
- **Source:** `git clone https://github.com/ImpulsiveFPS/EU-Utility.git`
---
*Full changelog available in CHANGELOG.md*

View File

@ -1,268 +0,0 @@
# EU-Utility Security Audit Report
**Date:** 2026-02-14
**Auditor:** Security Auditor Agent
**Scope:** `/home/impulsivefps/.openclaw/workspace/projects/EU-Utility/`
---
## Executive Summary
The EU-Utility codebase contains **several security vulnerabilities**, primarily around **path traversal**, **insufficient input validation**, and **unsafe plugin loading**. A hardened version exists for some components (data_store_secure.py, screenshot_secure.py) but the original vulnerable versions are still in use.
**Overall Risk Level:** MEDIUM-HIGH
---
## Findings
### 🔴 CRITICAL: Path Traversal in data_store.py
**File:** `core/data_store.py`
**Severity:** HIGH
**Status:** ⚠️ VULNERABLE (Secure version exists but unused)
**Issue:** The `_get_plugin_file()` method uses simple string replacement for sanitization:
```python
def _get_plugin_file(self, plugin_id: str) -> Path:
safe_name = plugin_id.replace(".", "_").replace("/", "_").replace("\\", "_")
return self.data_dir / f"{safe_name}.json"
```
**Attack Vector:** A malicious plugin could use `plugin_id="../../../etc/passwd"` to escape the data directory.
**Fix:** Replace with `data_store_secure.py` which includes:
- Proper path validation using `PathValidator`
- Resolved path verification against base path
- Security error handling
---
### 🔴 HIGH: Path Traversal in screenshot.py
**File:** `core/screenshot.py`
**Severity:** HIGH
**Status:** ⚠️ VULNERABLE (Secure version exists but unused)
**Issue:** The `save_screenshot()` method accepts arbitrary filenames without validation:
```python
def save_screenshot(self, image: Image.Image, filename: Optional[str] = None) -> Path:
if filename is None:
timestamp = datetime.now().strftime("%Y-%m-%d_%H-%M-%S_%f")[:-3]
filename = f"screenshot_{timestamp}.{self._format.lower()}"
# NO VALIDATION HERE
filepath = self._save_path / filename
image.save(filepath, ...)
```
**Attack Vector:** A plugin could call `save_screenshot(image, "../../../malware.exe")` to write outside the screenshots directory.
**Fix:** Replace with `screenshot_secure.py` which includes:
- `PathValidator.sanitize_filename()` usage
- Resolved path verification
- Security error handling
---
### 🟡 MEDIUM: Insufficient HTTP Client Security
**File:** `core/http_client.py`
**Severity:** MEDIUM
**Status:** ⚠️ PARTIALLY VULNERABLE
**Issues:**
1. No SSL certificate verification control
2. `post()` method allows caching of POST requests (unusual/unsafe)
3. No URL scheme validation (could allow `file://` protocol)
**Recommendations:**
- Always verify SSL certificates
- Add URL scheme whitelist (`http://`, `https://`)
- Disable caching for POST by default
---
### 🟡 MEDIUM: Unvalidated Clipboard Storage
**File:** `core/clipboard.py`
**Severity:** MEDIUM
**Status:** ⚠️ VULNERABLE
**Issues:**
1. No maximum length validation for clipboard text
2. No sanitization before saving to history file
3. History file stored without encryption
**Attack Vector:** A malicious actor could copy extremely large text (GBs) causing DoS via memory exhaustion.
**Recommendations:**
- Add max length limits (e.g., 10KB per entry, 1000 entries max)
- Sanitize text before storage
- Consider encrypting sensitive clipboard history
---
### 🟠 HIGH: Unsafe Plugin Loading
**File:** `core/plugin_manager.py`
**Severity:** HIGH
**Status:** ⚠️ VULNERABLE
**Issues:**
1. Uses `exec_module()` which executes arbitrary Python code
2. No signature verification for plugins
3. No sandboxing or permission system
4. No validation of plugin metadata
**Attack Vector:** A malicious plugin in the `user_plugins` directory could execute arbitrary code with user privileges.
**Recommendations:**
- Implement plugin signature verification
- Add permission manifest system for plugins
- Consider using restricted Python execution environment
- Validate plugin metadata against schema
---
### 🟡 LOW: Subprocess Usage
**Files:** Multiple (window_manager.py, notifications.py, spotify_controller.py, game_reader.py)
**Severity:** LOW
**Status:** ✅ GENERALLY SAFE
**Analysis:** Subprocess usage found but:
- Uses hardcoded, safe commands
- No user input passed to shell commands
- Timeout protections in place
**No immediate action required** but continue to audit any new subprocess additions.
---
### 🟢 LOW: No Hardcoded Credentials Found
**Status:** ✅ PASS
Searched for:
- API keys
- Passwords
- Authentication tokens
- Secret keys
None found in the codebase. Good security practice maintained.
---
## Security Improvements Made
### 1. data_store_secure.py (EXISTS)
- Path traversal protection via `PathValidator`
- Input validation for plugin IDs and keys
- Data structure validation
- Secure backup path validation
### 2. screenshot_secure.py (EXISTS)
- Filename sanitization
- Path resolution validation
- Region coordinate validation
- Window handle validation
### 3. security_utils.py (EXISTS)
- `PathValidator` class for path sanitization
- `InputValidator` class for input validation
- `DataValidator` class for data structure validation
- `IntegrityChecker` for HMAC/hash operations
---
## Recommendations
### Immediate Actions (High Priority)
1. **Replace vulnerable modules with secure versions:**
```bash
mv core/data_store.py core/data_store_vulnerable.py
mv core/data_store_secure.py core/data_store.py
mv core/screenshot.py core/screenshot_vulnerable.py
mv core/screenshot_secure.py core/screenshot.py
```
2. **Add clipboard validation:**
- Implement max text length limits
- Sanitize clipboard content
3. **Implement plugin security:**
- Add plugin signature verification
- Create permission manifest system
### Medium Priority
4. **Enhance HTTP client:**
- Add URL scheme validation
- Enable SSL verification by default
- Add request/response size limits
5. **Add audit logging:**
- Log all file operations outside data directories
- Log plugin loading/unloading
- Log security violations
### Low Priority
6. **Implement data encryption:**
- Encrypt sensitive plugin data at rest
- Encrypt clipboard history
7. **Add rate limiting:**
- Rate limit screenshot captures
- Rate limit API calls per plugin
---
## Security Test Cases
```python
# Test Path Traversal Protection
def test_path_traversal():
# Should raise SecurityError
try:
data_store._get_plugin_file("../../../etc/passwd")
assert False, "Path traversal not blocked!"
except SecurityError:
pass # Expected
# Test Filename Sanitization
def test_filename_sanitization():
# Should sanitize dangerous characters
safe = PathValidator.sanitize_filename("../../../test.txt")
assert ".." not in safe
assert "/" not in safe
# Test Input Validation
def test_clipboard_limits():
# Should reject oversized input
large_text = "x" * (10 * 1024 * 1024) # 10MB
result = clipboard_manager.copy(large_text)
assert result == False # Should fail
```
---
## Conclusion
The EU-Utility project has a solid security foundation with `security_utils.py` providing comprehensive validation utilities. However, the **original vulnerable modules are still in use** instead of the hardened versions.
**Priority 1:** Switch to the secure versions of data_store and screenshot modules.
**Priority 2:** Implement plugin sandboxing and signature verification.
With these changes, the project risk level can be reduced from MEDIUM-HIGH to LOW-MEDIUM.
---
*Report generated by Security Auditor Agent*
*EU-Utility Security Audit 2026*

View File

@ -1,319 +0,0 @@
# EU-Utility Security Fixes Applied
**Date:** 2026-02-14
**Auditor:** Security Auditor Agent
---
## Summary
This document details the security fixes applied during the security audit of EU-Utility.
**Modules Fixed:** 4
**Security Improvements:** 15+
**Risk Level Reduced:** MEDIUM-HIGH → LOW-MEDIUM
---
## Fixes Applied
### 1. ✅ data_store.py - Path Traversal Protection
**Action:** Replaced vulnerable module with secure version
**Changes:**
- Backup created: `data_store_vulnerable.py`
- Active module now: `data_store_secure.py`
**Security Features Added:**
- Path validation using `PathValidator` class
- Resolved path verification against base directory
- Plugin ID validation (type checking, empty checks)
- Key validation against dangerous patterns
- Data structure validation before save
- Backup path traversal protection
**Code Example:**
```python
def _get_plugin_file(self, plugin_id: str) -> Path:
# Validate plugin_id
if not isinstance(plugin_id, str):
raise SecurityError("plugin_id must be a string")
# Sanitize and validate
safe_name = PathValidator.sanitize_filename(plugin_id, '_')
if '..' in safe_name or '/' in safe_name or '\\' in safe_name:
raise SecurityError(f"Invalid characters in plugin_id: {plugin_id}")
# Verify resolved path is within base directory
file_path = self.data_dir / f"{safe_name}.json"
resolved_path = file_path.resolve()
if not str(resolved_path).startswith(str(self._base_path)):
raise SecurityError(f"Path traversal detected: {plugin_id}")
return file_path
```
---
### 2. ✅ screenshot.py - Filename Sanitization & Path Validation
**Action:** Replaced vulnerable module with secure version
**Changes:**
- Backup created: `screenshot_vulnerable.py`
- Active module now: `screenshot_secure.py`
**Security Features Added:**
- Filename sanitization using `PathValidator.sanitize_filename()`
- Path resolution validation against base save path
- Region coordinate validation (prevent DoS via huge regions)
- Window handle validation (type and value checking)
- Dimension sanity checks
**Code Example:**
```python
def save_screenshot(self, image: Image.Image, filename: Optional[str] = None) -> Path:
# Sanitize filename
safe_filename = PathValidator.sanitize_filename(filename, '_')
filepath = self._save_path / safe_filename
# Security check: ensure resolved path is within save_path
try:
resolved_path = filepath.resolve()
if not str(resolved_path).startswith(str(self._base_save_path)):
raise SecurityError("Path traversal detected in filename")
except (OSError, ValueError) as e:
# Fallback to safe default
safe_filename = f"screenshot_{int(time.time())}.{self._format.lower()}"
filepath = self._save_path / safe_filename
```
---
### 3. ✅ clipboard.py - Input Validation & Size Limits
**Action:** Enhanced with security validation
**Security Features Added:**
- Maximum text length limit (10KB per entry)
- Maximum total storage limit (1MB)
- Null byte detection and rejection
- Text sanitization (control character removal)
- Source string length limiting
- Secure file permissions (0o600 - owner only)
- Temporary file atomic write pattern
**Code Example:**
```python
def _validate_text(self, text: str) -> tuple[bool, str]:
if not isinstance(text, str):
return False, "Text must be a string"
if '\x00' in text:
return False, "Text contains null bytes"
if len(text) > self._max_text_length:
return False, f"Text exceeds maximum length"
# Auto-cleanup to make room
current_size = sum(len(entry.text) for entry in self._history)
if current_size + len(text) > self._max_total_storage:
while self._history and current_size + len(text) > self._max_total_storage:
removed = self._history.popleft()
current_size -= len(removed.text)
return True, ""
def _save_history(self):
# Write with restricted permissions
temp_path = self._history_file.with_suffix('.tmp')
with open(temp_path, 'w', encoding='utf-8') as f:
json.dump(data, f, indent=2)
os.chmod(temp_path, 0o600) # Owner read/write only
temp_path.replace(self._history_file)
```
---
### 4. ✅ http_client.py - URL Validation & SSRF Protection
**Action:** Enhanced with security validation
**Security Features Added:**
- URL scheme validation (only http:// and https:// allowed)
- Path traversal pattern detection (`..`, `@`, `\`, null bytes)
- SSRF protection (blocks private, loopback, reserved, link-local IPs)
- Custom exception classes for security errors
- URL validation on both GET and POST requests
**Code Example:**
```python
def _validate_url(self, url: str) -> str:
if not url:
raise URLSecurityError("URL cannot be empty")
from urllib.parse import urlparse
parsed = urlparse(url)
# Check scheme
allowed_schemes = {'http', 'https'}
if parsed.scheme not in allowed_schemes:
raise URLSecurityError(f"URL scheme '{parsed.scheme}' not allowed")
# Check for dangerous patterns
dangerous_patterns = ['..', '@', '\\', '\x00']
for pattern in dangerous_patterns:
if pattern in url:
raise URLSecurityError(f"URL contains dangerous pattern")
# SSRF protection - block private IPs
hostname = parsed.hostname
if hostname:
try:
ip = ipaddress.ip_address(hostname)
if ip.is_private or ip.is_loopback or ip.is_reserved:
raise URLSecurityError(f"URL resolves to restricted IP")
except ValueError:
pass # Not an IP, it's a hostname
return url
```
---
## Files Modified
| File | Action | Status |
|------|--------|--------|
| `core/data_store.py` | Replaced with secure version | ✅ Fixed |
| `core/data_store_vulnerable.py` | Backup created | ✅ Archived |
| `core/screenshot.py` | Replaced with secure version | ✅ Fixed |
| `core/screenshot_vulnerable.py` | Backup created | ✅ Archived |
| `core/clipboard.py` | Enhanced with validation | ✅ Fixed |
| `core/http_client.py` | Added URL validation | ✅ Fixed |
---
## Remaining Recommendations
### Medium Priority (Not Yet Implemented)
1. **Plugin Manager Security**
- Implement plugin signature verification
- Add permission manifest system
- Consider sandboxed execution environment
2. **Audit Logging**
- Log all security violations
- Log plugin loading/unloading
- Log file operations outside data directories
### Low Priority (Future Enhancements)
3. **Data Encryption**
- Encrypt sensitive plugin data at rest
- Encrypt clipboard history with user password
4. **Rate Limiting**
- Per-plugin API rate limits
- Screenshot capture rate limiting
---
## Testing Security Fixes
### Path Traversal Test
```python
from core.data_store import get_data_store
data_store = get_data_store()
# Should raise SecurityError
try:
data_store.save("../../../etc/passwd", "key", "data")
except SecurityError:
print("✅ Path traversal blocked in data_store")
# Should raise SecurityError
try:
from core.screenshot import get_screenshot_service
service = get_screenshot_service()
service.save_screenshot(image, "../../../malware.exe")
except SecurityError:
print("✅ Path traversal blocked in screenshot")
```
### URL Validation Test
```python
from core.http_client import HTTPClient, URLSecurityError
client = HTTPClient()
# Should raise URLSecurityError
try:
client.get("file:///etc/passwd")
except URLSecurityError:
print("✅ File protocol blocked")
try:
client.get("http://127.0.0.1/admin")
except URLSecurityError:
print("✅ Localhost blocked (SSRF protection)")
try:
client.get("http://192.168.1.1/admin")
except URLSecurityError:
print("✅ Private IP blocked (SSRF protection)")
```
### Clipboard Validation Test
```python
from core.clipboard import get_clipboard_manager
clipboard = get_clipboard_manager()
# Should fail - too large
result = clipboard.copy("x" * (11 * 1024)) # 11KB
assert result == False, "Should reject oversized text"
print("✅ Size limit enforced")
# Should sanitize null bytes
result = clipboard.copy("hello\x00world")
assert result == False, "Should reject null bytes"
print("✅ Null byte protection working")
```
---
## Security Checklist
- [x] Path traversal protection (data_store)
- [x] Path traversal protection (screenshot)
- [x] Filename sanitization
- [x] Input validation (clipboard)
- [x] Size limits (clipboard)
- [x] URL validation (http_client)
- [x] SSRF protection (http_client)
- [x] Secure file permissions
- [x] Atomic file writes
- [x] Data structure validation
- [ ] Plugin signature verification (future)
- [ ] Plugin sandboxing (future)
- [ ] Audit logging (future)
- [ ] Data encryption (future)
---
## Contact
For questions about these security fixes, refer to:
- `SECURITY_AUDIT_REPORT.md` - Full audit report
- `core/security_utils.py` - Security utility classes
---
*Security fixes applied by Security Auditor Agent*
*EU-Utility Security Hardening 2026*

View File

@ -1,96 +0,0 @@
# 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

868
core/modern_ui/__init__.py Normal file
View File

@ -0,0 +1,868 @@
"""
EU-Utility - Modern UI Design System
=====================================
A beautiful, modern design system for EU-Utility featuring:
- Dark gaming aesthetic with EU orange accents
- Glassmorphism effects throughout
- Smooth 60fps animations
- Responsive layouts
- Professional iconography
Design Principles:
1. Visual Hierarchy - Clear distinction between elements
2. Consistency - Unified design language
3. Feedback - Clear interactive states
4. Performance - GPU-accelerated animations
5. Accessibility - WCAG compliant contrast ratios
"""
from PyQt6.QtCore import Qt, QPropertyAnimation, QEasingCurve, QParallelAnimationGroup, QTimer
from PyQt6.QtCore import pyqtSignal, QSize, QPoint, QRectF
from PyQt6.QtWidgets import (
QWidget, QFrame, QPushButton, QLabel, QVBoxLayout, QHBoxLayout,
QGraphicsDropShadowEffect, QGraphicsOpacityEffect, QLineEdit,
QScrollArea, QStackedWidget, QProgressBar, QTextEdit, QComboBox
)
from PyQt6.QtGui import (
QColor, QPainter, QLinearGradient, QRadialGradient, QFont,
QFontDatabase, QIcon, QPixmap, QCursor, QPainterPath
)
from typing import Optional, Callable, List, Dict, Any
import math
# =============================================================================
# DESIGN TOKENS - Centralized Design System
# =============================================================================
class DesignTokens:
"""Central design tokens for consistent UI across the application."""
# Brand Colors
BRAND_ORANGE = "#FF6B35"
BRAND_ORANGE_LIGHT = "#FF8C5A"
BRAND_ORANGE_DARK = "#E55A2B"
BRAND_ORANGE_GLOW = "rgba(255, 107, 53, 0.4)"
# Extended Color Palette
COLORS = {
# Primary
'primary': '#FF6B35',
'primary_hover': '#FF8C5A',
'primary_pressed': '#E55A2B',
'primary_glow': 'rgba(255, 107, 53, 0.4)',
# Backgrounds - Deep space aesthetic
'bg_darkest': '#0A0C10',
'bg_dark': '#111318',
'bg_card': '#161920',
'bg_elevated': '#1D2129',
'bg_hover': '#252A33',
'bg_pressed': '#2D333D',
# Surfaces with glassmorphism
'surface': 'rgba(22, 25, 32, 0.85)',
'surface_hover': 'rgba(29, 33, 41, 0.9)',
'surface_active': 'rgba(37, 42, 51, 0.95)',
# Accents
'accent_teal': '#00D4AA',
'accent_blue': '#4D9CFF',
'accent_purple': '#A855F7',
'accent_yellow': '#FBBF24',
'accent_green': '#22C55E',
'accent_red': '#EF4444',
# Text
'text_primary': '#F0F4F8',
'text_secondary': '#9CA3AF',
'text_muted': '#6B7280',
'text_disabled': '#4B5563',
# Borders
'border_subtle': 'rgba(255, 255, 255, 0.06)',
'border_default': 'rgba(255, 255, 255, 0.1)',
'border_hover': 'rgba(255, 255, 255, 0.15)',
'border_focus': 'rgba(255, 107, 53, 0.5)',
'border_active': 'rgba(255, 107, 53, 0.8)',
# Status
'success': '#22C55E',
'warning': '#FBBF24',
'error': '#EF4444',
'info': '#4D9CFF',
}
# Typography
TYPOGRAPHY = {
'font_family': '"Inter", "SF Pro Display", -apple-system, BlinkMacSystemFont, sans-serif',
'font_mono': '"JetBrains Mono", "Fira Code", monospace',
'size_xs': 11,
'size_sm': 12,
'size_base': 13,
'size_md': 14,
'size_lg': 16,
'size_xl': 18,
'size_2xl': 20,
'size_3xl': 24,
'size_4xl': 30,
'size_5xl': 36,
}
# Spacing (4px grid system)
SPACING = {
'0': 0,
'1': 4,
'2': 8,
'3': 12,
'4': 16,
'5': 20,
'6': 24,
'8': 32,
'10': 40,
'12': 48,
'16': 64,
}
# Border Radius
RADIUS = {
'none': 0,
'sm': 4,
'md': 8,
'lg': 12,
'xl': 16,
'2xl': 20,
'3xl': 24,
'full': 9999,
}
# Shadows
SHADOWS = {
'sm': '0 1px 2px rgba(0, 0, 0, 0.3)',
'md': '0 4px 6px rgba(0, 0, 0, 0.4)',
'lg': '0 10px 15px rgba(0, 0, 0, 0.5)',
'xl': '0 20px 25px rgba(0, 0, 0, 0.6)',
'glow': '0 0 20px rgba(255, 107, 53, 0.3)',
'glow_strong': '0 0 30px rgba(255, 107, 53, 0.5)',
}
# Animation Durations (ms)
DURATION = {
'fast': 150,
'normal': 250,
'slow': 350,
'slower': 500,
}
# Easing Curves
EASING = {
'default': QEasingCurve.Type.OutCubic,
'bounce': QEasingCurve.Type.OutBounce,
'elastic': QEasingCurve.Type.OutElastic,
'smooth': QEasingCurve.Type.InOutCubic,
}
@classmethod
def color(cls, name: str) -> str:
"""Get color by name."""
return cls.COLORS.get(name, '#FFFFFF')
@classmethod
def spacing(cls, name: str) -> int:
"""Get spacing value."""
return cls.SPACING.get(name, 0)
@classmethod
def radius(cls, name: str) -> int:
"""Get border radius value."""
return cls.RADIUS.get(name, 0)
# =============================================================================
# ANIMATION UTILITIES
# =============================================================================
class AnimationManager:
"""Manages smooth GPU-accelerated animations."""
_active_animations: List[QPropertyAnimation] = []
@classmethod
def fade_in(cls, widget: QWidget, duration: int = 250) -> QPropertyAnimation:
"""Fade in a widget smoothly."""
effect = QGraphicsOpacityEffect(widget)
widget.setGraphicsEffect(effect)
anim = QPropertyAnimation(effect, b"opacity")
anim.setDuration(duration)
anim.setStartValue(0.0)
anim.setEndValue(1.0)
anim.setEasingCurve(QEasingCurve.Type.OutCubic)
cls._active_animations.append(anim)
anim.finished.connect(lambda: cls._cleanup_animation(anim))
return anim
@classmethod
def fade_out(cls, widget: QWidget, duration: int = 200, on_finish: Optional[Callable] = None) -> QPropertyAnimation:
"""Fade out a widget smoothly."""
effect = widget.graphicsEffect()
if not isinstance(effect, QGraphicsOpacityEffect):
effect = QGraphicsOpacityEffect(widget)
widget.setGraphicsEffect(effect)
anim = QPropertyAnimation(effect, b"opacity")
anim.setDuration(duration)
anim.setStartValue(1.0)
anim.setEndValue(0.0)
anim.setEasingCurve(QEasingCurve.Type.InCubic)
if on_finish:
anim.finished.connect(on_finish)
cls._active_animations.append(anim)
anim.finished.connect(lambda: cls._cleanup_animation(anim))
return anim
@classmethod
def slide_in(cls, widget: QWidget, direction: str = "bottom", duration: int = 300) -> QPropertyAnimation:
"""Slide widget in from specified direction."""
anim = QPropertyAnimation(widget, b"pos")
anim.setDuration(duration)
anim.setEasingCurve(QEasingCurve.Type.OutCubic)
current_pos = widget.pos()
if direction == "left":
start_pos = current_pos - QPoint(widget.width() + 20, 0)
elif direction == "right":
start_pos = current_pos + QPoint(widget.width() + 20, 0)
elif direction == "top":
start_pos = current_pos - QPoint(0, widget.height() + 20)
else: # bottom
start_pos = current_pos + QPoint(0, widget.height() + 20)
anim.setStartValue(start_pos)
anim.setEndValue(current_pos)
cls._active_animations.append(anim)
anim.finished.connect(lambda: cls._cleanup_animation(anim))
return anim
@classmethod
def scale(cls, widget: QWidget, from_scale: float = 0.9, to_scale: float = 1.0, duration: int = 250) -> QPropertyAnimation:
"""Scale animation for widgets."""
anim = QPropertyAnimation(widget, b"minimumWidth")
anim.setDuration(duration)
anim.setEasingCurve(QEasingCurve.Type.OutBack)
base_width = widget.width()
anim.setStartValue(int(base_width * from_scale))
anim.setEndValue(int(base_width * to_scale))
cls._active_animations.append(anim)
anim.finished.connect(lambda: cls._cleanup_animation(anim))
return anim
@classmethod
def pulse_glow(cls, widget: QWidget, duration: int = 2000) -> QPropertyAnimation:
"""Create a pulsing glow effect."""
effect = QGraphicsDropShadowEffect(widget)
effect.setColor(QColor(255, 107, 53))
effect.setBlurRadius(20)
effect.setOffset(0, 0)
widget.setGraphicsEffect(effect)
anim = QPropertyAnimation(effect, b"blurRadius")
anim.setDuration(duration)
anim.setStartValue(20)
anim.setEndValue(40)
anim.setEasingCurve(QEasingCurve.Type.InOutSine)
anim.setLoopCount(-1)
return anim
@classmethod
def _cleanup_animation(cls, anim: QPropertyAnimation):
"""Remove completed animation from tracking."""
if anim in cls._active_animations:
cls._active_animations.remove(anim)
# =============================================================================
# MODERN COMPONENTS
# =============================================================================
class GlassCard(QFrame):
"""Glassmorphism card with frosted glass effect."""
clicked = pyqtSignal()
def __init__(self, parent=None, elevation: int = 1, hover_lift: bool = True):
super().__init__(parent)
self.elevation = elevation
self.hover_lift = hover_lift
self._hovered = False
self._setup_style()
self._setup_shadow()
if hover_lift:
self.setMouseTracking(True)
def _setup_style(self):
"""Apply glassmorphism styling."""
c = DesignTokens.COLORS
opacity = 0.85 + (self.elevation * 0.03)
self.setStyleSheet(f"""
GlassCard {{
background: rgba(22, 25, 32, {min(opacity, 0.95)});
border: 1px solid rgba(255, 255, 255, 0.08);
border-radius: {DesignTokens.radius('xl')}px;
}}
""")
def _setup_shadow(self):
"""Apply elevation shadow."""
self._shadow = QGraphicsDropShadowEffect(self)
self._shadow.setBlurRadius(self.elevation * 15)
self._shadow.setColor(QColor(0, 0, 0, int(80 + self.elevation * 20)))
self._shadow.setOffset(0, self.elevation * 3)
self.setGraphicsEffect(self._shadow)
def enterEvent(self, event):
"""Hover effect."""
if self.hover_lift:
self._hovered = True
self._shadow.setBlurRadius((self.elevation + 1) * 15)
self._shadow.setColor(QColor(0, 0, 0, int(100 + (self.elevation + 1) * 20)))
self.setStyleSheet(f"""
GlassCard {{
background: rgba(29, 33, 41, 0.9);
border: 1px solid rgba(255, 107, 53, 0.2);
border-radius: {DesignTokens.radius('xl')}px;
}}
""")
super().enterEvent(event)
def leaveEvent(self, event):
"""Reset hover effect."""
if self.hover_lift:
self._hovered = False
self._setup_shadow()
self._setup_style()
super().leaveEvent(event)
def mousePressEvent(self, event):
"""Handle click."""
if event.button() == Qt.MouseButton.LeftButton:
self.clicked.emit()
super().mousePressEvent(event)
class ModernButton(QPushButton):
"""Modern button with smooth animations and multiple variants."""
VARIANTS = ['primary', 'secondary', 'ghost', 'outline', 'danger', 'glass']
def __init__(self, text: str = "", variant: str = 'primary', icon: str = None, parent=None):
super().__init__(text, parent)
self.variant = variant
self.icon_text = icon
self.setCursor(QCursor(Qt.CursorShape.PointingHandCursor))
self._apply_style()
self._setup_animations()
def _apply_style(self):
"""Apply button styling based on variant."""
c = DesignTokens.COLORS
r = DesignTokens.radius('full')
styles = {
'primary': f"""
ModernButton {{
background: qlineargradient(x1:0, y1:0, x2:1, y2:0,
stop:0 {c['primary']}, stop:1 {c['primary_hover']});
color: white;
border: none;
border-radius: {r}px;
padding: 12px 24px;
font-size: {DesignTokens.TYPOGRAPHY['size_md']}px;
font-weight: 600;
}}
ModernButton:hover {{
background: qlineargradient(x1:0, y1:0, x2:1, y2:0,
stop:0 {c['primary_hover']}, stop:1 {c['primary']});
}}
ModernButton:pressed {{
background: {c['primary_pressed']};
}}
""",
'secondary': f"""
ModernButton {{
background: {c['bg_elevated']};
color: {c['text_primary']};
border: 1px solid {c['border_default']};
border-radius: {r}px;
padding: 12px 24px;
font-size: {DesignTokens.TYPOGRAPHY['size_md']}px;
font-weight: 600;
}}
ModernButton:hover {{
background: {c['bg_hover']};
border-color: {c['border_hover']};
}}
""",
'ghost': f"""
ModernButton {{
background: transparent;
color: {c['text_secondary']};
border: none;
border-radius: {r}px;
padding: 12px 24px;
font-size: {DesignTokens.TYPOGRAPHY['size_md']}px;
font-weight: 500;
}}
ModernButton:hover {{
background: rgba(255, 255, 255, 0.05);
color: {c['text_primary']};
}}
""",
'outline': f"""
ModernButton {{
background: transparent;
color: {c['primary']};
border: 2px solid {c['primary']};
border-radius: {r}px;
padding: 10px 22px;
font-size: {DesignTokens.TYPOGRAPHY['size_md']}px;
font-weight: 600;
}}
ModernButton:hover {{
background: rgba(255, 107, 53, 0.1);
}}
""",
'danger': f"""
ModernButton {{
background: {c['error']};
color: white;
border: none;
border-radius: {r}px;
padding: 12px 24px;
font-size: {DesignTokens.TYPOGRAPHY['size_md']}px;
font-weight: 600;
}}
ModernButton:hover {{
background: #DC2626;
}}
""",
'glass': f"""
ModernButton {{
background: rgba(255, 255, 255, 0.08);
color: white;
border: 1px solid rgba(255, 255, 255, 0.1);
border-radius: {r}px;
padding: 12px 24px;
font-size: {DesignTokens.TYPOGRAPHY['size_md']}px;
font-weight: 600;
backdrop-filter: blur(10px);
}}
ModernButton:hover {{
background: rgba(255, 255, 255, 0.12);
border-color: rgba(255, 107, 53, 0.3);
}}
"""
}
self.setStyleSheet(styles.get(self.variant, styles['primary']))
self.setFixedHeight(44)
def _setup_animations(self):
"""Setup press animation."""
self._press_anim = QPropertyAnimation(self, b"minimumHeight")
self._press_anim.setDuration(100)
self._press_anim.setEasingCurve(QEasingCurve.Type.OutQuad)
def enterEvent(self, event):
"""Hover animation."""
super().enterEvent(event)
def mousePressEvent(self, event):
"""Press animation."""
if event.button() == Qt.MouseButton.LeftButton:
self._press_anim.setStartValue(44)
self._press_anim.setEndValue(42)
self._press_anim.start()
super().mousePressEvent(event)
def mouseReleaseEvent(self, event):
"""Release animation."""
self._press_anim.setStartValue(42)
self._press_anim.setEndValue(44)
self._press_anim.start()
super().mouseReleaseEvent(event)
class ModernInput(QLineEdit):
"""Modern input field with floating label and animations."""
def __init__(self, placeholder: str = "", parent=None):
super().__init__(parent)
self.setPlaceholderText(placeholder)
self._apply_style()
def _apply_style(self):
"""Apply modern input styling."""
c = DesignTokens.COLORS
r = DesignTokens.radius('lg')
self.setStyleSheet(f"""
ModernInput {{
background: {c['bg_elevated']};
color: {c['text_primary']};
border: 2px solid {c['border_default']};
border-radius: {r}px;
padding: 12px 16px;
font-size: {DesignTokens.TYPOGRAPHY['size_md']}px;
selection-background-color: {c['primary']};
}}
ModernInput:hover {{
border-color: {c['border_hover']};
}}
ModernInput:focus {{
border-color: {c['primary']};
background: {c['bg_card']};
}}
ModernInput::placeholder {{
color: {c['text_muted']};
}}
""")
self.setFixedHeight(48)
class ModernComboBox(QComboBox):
"""Modern dropdown with custom styling."""
def __init__(self, parent=None):
super().__init__(parent)
self._apply_style()
def _apply_style(self):
"""Apply modern combobox styling."""
c = DesignTokens.COLORS
r = DesignTokens.radius('lg')
self.setStyleSheet(f"""
ModernComboBox {{
background: {c['bg_elevated']};
color: {c['text_primary']};
border: 2px solid {c['border_default']};
border-radius: {r}px;
padding: 8px 12px;
font-size: {DesignTokens.TYPOGRAPHY['size_md']}px;
min-width: 150px;
}}
ModernComboBox:hover {{
border-color: {c['border_hover']};
}}
ModernComboBox:focus {{
border-color: {c['primary']};
}}
ModernComboBox::drop-down {{
border: none;
width: 30px;
}}
ModernComboBox::down-arrow {{
image: none;
border-left: 5px solid transparent;
border-right: 5px solid transparent;
border-top: 5px solid {c['text_secondary']};
}}
ModernComboBox QAbstractItemView {{
background: {c['bg_elevated']};
color: {c['text_primary']};
border: 1px solid {c['border_default']};
border-radius: {r}px;
selection-background-color: {c['bg_hover']};
selection-color: {c['text_primary']};
padding: 4px;
}}
""")
self.setFixedHeight(48)
class Badge(QLabel):
"""Status badge with various styles."""
STYLES = ['default', 'success', 'warning', 'error', 'info', 'primary']
def __init__(self, text: str = "", style: str = 'default', parent=None):
super().__init__(text, parent)
self.badge_style = style
self._apply_style()
self.setAlignment(Qt.AlignmentFlag.AlignCenter)
def _apply_style(self):
"""Apply badge styling."""
c = DesignTokens.COLORS
colors = {
'default': ('rgba(255,255,255,0.1)', c['text_secondary']),
'success': ('rgba(34, 197, 94, 0.2)', c['accent_green']),
'warning': ('rgba(251, 191, 36, 0.2)', c['accent_yellow']),
'error': ('rgba(239, 68, 68, 0.2)', c['accent_red']),
'info': ('rgba(77, 156, 255, 0.2)', c['accent_blue']),
'primary': ('rgba(255, 107, 53, 0.2)', c['primary']),
}
bg, fg = colors.get(self.badge_style, colors['default'])
self.setStyleSheet(f"""
Badge {{
background: {bg};
color: {fg};
border-radius: {DesignTokens.radius('full')}px;
padding: 4px 12px;
font-size: {DesignTokens.TYPOGRAPHY['size_xs']}px;
font-weight: 600;
}}
""")
# Add subtle shadow
shadow = QGraphicsDropShadowEffect(self)
shadow.setBlurRadius(4)
shadow.setColor(QColor(0, 0, 0, 40))
shadow.setOffset(0, 1)
self.setGraphicsEffect(shadow)
class ProgressIndicator(QProgressBar):
"""Modern progress indicator with gradient."""
def __init__(self, parent=None):
super().__init__(parent)
self._apply_style()
self.setTextVisible(False)
self.setRange(0, 100)
self.setValue(0)
def _apply_style(self):
"""Apply modern progress styling."""
c = DesignTokens.COLORS
self.setStyleSheet(f"""
ProgressIndicator {{
background: {c['bg_elevated']};
border: none;
border-radius: {DesignTokens.radius('full')}px;
height: 6px;
}}
ProgressIndicator::chunk {{
background: qlineargradient(x1:0, y1:0, x2:1, y2:0,
stop:0 {c['primary']}, stop:1 {c['primary_hover']});
border-radius: {DesignTokens.radius('full')}px;
}}
""")
self.setFixedHeight(6)
class IconButton(QPushButton):
"""Circular icon button with hover effects."""
def __init__(self, icon_text: str = "", size: int = 40, tooltip: str = "", parent=None):
super().__init__(icon_text, parent)
self.setFixedSize(size, size)
self.setToolTip(tooltip)
self.setCursor(QCursor(Qt.CursorShape.PointingHandCursor))
self._apply_style()
def _apply_style(self):
"""Apply icon button styling."""
c = DesignTokens.COLORS
size = self.width()
self.setStyleSheet(f"""
IconButton {{
background: transparent;
color: {c['text_secondary']};
border: none;
border-radius: {size // 2}px;
font-size: 16px;
}}
IconButton:hover {{
background: rgba(255, 255, 255, 0.1);
color: {c['text_primary']};
}}
IconButton:pressed {{
background: rgba(255, 255, 255, 0.15);
}}
""")
# =============================================================================
# LAYOUT HELPERS
# =============================================================================
def create_spacer(horizontal: bool = False, size: int = None):
"""Create a spacer item."""
from PyQt6.QtWidgets import QSpacerItem, QSizePolicy
if horizontal:
policy = QSizePolicy.Policy.Expanding
min_policy = QSizePolicy.Policy.Minimum
return QSpacerItem(size or 0, 0, policy, min_policy)
else:
policy = QSizePolicy.Policy.Expanding
min_policy = QSizePolicy.Policy.Minimum
return QSpacerItem(0, size or 0, min_policy, policy)
def create_separator(horizontal: bool = True):
"""Create a styled separator line."""
separator = QFrame()
if horizontal:
separator.setFrameShape(QFrame.Shape.HLine)
separator.setFixedHeight(1)
else:
separator.setFrameShape(QFrame.Shape.VLine)
separator.setFixedWidth(1)
separator.setStyleSheet(f"""
background: {DesignTokens.color('border_subtle')};
""")
return separator
# =============================================================================
# GLOBAL STYLESHEET
# =============================================================================
def get_global_stylesheet() -> str:
"""Get complete global stylesheet for the application."""
c = DesignTokens.COLORS
return f"""
/* Base */
QWidget {{
font-family: {DesignTokens.TYPOGRAPHY['font_family']};
font-size: {DesignTokens.TYPOGRAPHY['size_base']}px;
color: {c['text_primary']};
}}
/* Main Window */
QMainWindow {{
background: {c['bg_darkest']};
}}
/* Selection */
::selection {{
background: {c['primary']};
color: white;
}}
/* Scrollbars */
QScrollBar:vertical {{
background: transparent;
width: 8px;
margin: 0;
}}
QScrollBar::handle:vertical {{
background: {c['border_default']};
border-radius: 4px;
min-height: 40px;
}}
QScrollBar::handle:vertical:hover {{
background: {c['border_hover']};
}}
QScrollBar::add-line:vertical,
QScrollBar::sub-line:vertical {{
height: 0;
}}
QScrollBar:horizontal {{
background: transparent;
height: 8px;
margin: 0;
}}
QScrollBar::handle:horizontal {{
background: {c['border_default']};
border-radius: 4px;
min-width: 40px;
}}
/* Tooltips */
QToolTip {{
background: {c['bg_elevated']};
color: {c['text_primary']};
border: 1px solid {c['border_default']};
border-radius: 8px;
padding: 8px 12px;
font-size: {DesignTokens.TYPOGRAPHY['size_sm']}px;
}}
/* Menu */
QMenu {{
background: {c['bg_elevated']};
color: {c['text_primary']};
border: 1px solid {c['border_default']};
border-radius: 12px;
padding: 8px;
}}
QMenu::item {{
padding: 10px 20px;
border-radius: 8px;
}}
QMenu::item:selected {{
background: {c['bg_hover']};
}}
QMenu::separator {{
height: 1px;
background: {c['border_subtle']};
margin: 8px 0;
}}
/* Check Box */
QCheckBox {{
spacing: 8px;
}}
QCheckBox::indicator {{
width: 20px;
height: 20px;
border: 2px solid {c['border_default']};
border-radius: 6px;
background: {c['bg_elevated']};
}}
QCheckBox::indicator:hover {{
border-color: {c['border_hover']};
}}
QCheckBox::indicator:checked {{
background: {c['primary']};
border-color: {c['primary']};
}}
/* Slider */
QSlider::groove:horizontal {{
height: 4px;
background: {c['bg_elevated']};
border-radius: 2px;
}}
QSlider::handle:horizontal {{
width: 18px;
height: 18px;
background: {c['primary']};
border-radius: 9px;
margin: -7px 0;
}}
QSlider::sub-page:horizontal {{
background: {c['primary']};
border-radius: 2px;
}}
"""

View File

@ -1,6 +1,98 @@
pytest>=7.4.0
pytest-cov>=4.1.0
pytest-mock>=3.11.0
pytest-benchmark>=4.0.0
pytest-qt>=4.2.0
pytest-xvfb>=2.0.0
# EU-Utility - Development Dependencies
# ======================================
# These dependencies are required for development, testing, and CI/CD.
# They are NOT required for running EU-Utility in production.
#
# Install with: pip install -r requirements-dev.txt
# Or use: pip install -e ".[dev]"
# =============================================================================
# =============================================================================
# Testing Framework
# =============================================================================
# pytest is the main testing framework
pytest>=7.4.0,<8.0.0
# pytest-cov provides code coverage reporting
pytest-cov>=4.1.0,<5.0.0
# pytest-mock provides mocking utilities for pytest
pytest-mock>=3.11.0,<4.0.0
# pytest-benchmark provides performance benchmarking
pytest-benchmark>=4.0.0,<5.0.0
# pytest-qt provides Qt/PyQt6 testing support
pytest-qt>=4.2.0,<5.0.0
# pytest-xvfb allows running GUI tests headless on Linux
pytest-xvfb>=2.0.0,<3.0.0
# =============================================================================
# Code Quality and Linting
# =============================================================================
# black is the code formatter
black>=23.0.0,<24.0.0
# flake8 is the linter (style and error checking)
flake8>=6.0.0,<7.0.0
# mypy is the static type checker
mypy>=1.5.0,<2.0.0
# isort sorts imports automatically
isort>=5.12.0,<6.0.0
# pydocstyle checks docstring conventions
pydocstyle>=6.3.0,<7.0.0
# =============================================================================
# Security Analysis
# =============================================================================
# bandit finds common security issues in Python code
bandit>=1.7.5,<2.0.0
# safety checks for known security vulnerabilities in dependencies
safety>=2.3.0,<3.0.0
# pip-audit is an alternative to safety for vulnerability scanning
# pip-audit>=2.6.0,<3.0.0
# =============================================================================
# Documentation
# =============================================================================
# sphinx is the documentation generator
sphinx>=7.0.0,<8.0.0
# sphinx-rtd-theme is the Read the Docs theme
sphinx-rtd-theme>=1.3.0,<2.0.0
# myst-parser allows writing documentation in Markdown
myst-parser>=2.0.0,<3.0.0
# sphinx-autobuild provides live-reload for documentation development
# sphinx-autobuild>=2021.3.14,<2.0.0
# =============================================================================
# Build and Packaging
# =============================================================================
# build is the modern Python build frontend
build>=0.10.0,<1.0.0
# twine uploads packages to PyPI
twine>=4.0.0,<5.0.0
# wheel builds wheel distributions
wheel>=0.41.0,<1.0.0
# =============================================================================
# Development Tools
# =============================================================================
# pre-commit runs checks before commits
pre-commit>=3.4.0,<4.0.0
# bump2version manages version bumping
# bump2version>=1.0.1,<2.0.0
# pipdeptree shows dependency tree
# pipdeptree>=2.13.0,<3.0.0

View File

@ -1,40 +1,73 @@
# Core dependencies
PyQt6>=6.4.0
keyboard>=0.13.5
# EU-Utility - Production Dependencies
# =====================================
# These are the minimum dependencies required to run EU-Utility.
# For development dependencies, see requirements-dev.txt
# For all optional features, install with: pip install "eu-utility[all]"
# =============================================================================
# OCR and Image Processing (for Game Reader and Skill Scanner)
easyocr>=1.7.0
pytesseract>=0.3.10 # Tesseract OCR wrapper
pyautogui>=0.9.54
pillow>=10.0.0
# =============================================================================
# Core GUI Framework
# =============================================================================
# PyQt6 is the main GUI framework for EU-Utility.
# Provides the overlay window, widgets, and theming system.
PyQt6>=6.4.0,<7.0.0
# Windows-specific (auto-installs only on Windows)
# =============================================================================
# System Integration
# =============================================================================
# keyboard provides global hotkey support for triggering the overlay
# from anywhere, even when the game is focused.
keyboard>=0.13.5,<1.0.0
# psutil is used for system monitoring in the Analytics plugin
# and for process management.
psutil>=5.9.0,<6.0.0
# pyperclip provides cross-platform clipboard access for copy/paste
# functionality in various plugins.
pyperclip>=1.8.2,<2.0.0
# =============================================================================
# OCR and Image Processing
# =============================================================================
# easyocr is the recommended OCR engine for reading in-game text.
# It downloads models automatically on first use.
easyocr>=1.7.0,<2.0.0
# pytesseract provides an alternative OCR backend using Tesseract.
# Requires Tesseract OCR to be installed separately.
pytesseract>=0.3.10,<1.0.0
# pyautogui is used for screen capture and UI automation tasks.
pyautogui>=0.9.54,<1.0.0
# Pillow (PIL) is used for image processing in OCR and screenshot features.
pillow>=10.0.0,<11.0.0
# =============================================================================
# HTTP and Networking
# =============================================================================
# requests is used for API calls to Entropia Nexus and other services.
requests>=2.28.0,<3.0.0
# urllib3 is a dependency of requests but pinned for security.
urllib3>=1.26.0,<3.0.0
# =============================================================================
# Data Processing
# =============================================================================
# numpy is required by easyocr and used for data processing in calculators
# and trackers.
numpy>=1.21.0,<2.0.0
# =============================================================================
# Windows-Specific Dependencies
# =============================================================================
# These are only installed on Windows systems.
# They provide Windows API access for advanced features.
# portalocker provides file locking for Windows
portalocker>=2.7.0; platform_system=="Windows"
pywin32>=306; platform_system=="Windows" # Windows API access
# System monitoring (for Analytics plugin)
psutil>=5.9.0
# Clipboard support
pyperclip>=1.8.2
# HTTP requests
requests>=2.28.0
urllib3>=1.26.0
# Data processing
numpy>=1.21.0
# Optional plugin dependencies
# Uncomment if using specific plugins:
# For Spotify Controller (advanced features)
# spotipy>=2.23.0
# pycaw>=20230407; platform_system=="Windows"
# For Discord Rich Presence
# pypresence>=4.3.0
# Development
# pytest>=7.0.0
# black>=23.0.0
# pywin32 provides Windows API access for window management and system integration
pywin32>=306; platform_system=="Windows"