#!/usr/bin/env python3 # FWS — fenêtre « À propos » : deux onglets, « Le projet FWS » (ce qu'est FWS, # version, liens) et « Système » (matériel + logiciel détectés). Remplace le # « About Xfce » de libxfce4ui par une page de marque FWS. GTK3 (python-gobject # installé avec le bureau). import os import re import subprocess import gi gi.require_version("Gtk", "3.0") gi.require_version("Gdk", "3.0") # sinon gi charge Gdk 4.0 (conflit avec Gtk3) from gi.repository import Gdk, GLib, Gtk # noqa: E402 GLib.set_prgname("fws-about") def _osrelease(): data = {} for path in ("/etc/os-release", "/usr/lib/os-release"): try: with open(path) as fh: for line in fh: m = re.match(r'^([A-Z_]+)=(.*)$', line.strip()) if m: data[m.group(1)] = m.group(2).strip('"') break except OSError: continue return data def _cmd(*argv): try: return subprocess.check_output(argv, text=True, stderr=subprocess.DEVNULL).strip() except (OSError, subprocess.CalledProcessError): return "" def _cpu(): try: with open("/proc/cpuinfo") as fh: for line in fh: if line.startswith("model name"): return line.split(":", 1)[1].strip() except OSError: pass return "inconnu" def _mem(): try: with open("/proc/meminfo") as fh: for line in fh: if line.startswith("MemTotal"): kib = int(line.split()[1]) return f"{kib / 1048576:.1f} Gio" except OSError: pass return "inconnu" def _gpus(): out = [] for line in _cmd("lspci").splitlines(): low = line.lower() if "vga" in low or "3d" in low or "display" in low: out.append(line.split(":", 2)[-1].strip()) return out or ["inconnu"] def _desktop(): if os.environ.get("HYPRLAND_INSTANCE_SIGNATURE"): return "Hyprland" env = os.environ.get("XDG_CURRENT_DESKTOP") \ or os.environ.get("DESKTOP_SESSION") or "" return env or "inconnu" def _session_type(): t = os.environ.get("XDG_SESSION_TYPE", "") return {"wayland": "Wayland", "x11": "X11"}.get(t, t or "inconnu") def _disks(): out = [] for line in _cmd("lsblk", "-dno", "NAME,SIZE,MODEL,TYPE").splitlines(): f = line.split() if f and f[-1] == "disk": out.append(" ".join(f[:-1])) return out or ["inconnu"] def _grid(rows): grid = Gtk.Grid(column_spacing=18, row_spacing=8, margin=18) for i, (key, val) in enumerate(rows): k = Gtk.Label(xalign=1) k.set_markup(f"{GLib.markup_escape_text(key)}") k.get_style_context().add_class("dim-label") v = Gtk.Label(label=val, xalign=0, selectable=True) v.set_line_wrap(True) grid.attach(k, 0, i, 1, 1) grid.attach(v, 1, i, 1, 1) return grid def _project_tab(osr): box = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=10, margin=20) title = Gtk.Label() name = osr.get("PRETTY_NAME") or osr.get("NAME") or "FWS Linux" title.set_markup(f"{name}") box.pack_start(title, False, False, 0) tag = Gtk.Label(label="Une distribution Linux pensée pour remplacer " "Windows : bureau prêt à l'emploi, jeux, VR et " "compatibilité applicative.") tag.set_line_wrap(True) tag.set_max_width_chars(52) box.pack_start(tag, False, False, 0) feats = Gtk.Label() feats.set_markup( "Inclus : installateur graphique · plusieurs bureaux " "(GNOME, KDE, Hyprland, i3, XFCE) · Steam & Proton-GE · " "réalité virtuelle (SteamVR) · winboat (applications Windows) · " "pare-feu · réparation système intégrée.") feats.set_line_wrap(True) feats.set_max_width_chars(52) feats.set_xalign(0) box.pack_start(feats, False, False, 6) home = osr.get("HOME_URL") or "https://github.com/You-re-like-Windows-a-bitch/fws" link = Gtk.LinkButton.new_with_label(home, "Site du projet") box.pack_start(link, False, False, 0) return box def _system_tab(osr): rows = [ ("Système", osr.get("PRETTY_NAME", "FWS Linux")), ("Build", osr.get("BUILD_ID", "rolling")), ("Noyau", _cmd("uname", "-r") or "inconnu"), ("Bureau", _desktop()), ("Affichage", _session_type()), ("Nom de machine", _cmd("hostname") or os.uname().nodename), ("Processeur", _cpu()), ("Mémoire", _mem()), ("Carte(s) graphique(s)", "\n".join(_gpus())), ("Disque(s)", "\n".join(_disks())), ] scroll = Gtk.ScrolledWindow() scroll.set_policy(Gtk.PolicyType.NEVER, Gtk.PolicyType.AUTOMATIC) scroll.add(_grid(rows)) return scroll class AboutWindow(Gtk.Window): def __init__(self): super().__init__(title="À propos de FWS") self.set_default_size(520, 460) self.set_position(Gtk.WindowPosition.CENTER) self.set_type_hint(Gdk.WindowTypeHint.DIALOG) osr = _osrelease() notebook = Gtk.Notebook() notebook.append_page(_project_tab(osr), Gtk.Label(label="Le projet FWS")) notebook.append_page(_system_tab(osr), Gtk.Label(label="Système")) self.add(notebook) self.connect("destroy", Gtk.main_quit) def main(): if not Gtk.init_check()[0]: return 1 win = AboutWindow() win.show_all() Gtk.main() return 0 if __name__ == "__main__": raise SystemExit(main())