fix: Built-in Plugin Store, dependency dialog, removed settings/plugin_store plugins

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
This commit is contained in:
LemonNexus 2026-02-15 02:56:14 +00:00
parent c18a90481a
commit a81e5caf64
6 changed files with 85 additions and 1305 deletions

View File

@ -743,6 +743,10 @@ class OverlayWindow(QMainWindow):
plugins_tab = self._create_plugins_settings_tab()
tabs.addTab(plugins_tab, "Plugins")
# Plugin Store tab
store_tab = self._create_plugin_store_tab()
tabs.addTab(store_tab, "🔌 Store")
# Hotkeys tab
hotkeys_tab = self._create_hotkeys_settings_tab()
tabs.addTab(hotkeys_tab, "Hotkeys")
@ -944,6 +948,22 @@ class OverlayWindow(QMainWindow):
return tab
def _create_plugin_store_tab(self):
"""Create plugin store tab for browsing and installing plugins."""
from core.plugin_store import PluginStoreUI
if hasattr(self, 'plugin_manager') and self.plugin_manager:
return PluginStoreUI(self.plugin_manager)
# Fallback - show error
from PyQt6.QtWidgets import QWidget, QVBoxLayout, QLabel
tab = QWidget()
layout = QVBoxLayout(tab)
error = QLabel("Plugin Manager not available. Cannot load Plugin Store.")
error.setStyleSheet("color: #ff4757; font-size: 14px;")
layout.addWidget(error)
return tab
def _add_plugin_row(self, layout, plugin_id, plugin_class, colors, prefix):
"""Add a plugin row to the layout."""
try:

View File

@ -124,48 +124,30 @@ class PluginStoreWorker(QThread):
self.manifest_loaded.emit(plugins)
def _do_download(self):
"""Download and install a plugin."""
"""Download and install a plugin using raw files (no git clone)."""
plugin_id = self.target_plugin['id']
folder = self.target_plugin['folder']
self.progress_update.emit(f"Downloading {plugin_id}...")
# Create temp directory
temp_dir = Path("temp_download")
temp_dir.mkdir(exist_ok=True)
try:
# For git repositories, clone and copy folder
import subprocess
import urllib.request
clone_dir = temp_dir / "repo"
if clone_dir.exists():
shutil.rmtree(clone_dir)
# Clone the repository
self.progress_update.emit(f"Cloning repository...")
result = subprocess.run(
['git', 'clone', '--depth', '1', self.repo_url, str(clone_dir)],
capture_output=True,
text=True,
timeout=60
)
if result.returncode != 0:
raise Exception(f"Git clone failed: {result.stderr}")
# Copy plugin folder
source = clone_dir / folder
# Download files directly from raw git
dest = self.plugins_dir / plugin_id
dest.mkdir(parents=True, exist_ok=True)
if dest.exists():
shutil.rmtree(dest)
# Create __init__.py
init_url = f"{self.repo_url}/raw/branch/main/{folder}/__init__.py"
try:
urllib.request.urlretrieve(init_url, dest / "__init__.py")
except:
(dest / "__init__.py").touch()
self.progress_update.emit(f"Installing {plugin_id}...")
shutil.copytree(source, dest)
# Clean up
shutil.rmtree(temp_dir)
# Download plugin.py
plugin_url = f"{self.repo_url}/raw/branch/main/{folder}/plugin.py"
self.progress_update.emit(f"Downloading {plugin_id}/plugin.py...")
urllib.request.urlretrieve(plugin_url, dest / "plugin.py")
self.plugin_downloaded.emit(plugin_id, True)
@ -478,12 +460,23 @@ class PluginStoreUI(QWidget):
# Dependencies indicator
if plugin.dependencies.get('plugins') or plugin.dependencies.get('core'):
deps_count = len(plugin.dependencies.get('plugins', [])) + len(plugin.dependencies.get('core', []))
deps_label = QLabel(f"🔗 {deps_count} dependencies")
deps_label.setStyleSheet("color: #ffd93d; font-size: 10px;")
deps_text = "Requires: " + ", ".join(
plugin.dependencies.get('plugins', []) + plugin.dependencies.get('core', [])
)
deps_label.setToolTip(deps_text[:200])
deps_label = QPushButton(f"🔗 {deps_count} dependencies")
deps_label.setStyleSheet("""
QPushButton {
color: #ffd93d;
font-size: 10px;
background-color: transparent;
border: none;
text-align: left;
padding: 0px;
}
QPushButton:hover {
color: #ffed8a;
text-decoration: underline;
}
""")
deps_label.setCursor(Qt.CursorShape.PointingHandCursor)
deps_label.clicked.connect(lambda checked, p=plugin: self._show_dependencies_dialog(p))
layout.addWidget(deps_label)
layout.addStretch()
@ -628,6 +621,40 @@ class PluginStoreUI(QWidget):
QMessageBox.information(self, "Uninstalled", f"'{plugin.name}' has been uninstalled.")
self._load_plugins()
def _show_dependencies_dialog(self, plugin: PluginInfo):
"""Show dialog with plugin dependencies."""
deps = plugin.dependencies
msg = f"<h3>🔌 {plugin.name} Dependencies</h3>"
# Core dependencies
core_deps = deps.get('core', [])
if core_deps:
msg += "<h4>Core Services Required:</h4><ul>"
for dep in core_deps:
msg += f"<li>✅ {dep} (built-in)</li>"
msg += "</ul>"
# Plugin dependencies
plugin_deps = deps.get('plugins', [])
if plugin_deps:
msg += "<h4>Plugins Required:</h4><ul>"
for dep in plugin_deps:
dep_name = dep.split('.')[-1].replace('_', ' ').title()
msg += f"<li>📦 {dep_name}</li>"
msg += "</ul>"
msg += "<p><i>These will be automatically installed when you install this plugin.</i></p>"
if not core_deps and not plugin_deps:
msg += "<p>This plugin has no dependencies.</p>"
dialog = QMessageBox(self)
dialog.setWindowTitle(f"Dependencies - {plugin.name}")
dialog.setTextFormat(Qt.TextFormat.RichText)
dialog.setText(msg)
dialog.setIcon(QMessageBox.Icon.Information)
dialog.exec()
def _check_updates(self):
"""Check for plugin updates."""
self.progress.show()

