plugins_view.py 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596
  1. # -*- coding: utf-8 -*-
  2. """
  3. F3: Plugin-Auswahl — Checkboxen gruppiert nach Kategorie.
  4. Liest plugins.json im Format:
  5. {
  6. "PluginList": [
  7. { "name": "Kategorie", "plugins": [
  8. { "name": "...", "description": "...", "recommended": true, "checked": true }
  9. ]}
  10. ]
  11. }
  12. """
  13. from __future__ import annotations
  14. import json
  15. from pathlib import Path
  16. from textual.widgets import Checkbox, Label, Static
  17. from .base import InstallerView
  18. class PluginsView(InstallerView):
  19. """Plugin-Auswahl (F3)."""
  20. TITLE = "Plugins"
  21. VIEW_ID = "plugins"
  22. MODES = ["server", "standalone"]
  23. def __init__(self, installer_config, **kwargs) -> None:
  24. super().__init__(installer_config, **kwargs)
  25. self._plugin_list: list[dict] = []
  26. self._load_plugins()
  27. def _load_plugins(self) -> None:
  28. """Laedt Plugin-Metadaten aus plugins.json."""
  29. plugins_json = Path(__file__).parent.parent / "plugins.json"
  30. if plugins_json.is_file():
  31. with open(plugins_json) as f:
  32. data = json.load(f)
  33. self._plugin_list = data.get("PluginList", [])
  34. # Initiale Auswahl aus checked-Feld setzen
  35. if not self._config.selected_plugins:
  36. for category in self._plugin_list:
  37. for plugin in category.get("plugins", []):
  38. if plugin.get("checked", False):
  39. self._config.selected_plugins.append(plugin["name"])
  40. def compose(self):
  41. yield Static("── Plugin-Auswahl ──", classes="section-header")
  42. yield Label("Waehle die Plugins fuer die Installation:\n")
  43. if not self._plugin_list:
  44. yield Label("Keine Plugin-Daten gefunden (plugins.json fehlt)")
  45. return
  46. for category in self._plugin_list:
  47. cat_name = category.get("name", "Sonstige")
  48. plugins = category.get("plugins", [])
  49. yield Static(f"\n {cat_name}", classes="section-header")
  50. for plugin in plugins:
  51. name = plugin["name"]
  52. desc = plugin.get("description", "")
  53. recommended = plugin.get("recommended", False)
  54. is_selected = name in self._config.selected_plugins
  55. label = name
  56. if desc:
  57. label += f" — {desc}"
  58. if recommended:
  59. label += " [empfohlen]"
  60. yield Checkbox(
  61. label,
  62. value=is_selected,
  63. id=f"plugin-{name}",
  64. )
  65. def on_checkbox_changed(self, event: Checkbox.Changed) -> None:
  66. cb_id = event.checkbox.id or ""
  67. if not cb_id.startswith("plugin-"):
  68. return
  69. plugin_name = cb_id[7:] # "plugin-" entfernen
  70. if event.value:
  71. if plugin_name not in self._config.selected_plugins:
  72. self._config.selected_plugins.append(plugin_name)
  73. else:
  74. if plugin_name in self._config.selected_plugins:
  75. self._config.selected_plugins.remove(plugin_name)