import gi
import os

gi.require_version("Gtk", "4.0")
import subprocess
from typing import List

from gi.repository import Gtk

# Mirror Liste
MIRRORS = [
    f"{_('Standard')} - https://repo-default.voidlinux.org/",
    f"{_('Weltweit (Tier 1)')} - https://repo-fastly.voidlinux.org/",
    f"{_('Frankfurt (Tier 1)')} - https://repo-de.voidlinux.org/",
    f"{_('Helsinki (Tier 1)')} - https://repo-fi.voidlinux.org/",
    f"{_('Chicago (Tier 1)')} - https://mirrors.servercentral.com/voidlinux/",
]

# --- PAKET DEFINITIONEN ---

SERVICES_SET = ["chrony", "dbus", "NetworkManager", "polkit", "acpid", "cronie", "avahi-daemon", "bluetooth", "tlp"]

BASE_SET = [
    "espeakup", "void-live-audio", "brltty", "dialog", "void-docs-browse", "xmirror", "tmux",
    "grub-i386-efi", "grub-x86_64-efi", "chrony", "zramen", "bash-completion", "base-devel", "binutils", "dkms", 
    "git", "wget", "curl", "fzf", "topgrade", "vsv", "rsync", "tar", "unzip", "xz", "rpm", "rpmextract", 
    "avahi", "nss-mdns", "acpid", "cronie", "mtools", "xtools", "cryptsetup", "lvm2", "mdadm", "gptfdisk", 
    "parted", "dosfstools", "exfatprogs", "btrfs-progs", "grub-btrfs", "zfs", "zfs-auto-snapshot", "udisks2", 
    "gvfs", "gvfs-afc", "gvfs-afp", "gvfs-cdda", "gvfs-gphoto2", "gvfs-mtp", "gvfs-smb", "linux-headers", "alsa-pipewire",
    "linux-firmware", "linux-firmware-amd", "linux-firmware-intel", "linux-firmware-nvidia", "linux-firmware-network", 
    "broadcom-wl-dkms", "os-prober", "efibootmgr", "rtkit", "tlp", "tlpui", "bluez", "bluez-cups", "dconf", 
    "elogind", "dbus", "dbus-elogind", "dbus-elogind-x11", "papirus-icon-theme", "dejavu-fonts-ttf", "alsa-utils", "alsa-plugins-pulseaudio", 
    "freefont-ttf", "liberation-fonts-ttf", "noto-fonts-emoji", "font-awesome6", "terminus-font", "xdg-user-dirs", 
    "xdg-utils", "xdg-desktop-portal", "engrampa", "xarchiver", "ntfs-3g", "octoxbps", "ocs-url", "gtk+3", "gtk4", 
    "void-repo-multilib", "void-repo-multilib-nonfree", "void-repo-nonfree", "vsv", "python3", "python3-dbus", 
    "python3-gobject", "python3-pyudev", "ca-certificates", "samba" 
]

XORG_SET = ["xorg-minimal", "xorg-video-drivers", "xorg-input-drivers", "xrandr", "setxkbmap", "xauth", "numlockx", "font-misc-misc"]

# Desktop Sets
CINNAMON_SET = ["cinnamon", "cinnamon-control-center", "cinnamon-desktop", "cinnamon-screensaver",
    "cinnamon-session", "cinnamon-settings-daemon", "file-roller", "gnome-keyring",
    "gnome-screenshot", "gnome-terminal", "lightdm", "lightdm-gtk-greeter",
    "lightdm-gtk-greeter-settings", "mugshot", "nemo", "nemo-audio-tab", "nemo-compare",
    "nemo-emblems", "nemo-extensions", "nemo-image-converter", "nemo-python", "NetworkManager", "network-manager-applet",
    "simple-scan", "colord", "xdg-desktop-portal", "xdg-user-dirs", "xdg-user-dirs-gtk", "xdg-desktop-portal-wlr", "xdg-desktop-portal-xapp", "xdg-desktop-portal-gtk", "xdg-desktop-portal-gnome"]
    