View File

@ -1,7 +0,0 @@
"""
Plugin Store UI Plugin
"""
from .plugin import PluginStoreUIPlugin
__all__ = ["PluginStoreUIPlugin"]

View File

@ -1,55 +0,0 @@
"""
EU-Utility - Plugin Store UI Plugin
Provides the Plugin Store interface for browsing and installing plugins.
"""
from PyQt6.QtWidgets import QWidget, QVBoxLayout, QLabel
from core.base_plugin import BasePlugin
from core.plugin_store import PluginStoreUI
class PluginStoreUIPlugin(BasePlugin):
"""Plugin Store for browsing and installing plugins from repositories."""
name = "Plugin Store"
version = "1.0.0"
author = "ImpulsiveFPS"
description = "Browse, install, and manage plugins from the official repository"
icon = "shopping-bag"
hotkeys = [
{
'action': 'open_store',
'description': 'Open Plugin Store',
'default': 'ctrl+shift+p',
'config_key': 'pluginstore_open'
}
]
def initialize(self):
"""Setup plugin store."""
self.store_ui = None
def get_ui(self):
"""Create plugin store UI."""
# Get plugin manager from overlay
plugin_manager = getattr(self.overlay, 'plugin_manager', None)
if not plugin_manager:
# Fallback - show error
widget = QWidget()
layout = QVBoxLayout(widget)
error = QLabel("Plugin Manager not available. Cannot load Plugin Store.")
error.setStyleSheet("color: #ff4757; font-size: 14px;")
layout.addWidget(error)
return widget
self.store_ui = PluginStoreUI(plugin_manager)
return self.store_ui
def on_hotkey(self):
"""Handle hotkey press."""
# Show the plugin store tab
if hasattr(self.overlay, 'show_plugin'):
self.overlay.show_plugin('plugins.plugin_store_ui.plugin')

View File

@ -1,7 +0,0 @@
"""
Settings Plugin
"""
from .plugin import SettingsPlugin
__all__ = ["SettingsPlugin"]

File diff suppressed because it is too large Load Diff