Widgets have Qt::WindowDoesNotAcceptFocus flag set so they don't
steal focus from the game. Calling activateWindow() on them
produces a warning.
Removed activateWindow() call since:
1. Widgets should not accept focus (they're overlays)
2. raise_() is sufficient to bring them to front
3. WindowDoesNotAcceptFocus is intentional for game overlay widgets
ISSUE: Clock and System Monitor widgets were created but not visible.
The widgets were being garbage collected because they weren't stored.
FIX:
1. Store widget in self._active_widgets list to prevent GC
2. Set parent=self to keep widget alive with overlay
3. Position widget at center of screen (visible location)
4. Call raise_() and activateWindow() to bring to front
5. Added debug output showing widget position
WIDGET CREATION NOW:
- Creates widget with parent
- Positions at center of screen
- Shows, raises, activates
- Stores reference in list
- Prints position for debugging
The issue was that installed plugins (calculator, clock_widget, etc.)
could not import 'plugins.base_plugin' because the plugins package
wasn't properly in Python's module path when loading via
spec_from_file_location.
FIX:
1. Added project root to sys.path so 'plugins' package is findable
2. Added _ensure_plugins_package() method to preload plugins module
3. Modified discover_plugins() to try normal import first
4. Added proper error logging with traceback for debugging
This ensures installed plugins can properly import BasePlugin
from plugins.base_plugin as expected.
NEW UI LAYOUT:
- Added tab bar at top of content area with 3 tabs:
* 🔌 Plugins - Shows plugin list from sidebar + plugin content
* 🎨 Widgets - Widget gallery to add overlay widgets
* ⚙️ Settings - All settings in one place
WIDGETS TAB FEATURES:
- Built-in widgets section with Clock and System Monitor
- Each widget has Add button to create overlay
- Plugin widgets section (placeholder for plugin-added widgets)
- Descriptions for each widget type
SETTINGS TAB FEATURES:
- Moved settings from dialog into dedicated tab
- Sub-tabs: Plugins, Plugin Store, Hotkeys, Appearance, About
- Removed Settings button from header (now in tabs)
CHANGES:
- _create_content_area() replaced with _create_content_area_with_tabs()
- Added _switch_tab() method
- Added _create_plugins_tab(), _create_widgets_tab(), _create_settings_tab()
- Added _create_widget_button() helper
- Added _add_clock_widget() and _add_system_monitor_widget()
- Removed Settings button from header bar
- Removed old _open_settings() dialog approach
The UI is now organized with clear navigation between
plugins, widgets, and settings via top tabs.
CHANGES:
1. Fixed plugin download to use raw git files instead of git clone
- Avoids Windows permission issues with .git/objects
- Downloads __init__.py and plugin.py directly
2. Added clickable dependencies button showing full dependency dialog
- Shows Core Services Required
- Shows Plugins Required
- Lists what will be auto-installed
3. Integrated Plugin Store into Settings dialog
- Added 🔌 Store tab to Settings
- Plugin Store is now built-in, not a plugin
4. Removed plugins/settings/ and plugins/plugin_store_ui/
- Settings is now built into overlay_window.py
- Users access via Settings button
5. Added _create_plugin_store_tab() method to OverlayWindow
NOTE: Pull latest EU-Utility-Plugins-Repo to get Clock Widget
The base_plugin.py was removed from plugins/ folder during cleanup
but is still needed by core/plugin_manager.py and built-in plugins.
CHANGES:
- Restored base_plugin.py from plugin repo to core/base_plugin.py
- Updated imports in core/plugin_manager.py
- Updated imports in core/plugin_manager_optimized.py
- Updated imports in plugins/settings/plugin.py
- Updated imports in plugins/plugin_store_ui/plugin.py
This fixes ModuleNotFoundError when starting EU-Utility.
BREAKING CHANGE: EU-Utility is now a framework-only application.
All user-facing features have been moved to separate plugin repository.
NEW FEATURES:
1. Plugin Store Core Module (core/plugin_store.py)
- PluginStoreWorker: Background operations (fetch, download, updates)
- PluginStoreUI: Grid-based plugin browser with cards
- PluginInfo dataclass for plugin metadata
- Fetches from remote git repository
2. Plugin Store UI Features:
- Grid layout with plugin cards (300x200px each)
- Search/filter by name, description, tags
- Category filter dropdown
- Visual indicators:
* 📦 Plugin icon (emoji-based)
* Version badge
* Status badges (✅ Enabled, 📦 Installed)
* Tag display
* 🔗 Dependency count with tooltip
- Install/Enable/Disable/Uninstall buttons
- Progress bar for operations
- Refresh and Check Updates buttons
3. Settings Integration:
- New 'Plugin Store' tab in Settings
- Moved plugin management to 'My Plugins' tab
- Plugin Store uses core module directly
4. Plugin Store UI Plugin (plugins/plugin_store_ui/):
- Standalone plugin for overlay integration
- Hotkey: Ctrl+Shift+P (configurable)
ARCHITECTURE CHANGES:
- EU-Utility Core: Framework only (PluginAPI, services, overlay)
- Plugin Repository: https://git.lemonlink.eu/impulsivefps/EU-Utility-Plugins-Repo
- Plugins installed via Store → user plugins/ directory
- Local plugins/ folder still supported for development
MANIFEST FORMAT:
USER WORKFLOW:
1. Open Settings → Plugin Store
2. Browse/search available plugins
3. Click Install (with dependency confirmation)
4. Restart EU-Utility
5. Enable plugin in 'My Plugins' tab
DEVELOPER WORKFLOW:
1. Develop plugin locally in plugins/
2. Test with core framework
3. Submit to plugin repository
4. Users install via Store
This enables limitless modularity - users only install
what they need, developers can publish independently.
BUG: OCR was reading text from Discord, EU-Utility UI, and other windows.
FIX:
1. Added find_entropia_window() - Uses win32gui + psutil on Windows to find
the game window by process name 'Entropia.exe' and window title containing
'Entropia Universe'. Returns (left, top, width, height).
2. Added capture_entropia_region() - Captures only the game window region,
falls back to full screen if window not found.
3. Added is_valid_skill_text() - Filters out non-game text patterns:
- Discord, Event Bus, Game Reader, Test, Page Scanner, HOTKEY MODE
- UI elements like 'Skill Tracker', 'Calculator', 'Nexus Search'
- Debug text like '[SkillScanner]', 'Parsed:', 'Cleared'
- Process names like 'Entropia.exe', 'Client (64 bit)', 'Arkadia'
- Lines with >10 words (skills aren't that long)
4. Added recognize_image() method to OCRService for convenience.
5. Modified SkillOCRThread.run() to:
- Capture only Entropia window
- Filter text before parsing
- Use _parse_skills_filtered() which validates each line
6. Added _parse_skills_filtered() method that:
- Splits text by lines
- Only keeps lines containing a valid rank
- Validates each line with is_valid_skill_text()
- Logs filtered lines for debugging
RESULT:
- Scanner now ONLY reads from the game window
- Invalid text (Discord, UI, debug) is filtered out
- Much cleaner skill parsing results
Note: Window title varies by location (e.g., '[Arkadia]', '[Calypso]')
but process name is always 'Entropia.exe'.
The Spotify 'Now Playing' overlay widget was appearing even when
the Spotify Controller plugin was not enabled.
CHANGES:
- Set 'spotify' overlay widget to enabled: False in default settings
- Removed Spotify from dashboard default widgets
- Both settings.py and settings_secure.py updated
The widget can still be manually enabled by users who want it:
1. Edit config/settings.json
2. Set overlay_widgets.spotify.enabled to true
3. Or use the overlay widget controls
This fixes the issue where the Spotify widget appeared even when
the plugin wasn't enabled.
The string contained C:\Program Files\Tesseract-OCR which Python
interpreted as escape sequences (\P is invalid).
Fixed by escaping backslashes: C:\Program Files\Tesseract-OCR
Plugins can now declare dependencies on other plugins.
NEW FEATURES:
- dependencies['plugins'] = ['plugin_id1', 'plugin_id2']
- Separates pip packages (auto-installed) from plugin dependencies (user enabled)
- Settings dialog shows which plugins need to be enabled first
- PluginDependencyCheck tracks installed/enabled status
EXAMPLE:
dependencies = {
'pip': ['requests'],
'plugins': ['plugins.dashboard.plugin.DashboardPlugin']
}
NEW FEATURES:
1. Plugin Dependency Declaration (BasePlugin):
- Added 'dependencies' class attribute
- Format: {'pip': ['package1', 'package2'], 'optional': {...}}
- Plugins can declare required pip packages
2. Plugin Dependency Manager (core/plugin_dependency_manager.py):
- Checks if declared dependencies are installed
- Installs missing packages via pip
- Tracks installation status
- Shows progress dialog during installation
3. Settings Dialog Integration:
- When enabling a plugin with dependencies, shows dialog
- Lists missing dependencies
- Asks user if they want to install
- Shows progress bar during installation
- Handles installation failures gracefully
4. Example: Game Reader Test plugin:
- Declares dependencies: pillow, numpy
- Optional: easyocr, pytesseract, paddleocr
- When enabled, prompts to install if missing
WORKFLOW:
1. User enables a plugin in Settings → Plugins
2. System checks if plugin has dependencies
3. If dependencies missing, shows dialog
4. User clicks Yes to install
5. Progress dialog shows installation progress
6. Plugin loads after dependencies installed
This eliminates manual pip install steps for plugins!
BUG FIXES:
1. HTTPClient '_generate_cache_key' AttributeError:
- The method definition was missing, only had docstring and body
- Added proper method signature: def _generate_cache_key(self, url, params)
2. Dashboard 'bg_dark' KeyError:
- EU_COLORS doesn't have 'bg_dark'
- Changed to 'bg_secondary' which is the correct color
3. Log Parser 'maximum recursion depth exceeded':
- read_log() was calling itself instead of parent method
- Changed to super().read_log() to call BasePlugin's method
These fixes resolve:
- Universal Search not working
- API errors
- Dashboard customize dialog crash
- Log Parser infinite recursion
CHANGES:
1. Settings plugin is no longer categorized as 'Core' plugin
- The settings menu is built into the overlay window
- Having both was redundant
- Settings plugin still exists but won't be auto-enabled
2. Removed hardcoded SpotifyWidget from core/dashboard.py
- Spotify widget was baked into core instead of being a proper plugin
- Should be in plugins/spotify_controller/ instead
- Commented out the widget addition for now
This addresses the user's feedback that:
- Settings plugin is redundant with the settings menu
- Spotify widget shouldn't be in core
BUG 1: Sidebar buttons clicked wrong plugin
- Lambda captured idx by reference, always using last value
- Fixed by using functools.partial to capture by value
BUG 2: Dashboard plugin KeyError 'border_subtle'
- Changed to 'border_default' which exists in EU_COLORS
The sidebar should now correctly switch to the clicked plugin.
BUG: TypeError: missing 1 required positional argument: 'checked'
The lambda functions were expecting a 'checked' argument that wasn't
being passed by the signals:
- QShortcut.activated doesn't pass any arguments
- SidebarButton.clicked doesn't pass any arguments
Fix: Removed 'checked' parameter from both lambda functions.
BUG: KeyError: 'border_color' when opening Settings dialog.
The color dictionary uses 'border_default' not 'border_color'.
Fixed all 5 occurrences in the file.
BUG: KeyError: 'accent_primary' when opening Settings dialog.
The color dictionary uses 'accent_orange' not 'accent_primary'.
Fixed all 10 occurrences in the file.
BUG: name 'QCheckBox' is not defined errors in plugins settings tab.
Root cause: QCheckBox was imported inside _open_settings() method but
_create_plugins_settings_tab() also uses it. The local import didn't
propagate to the helper method.
FIX:
- Added QCheckBox to top-level PyQt6 imports
- Added QTabWidget to top-level imports (also used)
- Removed redundant local imports from _open_settings()
All settings UI components now available globally in the module.
BUG: AttributeError when accessing plugin_class.name in settings tab.
The error occurred when iterating over discovered plugins and trying
to access .name, .version, or .description attributes. While all
plugins should have these attributes, there might be edge cases
where the plugin_class is not properly formed.
FIX:
- Added getattr() with defaults for safe attribute access
- Added try-except around each plugin row creation
- Added error logging for debugging
- Gracefully skip broken plugin entries instead of crashing
Changes:
- _create_plugins_settings_tab() now uses getattr() for all
plugin attributes with sensible defaults
- Each plugin row is wrapped in try-except for isolation
- Errors are logged but don't crash the settings UI
BUG: AttributeError: 'ScreenshotService' object has no attribute '_platform'
Root cause: In __init__, _get_default_save_path() was called BEFORE
_platform was initialized. The method tried to access self._platform
to determine the save path.
FIX: Moved platform detection BEFORE save path initialization in:
- core/screenshot.py
- core/screenshot_secure.py
- core/screenshot_vulnerable.py
Order changed from:
1. self._save_path = self._get_default_save_path() # FAILS - needs _platform
2. self._platform = platform.system().lower()
To:
1. self._platform = platform.system().lower()
2. self._save_path = self._get_default_save_path() # WORKS - _platform exists
This is a common Python initialization order bug where methods called
in __init__ reference attributes that haven't been set yet.
BUGS FIXED:
1. Missing dependencies in requirements.txt:
- Added pytesseract>=0.3.10 (OCR service needs it)
- Added psutil>=5.9.0 (Analytics plugin needs it)
- Added pywin32>=306 for Windows (window/screenshot needs it)
2. Type mismatch in plugin_api.py:
- get_eu_window() documented as returning Dict[str, Any]
- But actually returned WindowInfo dataclass
- Fixed: Now converts WindowInfo to dict before returning
This should resolve most import and type errors users were seeing.
All 10 core services implemented and integrated:
CORE SERVICES:
1. Nexus API Client - Search items, mobs, market data
2. Data Store - Plugin persistence with auto-backup
3. Notification System - Toast notifications with sounds
4. Window Manager - EU window detection and focus
5. HTTP Client - Cached HTTP with rate limiting
6. Event Bus - Typed events with pub/sub
7. Audio Service - Sound playback with volume control
8. Clipboard Manager - Copy/paste with history
9. Screenshot Service - Screen capture with auto-save
10. Task Manager - Thread pool with priorities
Each service:
- Singleton pattern
- Thread-safe
- PluginAPI integration
- BasePlugin convenience methods
Updated:
- core/main.py - Initialize all services
- core/plugin_api.py - Service registration
- plugins/base_plugin.py - Exposed methods