GNOME_SET = ["gdm", "gnome-core", "gnome-keyring", "sushi", "gnome-terminal",
    "gnome-disk-utility", "gnome-tweaks", "NetworkManager", "network-manager-applet",
    "nautilus-gnome-terminal-extension", "extension-manager", "file-roller",
    "nautilus-papers-extension", "nautilus-python", "seahorse-nautilus", "xdg-desktop-portal", "xdg-desktop-portal-wlr", "xdg-user-dirs", "xdg-user-dirs-gtk", "xdg-desktop-portal-xapp", "xdg-desktop-portal-gtk", "xdg-desktop-portal-gnome"]

KDE_SET = ["sddm", "kde5", "dolphin", "konsole", "ark", "kate", "gwenview", "okular", "spectacle",
    "dolphin-plugins", "kf6-kaccounts-integration", "kaccounts-providers", "kde-gtk-config",
    "kde5-baseapps", "kdegraphics-thumbnailers", "kf6-kdesu", "kde-cli-tools", "kfind", "kio-extras", "kf6-kded",
    "kscreen", "ksysguard", "plasma-browser-integration", "plasma-desktop", "plasma-disks",
    "plasma-nm", "plasma-pa", "sddm-kcm", "xdg-desktop-portal-kde", "NetworkManager", "plasma-nm"]

MATE_SET = ["mate", "mate-extra", "mate-applets", "mate-panel-appmenu", "mate-power-manager", "mate-themes", "mate-tweak", "gnome-terminal", "lightdm", "lightdm-gtk-greeter","lightdm-gtk-greeter-settings", "caja", "caja-extensions", "caja-image-converter", "caja-open-terminal", "caja-sendto", "caja-share", "caja-wallpaper", "gnome-keyring", "NetworkManager", "network-manager-applet", "xdg-desktop-portal-xapp", "xdg-desktop-portal-gtk", "xdg-desktop-portal-gnome"]

XFCE_SET = ["xfce4", "xfce4-appfinder", "xfce4-panel", "xfce4-notifyd", "xfce4-power-manager",
    "xfce4-screensaver", "xfce4-screenshooter", "xfce4-dev-tools", "xfce4-panel-profiles",
    "xfce4-plugins", "xfce4-battery-plugin", "xfce4-clipman-plugin", "xfce4-cpufreq-plugin",
    "xfce4-cpugraph-plugin", "xfce4-datetime-plugin", "xfce4-docklike-plugin",
    "xfce4-fsguard-plugin", "xfce4-sensors-plugin", "xfce4-wavelan-plugin",
    "xfce4-weather-plugin", "xfce4-whiskermenu-plugin", "NetworkManager", "network-manager-applet",
    "Thunar", "thunar-archive-plugin", "thunar-media-tags-plugin", "thunar-volman", "tumbler",
    "lightdm", "lightdm-gtk-greeter", "lightdm-gtk-greeter-settings",
    "menulibre", "mugshot", "gnome-disk-utility", "gnome-icon-theme", "xdg-desktop-portal", "xdg-desktop-portal-wlr", "xdg-user-dirs", "xdg-user-dirs-gtk", "xdg-desktop-portal-xapp", "xdg-desktop-portal-gtk", "xdg-desktop-portal-gnome"]
    
LXQT_SET = ["lxqt",                 # Das Meta-Paket
    "openbox", "obconf-qt", # Der Window Manager (Openbox ist Standard für LXQt)
    
    # Core Komponenten (explizit gewünscht)
    "pcmanfm-qt",           # Dateimanager
    "lxqt-admin",           # Admin-Tools (Datum/Zeit etc.)
    "lxqt-archiver",        # Archiv-Verwaltung (basiert auf libfm-qt)
    "lxqt-config",          # Kontrollzentrum
    "lxqt-menu-data",       # Menü-Strukturen
    "lxqt-notificationd",   # Benachrichtigungen
    "lxqt-panel",           # Taskleiste
    "lxqt-powermanagement", # Energieverwaltung
    "lxqt-runner",          # Schnellstarter (Alt+F2)
    "lxqt-sudo",            # Grafischer Sudo-Dialog
    "lxqt-themes",          # Designs
    
    # Qt Integration
    "lxqt-qtplugin",        # Integration von Qt-Einstellungen
    "lxqt-qt5plugin",       # Speziell für Qt5 Apps (falls noch vorhanden)
    
    # System Integration
    "xdg-desktop-portal-lxqt", # Wichtig für Flatpak & Dateidialoge
    "gnome-keyring",        # Passwort-Speicher
    
    # Apps & Icons
    "lximage-qt",           # Bildbetrachter
    "qterminal",            # Terminal
    "oxygen-icons", "breeze-icons",
    
    # Display Manager
    "sddm"]
    
