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:
parent
c18a90481a
commit
a81e5caf64
|
|
@ -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:
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
|
|
|
|||
|
|
@ -1,7 +0,0 @@
|
|||
"""
|
||||
Plugin Store UI Plugin
|
||||
"""
|
||||
|
||||
from .plugin import PluginStoreUIPlugin
|
||||
|
||||
__all__ = ["PluginStoreUIPlugin"]
|
||||
|
|
@ -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')
|
||||
|
|
@ -1,7 +0,0 @@
|
|||
"""
|
||||
Settings Plugin
|
||||
"""
|
||||
|
||||
from .plugin import SettingsPlugin
|
||||
|
||||
__all__ = ["SettingsPlugin"]
|
||||
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue