# plugins/plugin_manager.py def register(app): from PyQt5.QtWidgets import ( QWidget, QVBoxLayout, QHBoxLayout, QLabel, QPushButton, QFileDialog, QScrollArea, QMessageBox ) import os import json import shutil import importlib.util plugin_dir = os.path.join(os.path.dirname(__file__)) config_path = os.path.join(plugin_dir, "enabled_plugins.json") tab = QWidget() layout = QVBoxLayout() if not hasattr(app, "loaded_plugins"): app.loaded_plugins = [] if not hasattr(app, "plugin_refs"): app.plugin_refs = {} if os.path.exists(config_path): with open(config_path, "r") as f: plugin_status = json.load(f) else: plugin_status = {} # Área de scroll para muitos plugins scroll = QScrollArea() scroll_widget = QWidget() scroll_layout = QVBoxLayout() def save_config(): with open(config_path, "w") as f: json.dump(plugin_status, f, indent=4) def activate_plugin(fname): if fname in app.plugin_refs: QMessageBox.information(tab, "Aviso", f"Plugin '{fname}' já está carregado.") return try: path = os.path.join(plugin_dir, fname) spec = importlib.util.spec_from_file_location("plugin", path) plugin = importlib.util.module_from_spec(spec) spec.loader.exec_module(plugin) plugin.register(app) app.loaded_plugins.append(fname) app.plugin_refs[fname] = plugin plugin_status[fname] = True save_config() refresh_ui() except Exception as e: QMessageBox.critical(tab, "Erro ao ativar", f"{fname}:\n{e}") def deactivate_plugin(fname): QMessageBox.information(tab, "Desativação", f"O plugin '{fname}' será desabilitado. Reinicie o app para refletir completamente.") plugin_status[fname] = False save_config() refresh_ui() def refresh_ui(): for i in reversed(range(scroll_layout.count())): scroll_layout.itemAt(i).widget().setParent(None) for fname in sorted(os.listdir(plugin_dir)): if fname.endswith(".py") and fname != "plugin_manager.py": row = QHBoxLayout() label = QLabel(fname) status = QLabel("✅ Ativado" if plugin_status.get(fname, True) else "❌ Desativado") btn = QPushButton("Desativar" if plugin_status.get(fname, True) else "Ativar") def make_action(name, active): return lambda: deactivate_plugin(name) if active else activate_plugin(name) btn.clicked.connect(make_action(fname, plugin_status.get(fname, True))) row.addWidget(label) row.addWidget(status) row.addWidget(btn) scroll_layout.addLayout(row) def import_plugin(): file, _ = QFileDialog.getOpenFileName(app, "Importar plugin", "", "Python Files (*.py)") if file: dst = os.path.join(plugin_dir, os.path.basename(file)) if os.path.exists(dst): QMessageBox.warning(tab, "Aviso", "Esse plugin já existe.") return shutil.copy(file, dst) plugin_status[os.path.basename(file)] = True save_config() activate_plugin(os.path.basename(file)) import_btn = QPushButton("📂 Importar novo Plugin (.py)") import_btn.clicked.connect(import_plugin) scroll_widget.setLayout(scroll_layout) scroll.setWidgetResizable(True) scroll.setWidget(scroll_widget) layout.addWidget(import_btn) layout.addWidget(scroll) tab.setLayout(layout) app.tabs.addTab(tab, "Marketplace de Plugins") refresh_ui()