LXDE_SET = [
    "lxde",                 # Das Meta-Paket
    "lxde-common",          # Sitzungskonfigurationen
    "lxde-icon-theme",      # Standard-Icons
    "lxmenu-data",          # Menü-Strukturen
    
    # Core Komponenten
    "lxpanel",              # Die Taskleiste
    "lxrandr",              # Bildschirmauflösung
    "lxtask",               # Task-Manager
    "lxterminal",           # Terminal
    "pcmanfm",              # Dateimanager
    "libfm-extra",          # Bibliothek für Dateimanager-Funktionen
    
    # Login Manager & Tools
    "lxdm",                 # Display Manager
    "lxappearance",         # Themen-Einstellungen
    "leafpad",              # Einfacher Texteditor
    "gpicview",             # Bildbetrachter
    "openbox"               # Der Window Manager
]
I3_SET = [
    "i3-gaps",              # Der WM mit Lücken zwischen den Fenstern
    "i3blocks",             # Flexiblere Statusleiste
    "i3status",             # Standard Statusleiste (Backup)
    "i3lock-color",         # Sperrbildschirm mit mehr Farboptionen
    "i3lockr",              # Wrapper/Glitch-Effekt für den Lockscreen
    "i3cat",                # Tool um Ausgaben für die Bar zu kombinieren
    "i3wsr",                # Workspace Renamer (automatische Benennung nach Icons)
    
    "rofi",                 # Launcher (Menü)
    "dmenu",                # Fallback Launcher
    "dunst",                # Benachrichtigungen
    
    "azote",                # Wallpaper Manager
    "autotiling",           # Skript für automatisches Tiling (Spiral/Master-Stack)
    "picom",                # Compositor (für Transparenz/Schatten)
    
    # GUI Tools & System
    "arandr",               # Bildschirmeinstellungen
    "lxappearance",         # Themes einstellen
    "network-manager-applet", # WLAN Tray Icon
    "polkit-gnome",         # Rechte-Verwaltung
    
    # Apps
    "alacritty",            # Terminal
    "thunar",               # Dateimanager
    
    # Login Manager
    "lightdm", "lightdm-gtk-greeter", "lightdm-gtk-greeter-settings"
]
SWAY_SET = [
    "swayfx",               # Ersetzt 'sway' (bietet mehr optische Effekte wie Schatten/Runde Ecken)
    "swaybg",               # Hintergrundbilder
    "swayidle",             # Idle-Management
    "swaylock",             # Sperrbildschirm
    "swayimg",              # Bildbetrachter für Sway
    
    # Statusbar & Menü & Benachrichtigungen
    "waybar",               # Die Leiste (Statusbar)
    "rofi",                 # Anwendungsstarter (statt wofi, wie gewünscht)
    "dunst",                # Benachrichtigungs-Daemon (statt mako, wie gewünscht)
    
    # Tools & Konfiguration
    "kanshi",               # Automatisches Display-Profil-Management (Hotplugging)
    "azote",                # Wallpaper Manager & Monitor-Einstellung
    "autotiling",           # Skript für automatisches Tiling (Spiral/Master-Stack)
    "wdisplays",            # GUI für Monitoreinstellungen
    
    # Screenshot & Clipboard
    "grim", "slurp",        # Screenshot Basis-Tools
    "grimshot",             # Screenshot Skript (falls im Repo verfügbar)
    "wl-clipboard",         # Clipboard Manager
    
    # Kompatibilität
    "xorg-server-xwayland", # X11-Apps unter Wayland
    "qt5-wayland", "qt6-wayland", # Qt-Support
    
    # Basis-Apps
    "alacritty",            # Terminal
    "thunar",               # Dateimanager
    
    # System-Integration
    "network-manager-applet",
    "polkit-gnome",
    "lightdm", "lightdm-gtk-greeter", "qt5-wayland", "qt6-wayland"
 ]
OPENBOX_SET = [
    # Core & Konfiguration
    "openbox",              # Der Window Manager
    "obconf",               # GUI zum Konfigurieren von Openbox
    "lxappearance-obconf",  # Plugin, um Openbox-Themes in lxappearance zu wählen
    
    # Interface Elemente
    "tint2",                # Die klassische Taskleiste für Openbox
    "jgmenu",               # Modernes, dynamisches Menü (Startmenü)
    "dmenu",                # Minimalistischer Launcher
    "rofi",                 # Komfortabler Launcher
    "dunst",                # Benachrichtigungen
    
    # System Tray Apps (Wichtig für Usability!)
    "volumeicon",           # Lautstärke-Icon im Tray
    "cbatticon",            # Batterie-Icon im Tray
    "network-manager-applet", # WLAN-Icon
    
    # Optik & Verhalten
    "nitrogen",             # Wallpaper setzen
    "picom",                # Compositor (Schatten, Transparenz, V-Sync)
    "lxappearance",         # GTK-Themen und Icons einstellen
    "arandr",               # Bildschirm-Auflösung (GUI)
    
    # Tools
    "scrot",                # Screenshot Tool (einfach per Taste)
    "gmrun",                # Befehls-Ausführen Dialog
    "polkit-gnome",         # Authentifizierungs-Dialog (für Sudo-GUIs)
    
    # Basis Apps
    "thunar",               # Dateimanager (passt perfekt zu Openbox)
    "alacritty",            # Terminal
    
    # Login Manager
    "lightdm", "lightdm-gtk-greeter", "lightdm-gtk-greeter-settings"
]
AWESOME_SET = [
    "awesome",              # Der WM
    "vicious",              # Widgets für Awesome (Battery, CPU, Mem etc.)
    "picom",                # Compositor
    "nitrogen",             # Wallpaper
    "rofi", "dmenu",        # Launcher
    
    # System Tray Helfer (da Awesome standardmäßig leer ist)
    "volumeicon",           # Audio Icon
    "cbatticon",            # Batterie Icon
    "network-manager-applet", # WLAN Icon
    
    # GUI Tools
    "arandr",               # Bildschirm
    "lxappearance",         # Themes
    "polkit-gnome",         # Auth
    "scrot",                # Screenshots
    
    # Apps
    "alacritty",            # Terminal
    "thunar",               # Files
    
    # Login
    "lightdm", "lightdm-gtk-greeter", "lightdm-gtk-greeter-settings"
]
COSMIC_SET = ["cosmic-desktop-full", "gdm", "xdg-desktop-portal-xapp", "xdg-desktop-portal-gtk", "xdg-desktop-portal", "xdg-desktop-portal-cosmic"]

# Bundles
BUNDLE_NVIDIA = ["nvidia", "nvidia-libs", "nvidia-dkms"]
BUNDLE_PRINTER = ["cups", "cups-filters", "foomatic-db", "foomatic-db-engine", "gutenprint", "system-config-printer", "hplip", "python3-cups"]
BUNDLE_PIPEWIRE = ["pipewire", "wireplumber", "pavucontrol", "pulsemixer", "libspa-bluetooth", "alsa-pipewire"]
BUNDLE_NONFREE_CODECS = ["ffmpeg", "ffmpegthumbnailer", "gst-libav", "gst-plugins-base1", "gst-plugins-good1", "gst-plugins-bad1", "x264", "x265" "gst-plugins-ugly1"]

class SoftwareConfigView(Gtk.Box):
    def __init__(self):
        super().__init__(orientation=Gtk.Orientation.VERTICAL, spacing=12)
        for s in (self.set_margin_top, self.set_margin_bottom, self.set_margin_start, self.set_margin_end):
            s(6)

        title = Gtk.Label.new(_("Software & Konfiguration"))
        title.add_css_class("title-2")
        title.set_halign(Gtk.Align.START)
        self.append(title)

        sc = Gtk.ScrolledWindow()
        sc.set_vexpand(True)
        sc.set_policy(Gtk.PolicyType.NEVER, Gtk.PolicyType.AUTOMATIC)
        self.append(sc)
        
        root = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=15)
        self._set_margins(root, 10)
        sc.set_child(root)

        # 1. Mirror
        self.f_repo = Gtk.Frame(label=_("Repository Server"))
        self.f_repo.add_css_class("card")
        box_repo = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL, spacing=8)
        self._set_margins(box_repo, 10)
        self.cmb_mirror = Gtk.ComboBoxText()
        for m in MIRRORS: self.cmb_mirror.append_text(m)
        self.cmb_mirror.set_active(0)
        box_repo.append(Gtk.Label.new(_("Mirror:")))
        box_repo.append(self.cmb_mirror)
        self.f_repo.set_child(box_repo)
        root.append(self.f_repo)

        # 2. Desktop Selection (Exclusive)
        self.f_de = Gtk.Frame(label=_("Desktop Umgebung / Window Manager"))
        self.f_de.add_css_class("card")
        grid_de = Gtk.Grid()
        grid_de.set_column_spacing(20); grid_de.set_row_spacing(15); grid_de.set_column_homogeneous(True)
        self._set_margins(grid_de, 10)

        self.cb_none = Gtk.CheckButton.new_with_label(_("Minimal (Kein Desktop)"))
        self.cb_none.set_active(True)
        grid_de.attach(self.cb_none, 0, 0, 1, 1)

        # Reihe 1
        self.cb_cinnamon = Gtk.CheckButton.new_with_label("Cinnamon"); self.cb_cinnamon.set_group(self.cb_none); grid_de.attach(self.cb_cinnamon, 1, 0, 1, 1)
        self.cb_gnome = Gtk.CheckButton.new_with_label("GNOME"); self.cb_gnome.set_group(self.cb_none); grid_de.attach(self.cb_gnome, 2, 0, 1, 1)
        self.cb_kde = Gtk.CheckButton.new_with_label("KDE Plasma"); self.cb_kde.set_group(self.cb_none); grid_de.attach(self.cb_kde, 3, 0, 1, 1)
        self.cb_xfce = Gtk.CheckButton.new_with_label("XFCE"); self.cb_xfce.set_group(self.cb_none); grid_de.attach(self.cb_xfce, 4, 0, 1, 1)

        # Reihe 2
        self.cb_lxqt = Gtk.CheckButton.new_with_label("LXQt"); self.cb_lxqt.set_group(self.cb_none); grid_de.attach(self.cb_lxqt, 0, 1, 1, 1)
        self.cb_lxde = Gtk.CheckButton.new_with_label("LXDE"); self.cb_lxde.set_group(self.cb_none); grid_de.attach(self.cb_lxde, 1, 1, 1, 1)
        self.cb_i3 = Gtk.CheckButton.new_with_label("i3 (Tiling)"); self.cb_i3.set_group(self.cb_none); grid_de.attach(self.cb_i3, 2, 1, 1, 1)
        self.cb_sway = Gtk.CheckButton.new_with_label("Sway (Wayland)"); self.cb_sway.set_group(self.cb_none); grid_de.attach(self.cb_sway, 3, 1, 1, 1)
        self.cb_openbox = Gtk.CheckButton.new_with_label("Openbox"); self.cb_openbox.set_group(self.cb_none); grid_de.attach(self.cb_openbox, 4, 1, 1, 1)

        # Reihe 3
        self.cb_awesome = Gtk.CheckButton.new_with_label("Awesome WM"); self.cb_awesome.set_group(self.cb_none); grid_de.attach(self.cb_awesome, 0, 2, 1, 1)
        self.cb_cosmic = Gtk.CheckButton.new_with_label("Cosmic (extern Repo)"); self.cb_cosmic.set_group(self.cb_none); grid_de.attach(self.cb_cosmic, 1, 2, 1, 1)
        self.cb_mate = Gtk.CheckButton.new_with_label("MATE"); self.cb_mate.set_group(self.cb_none); grid_de.attach(self.cb_mate, 2, 2, 1, 1)

        self.f_de.set_child(grid_de)
        root.append(self.f_de)

        # 3. Additional Software
        f_extra = Gtk.Frame(label=_("Zusätzliche Pakete"))
        f_extra.add_css_class("card")
        grid_main = Gtk.Grid(); grid_main.set_column_spacing(15); grid_main.set_row_spacing(15); grid_main.set_column_homogeneous(True)
        self._set_margins(grid_main, 10)

        # Kachel 1: Driver & Services
        box_sys = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=6)
        box_sys.append(Gtk.Label(label=_("Driver & Services")))
        self.cb_nvidia = Gtk.CheckButton.new_with_label("NVIDIA"); box_sys.append(self.cb_nvidia)
        self.cb_printer = Gtk.CheckButton.new_with_label(_("Printer (CUPS)")); box_sys.append(self.cb_printer)
        self.cb_pipewire = Gtk.CheckButton.new_with_label("PipeWire"); box_sys.append(self.cb_pipewire)
        self.cb_codecs = Gtk.CheckButton.new_with_label("Codecs"); box_sys.append(self.cb_codecs)
        self.cb_flatpak = Gtk.CheckButton.new_with_label("Flatpak"); box_sys.append(self.cb_flatpak)
        grid_main.attach(box_sys, 0, 0, 1, 1)

        # Kachel 2: Internet
        box_net = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=6)
        box_net.append(Gtk.Label(label=_("Internet")))
        # Firefox Sektion
        self.cb_firefox_en = Gtk.CheckButton.new_with_label("Firefox")
        self.cb_firefox = Gtk.CheckButton.new_with_label("Firefox (de)")
        box_net.append(self.cb_firefox_en)
        box_net.append(self.cb_firefox)
        
        # Thunderbird Sektion
        self.cb_thunderbird_en = Gtk.CheckButton.new_with_label("Thunderbird")
        self.cb_thunderbird = Gtk.CheckButton.new_with_label("Thunderbird (de)")
        box_net.append(self.cb_thunderbird_en)
        box_net.append(self.cb_thunderbird)
        self.cb_chromium = Gtk.CheckButton.new_with_label("Chromium"); box_net.append(self.cb_chromium)
        self.cb_vivaldi = Gtk.CheckButton.new_with_label("Vivaldi"); box_net.append(self.cb_vivaldi)
        self.cb_element = Gtk.CheckButton.new_with_label("Element"); box_net.append(self.cb_element)
        grid_main.attach(box_net, 1, 0, 1, 1)

        # Kachel 3: Office
        box_off = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=6)
        box_off.append(Gtk.Label(label=_("Office")))
        self.cb_libre = Gtk.CheckButton.new_with_label("LibreOffice (de)"); box_off.append(self.cb_libre)
        self.cb_papers = Gtk.CheckButton.new_with_label("Papers"); box_off.append(self.cb_papers)
        self.cb_xournal = Gtk.CheckButton.new_with_label("Xournal++"); box_off.append(self.cb_xournal)
        self.cb_freeplane = Gtk.CheckButton.new_with_label("Freeplane"); box_off.append(self.cb_freeplane)
        self.cb_evince = Gtk.CheckButton.new_with_label("Evince (PDF)"); box_off.append(self.cb_evince)
        grid_main.attach(box_off, 2, 0, 1, 1)

        # Kachel 4: Multimedia
        box_media = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=6)
        box_media.append(Gtk.Label(label=_("Multimedia")))
        self.cb_kdenlive = Gtk.CheckButton.new_with_label("Kdenlive (KDE)"); box_media.append(self.cb_kdenlive)
        self.cb_gimp = Gtk.CheckButton.new_with_label("GIMP"); box_media.append(self.cb_gimp)
        self.cb_inkscape = Gtk.CheckButton.new_with_label("Inkscape"); box_media.append(self.cb_inkscape)
        self.cb_vlc = Gtk.CheckButton.new_with_label("VLC"); box_media.append(self.cb_vlc)
        self.cb_obs = Gtk.CheckButton.new_with_label("OBS Studio"); box_media.append(self.cb_obs)
        grid_main.attach(box_media, 3, 0, 1, 1)

        # Kachel 5: System-Tools
        box_tools = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=6)
        box_tools.append(Gtk.Label(label=_("System-Tools")))
        self.cb_timeshift = Gtk.CheckButton.new_with_label("Timeshift"); box_tools.append(self.cb_timeshift)
        self.cb_gparted = Gtk.CheckButton.new_with_label("GParted"); box_tools.append(self.cb_gparted)
        self.cb_gnome_disk = Gtk.CheckButton.new_with_label("GNOME Disk"); box_tools.append(self.cb_gnome_disk)
        self.cb_filezilla = Gtk.CheckButton.new_with_label("FileZilla"); box_tools.append(self.cb_filezilla)
        self.cb_fastfetch = Gtk.CheckButton.new_with_label("Fastfetch"); box_tools.append(self.cb_fastfetch)
        grid_main.attach(box_tools, 4, 0, 1, 1)

        f_extra.set_child(grid_main); root.append(f_extra)

        # 4. Copy Options
        self.f_copy = Gtk.Frame(label=_("Anpassungen kopieren"))
        self.f_copy.add_css_class("card")
        box_copy = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=10); self._set_margins(box_copy, 10)
        self.rb_copy_none = Gtk.CheckButton.new_with_label(_("Nichts kopieren"))
        self.rb_copy_iso = Gtk.CheckButton.new_with_label(_("ISO-Anpassungen kopieren"))
        self.rb_copy_include = Gtk.CheckButton.new_with_label(_("Inhalt aus /opt/INCLUDE kopieren"))
        self.rb_copy_iso.set_group(self.rb_copy_none); self.rb_copy_include.set_group(self.rb_copy_none)
        box_copy.append(self.rb_copy_none); box_copy.append(self.rb_copy_iso); box_copy.append(self.rb_copy_include)
        self.f_copy.set_child(box_copy); root.append(self.f_copy)

        self.f_info = Gtk.Frame(); self.f_info.add_css_class("card")
        box_info = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL, spacing=12); self._set_margins(box_info, 12)
        info_icon = Gtk.Image.new_from_icon_name("emblem-important-symbolic")
        box_info.append(info_icon)
        self.lbl_include_info = Gtk.Label(label=_("Hinweis: Der Inhalt von /opt/INCLUDE wird automatisch integriert."))
        self.lbl_include_info.set_wrap(True); box_info.append(self.lbl_include_info)
        self.f_info.set_child(box_info); root.append(self.f_info)

        self.install_mode = "net"

    def _set_margins(self, widget, value):
        widget.set_margin_top(value); widget.set_margin_bottom(value); widget.set_margin_start(value); widget.set_margin_end(value)

    def set_install_mode(self, mode: str):
        self.install_mode = mode
        is_live = (mode == "live")
        self.f_de.set_visible(not is_live); self.f_repo.set_visible(not is_live); self.f_copy.set_visible(is_live)
        if not is_live: self.rb_copy_include.set_active(True)
        else: self.rb_copy_iso.set_active(True)

    def get_copy_option(self) -> str:
        if self.install_mode == "net": return "include"
        if self.rb_copy_iso.get_active(): return "iso"
        if self.rb_copy_include.get_active(): return "include"
        return "none"

    def get_mirror_url(self) -> str:
        sel = self.cmb_mirror.get_active_text() or ""
        return sel.split(" - ")[-1].strip() if "https://" in sel else "https://repo-default.voidlinux.org"

    def get_selected_packages(self, fs_choice: str = "ext4") -> List[str]:
        pkgs = []
        desktop_active = False
        if self.install_mode == "net":
            if self.cb_cinnamon.get_active(): pkgs.extend(CINNAMON_SET); desktop_active = True
            elif self.cb_gnome.get_active(): pkgs.extend(GNOME_SET); desktop_active = True
            elif self.cb_kde.get_active(): pkgs.extend(KDE_SET); desktop_active = True
            elif self.cb_mate.get_active(): pkgs.extend(MATE_SET); desktop_active = True
            elif self.cb_xfce.get_active(): pkgs.extend(XFCE_SET); desktop_active = True
            elif self.cb_lxqt.get_active(): pkgs.extend(LXQT_SET); desktop_active = True
            elif self.cb_lxde.get_active(): pkgs.extend(LXDE_SET); desktop_active = True
            elif self.cb_i3.get_active(): pkgs.extend(I3_SET); desktop_active = True
            elif self.cb_sway.get_active(): pkgs.extend(SWAY_SET); desktop_active = True
            elif self.cb_openbox.get_active(): pkgs.extend(OPENBOX_SET); desktop_active = True
            elif self.cb_awesome.get_active(): pkgs.extend(AWESOME_SET); desktop_active = True
            elif self.cb_cosmic.get_active(): pkgs.extend(COSMIC_SET + SERVICES_SET); desktop_active = True
            
            if desktop_active: pkgs.extend(XORG_SET)

        # Zusatzpakete sammeln
        if self.cb_nvidia.get_active(): pkgs.extend(BUNDLE_NVIDIA)
        if self.cb_printer.get_active(): pkgs.extend(BUNDLE_PRINTER)
        if self.cb_pipewire.get_active(): pkgs.extend(BUNDLE_PIPEWIRE)
        if self.cb_codecs.get_active(): pkgs.extend(BUNDLE_NONFREE_CODECS)
        if self.cb_flatpak.get_active(): pkgs.append("flatpak")
        if self.cb_firefox_en.get_active(): pkgs.append("firefox")
        if self.cb_firefox.get_active(): pkgs.extend(["firefox", "firefox-i18n-de"])
        if self.cb_chromium.get_active(): pkgs.append("chromium")
        if self.cb_vivaldi.get_active(): pkgs.append("vivaldi")
        if self.cb_element.get_active(): pkgs.append("element-desktop")
        if self.cb_thunderbird_en.get_active(): pkgs.append("thunderbird")
        if self.cb_thunderbird.get_active(): pkgs.extend(["thunderbird", "thunderbird-i18n-de"])
        if self.cb_libre.get_active(): pkgs.extend(["libreoffice", "libreoffice-i18n-de"])
        if self.cb_papers.get_active(): pkgs.append("papers")
        if self.cb_xournal.get_active(): pkgs.append("xournalpp")
        if self.cb_freeplane.get_active(): pkgs.append("freeplane")
        if self.cb_evince.get_active(): pkgs.append("evince")
        if self.cb_kdenlive.get_active(): pkgs.append("kdenlive")
        if self.cb_gimp.get_active(): pkgs.append("gimp")
        if self.cb_inkscape.get_active(): pkgs.append("inkscape")
        if self.cb_vlc.get_active(): pkgs.append("vlc")
        if self.cb_obs.get_active(): pkgs.append("obs")
        if self.cb_timeshift.get_active(): pkgs.append("timeshift")
        if self.cb_gparted.get_active(): pkgs.append("gparted")
        if self.cb_gnome_disk.get_active(): pkgs.append("gnome-disk-utility")
        if self.cb_filezilla.get_active(): pkgs.append("filezilla")
        if self.cb_fastfetch.get_active(): pkgs.append("fastfetch")

        pkgs.extend(BASE_SET)
        return list(set(pkgs))

    def get_include_root(self) -> str:
        return "/opt/INCLUDE"
