Objectifs
Il s'agit de créer une application graphique imitant l'outil language-selector-gnome disponible dans Ubuntu, qui soit lancé automatiquement dès la première session après une installation de antiX ou d'un de ses « respins » (nom donné par la communauté antiX aux versions dérivées, que l'on peut produire avec l'outil Snapshot, ou dans un live, avec l'outil remaster-antix.
Je suis une apprentie en matière de codage et même de scripting, et Claude.ai, quand consulté, attaque directement par une proposition de formation sur le tas. Je dois de toute façon, apprendre à scripter, alors, allons-y, c'est le moment ! 👌
Entrée en matière
« Python + GTK3 reste ma recommandation, pour ces raisons adaptées à ta situation : »🐍
- La syntaxe est lisible, les erreurs sont explicites
- GTK3 en Python est très bien documenté en français
- Le code ressemblera à ce que tu peux lire et comprendre progressivement
- Avec mon aide et celle des autres IA, on peut construire ça ensemble pas à pas, en commentant chaque bloc
(…)
pour la programmation : tu vas voir que Python est vraiment le meilleur point d'entrée. La syntaxe est proche du langage naturel, et avec GTK3 on manipule des objets qui ont une logique très visuelle — une fenêtre, un onglet, un bouton, une liste. Rien d'abstrait. ☕
→ J'ai une question sur l'articulation entre Python et GTK3, comment cela se produit-il ?
L'articulation entre Python et GTK3
Alors : Python est le langage, GTK3 est la boîte à outils graphique. L'articulation entre les deux se fait via python3-gi — le "gi" signifie "GObject Introspection". C'est le pont qui permet à Python de parler à GTK3.
Concrètement :
gi.require_version('Gtk', '3.0')
from gi.repository import Gtk
Ces trois lignes disent : "je veux utiliser GTK version 3, et j'importe ses composants".
Ensuite tout ce que tu vois à l'écran — fenêtre, onglet, bouton, liste — est un objet GTK que Python manipule. Par exemple :
bouton = Gtk.Button(label="Appliquer")
La logique est : Python décrit quoi afficher et quoi faire quand l'utilisateur clique, GTK3 se charge du dessin à l'écran.
C'est ça qui t'intéresse comme articulation, ou tu voulais aller plus loin dans une direction précise ? 🙂
→ c'est bien ça. Et "GObject" tu peux m'en parler en détails ?
Bien sûr !
GObject est le système de base sur lequel repose toute la pile GTK. C'est une bibliothèque C qui apporte à un langage qui n'en a pas nativement — le C — un système orienté objet : des classes, de l'héritage, des signaux.
Pourquoi ça existe ? GTK a été écrit en C pour être léger et portable. Mais le C ne connaît pas les objets. GObject est la solution inventée par les développeurs GNOME pour combler ce manque — une sorte de "couche objet" construite au-dessus du C.
Ce que GObject apporte concrètement :
- Les classes et l'héritage : un Gtk.Button hérite de Gtk.Widget qui hérite de GObject.Object. Chaque niveau ajoute des capacités.
- Les signaux : le mécanisme qui permet de dire "quand l'utilisateur clique sur ce bouton, appelle cette fonction". C'est le cœur de toute interface graphique GTK.
- Les propriétés : chaque objet a des propriétés modifiables (taille, couleur, texte...).
- La gestion mémoire : GObject compte les références pour savoir quand libérer la mémoire.
👉 Et "Introspection" dans python3-gi ? C'est ce qui permet à Python de "découvrir" automatiquement toutes les classes et fonctions GTK sans qu'il faille tout réécrire en Python. GObject expose ses propres métadonnées, et python3-gi les lit pour construire le pont.

Légende
👉 Une analogie : GObject est le fabricant de pièces, GTK3 est l'assembleur, et python3-gi est le traducteur qui te permet de donner tes instructions en Python. 🙂
Des questions sur un point précis ?
→ Oui une question, tu dis «Le C ne connaît pas les objets» et «GObject est la solution inventée pour combler ce manque» : en quoi est-il écrit ?
😄 Excellente question — et c'est là que c'est malicieux !
GObject est écrit... en C. Il simule l'orienté objet en C en utilisant des structures (struct), des pointeurs de fonctions, et des conventions strictes de nommage et d'organisation du code.
C'est du C qui fait semblant d'être objet — de façon très disciplinée et très rigoureuse, mais du C quand même :
Les classes sont des structures, l'héritage est simulé en plaçant la structure parente en premier membre de la structure enfant, et les méthodes sont des fonctions dont le premier argument est toujours un pointeur vers l'objet.
C'est un tour de force d'ingénierie, et aussi la preuve que quand on n'a pas l'outil, on l'invente avec ce qu'on a. ☕ 🙂
Squelette Python GTK3 pour sélecteur de langue
Le workflow
- Au premier démarrage de session après installation, le programme se lance automatiquement
- Les démarrages suivants : le programme reste disponible dans les menus, section Préférences, mais ne se lance plus automatiquement
Dans le détail :
- Un fichier locales-reconfiguration.desktop sous /usr/share/applications : point d'entrée permanent dans les menus
- Un lien symbolique de ce fichier vers /etc/xdg/autostart : pour le lancement automatique au premier démarrage ## Lors des tests vérifier si un symlink dans /etc/xdg/autostart suffit à lancer le programme au moment voulu
- Vérification de l'absence du répertoire /live : si le système est en session live, le programme quitte silencieusement ; sinon il se lance
- Le script /usr/local/bin/locales-reconfiguration.py : le programme lui-même
- Aux démarrages suivants : le lien symbolique n'existe plus → pas de lancement automatique
Nous nous inspirons du programme language-selector-gnome de Ubuntu dont la description suit.
Description de ce que fait language-selector-gnome
- Ouverture du programme sans droits particuliers
- Affichage de la fenêtre principale avec deux onglets : Langue / Formats régionaux
- L'utilisateur choisit sa langue dans l'onglet Langue
- L'utilisateur choisit ses formats régionaux dans l'onglet Formats régionaux
- Clic sur Appliquer à tout le système : une boîte de dialogue demande le mot de passe administrateur
- Le choix de l'utilisateur est validé pour tout le système
- Modification de /etc/locale.gen : seule la locale choisie reste décommentée
- Appel à /usr/sbin/locale-gen
- Mise à jour de /etc/default/locale avec les variables LC_*
- Fermeture du programme
Description de ce que fera le programme
- Lecture de ~/.config/locale pour détecter la langue configurée par l'utilisateur
- Fallback vers /etc/default/locale si ~/.config/locale est absent ou vide
- Extraction des codes locales présents (LANG, LC_*)
- Affichage d'une confirmation à l'utilisateur : langue détectée, demande de mot de passe
- Remplacement du contenu de /usr/share/i18n/SUPPORTED par le template depuis /usr/share/bento/locale.gen.template, via sudo -S via subprocess (locale.gen.template contient la même chose que le fichier /usr/share/i18n/SUPPORTED mais il est entièrement commenté)
- On décommente les lignes correspondantes aux locales détectées dans /etc/locale.gen (lequel est un lien symbolique qui pointe vers /usr/share/i18n/SUPPORTED )
- Appel à /usr/sbin/locale-gen via sudo -S via subprocess
- Information à l'utilisateur : pour configurer plusieurs langues, utiliser sudo dpkg-reconfigure locales
Workflow du lancement du programme
Premier démarrage de session après installation
- Un fichier locales-reconfiguration.desktop est présent sous /etc/xdg/autostart : il déclenche automatiquement le lancement à la première ouverture de session
- Ce fichier .desktop appelle un script bash /usr/local/bin/start-locales-reconfigurator.sh
- Le script bash vérifie que l'on n'est pas en session live (absence du répertoire /live), puis lance le programme Python GTK3 /usr/local/bin/locales-reconfiguration.py
- Python crée un fichier /tmp/locales-reconf.started pour signaler qu'il est bien démarré
- Le script bash détecte l'apparition de ce fichier locales-reconf.started, puis supprime /etc/xdg/autostart/locales-reconfiguration.desktop
- Le programme Python GTK3 se présente à l'utilisateur
Le script start-locales-reconfigurator.sh
Pour détecter l'apparition du fichier locales-reconf.started, on pourrait utiliser un simple if :
rm /etc/xdg/autostart/locales-reconfiguration.desktop
fi
Mais avec if, si Python démarre lentement, le test s'exécute avant que le fichier locales-reconf.started soit créé — et rien ne se passe. Le lanceur n'est pas supprimé.
On utilise donc while à la place : il boucle et attend patiemment l'apparition du fichier, en retestant toutes les 0,5 secondes. Dès que Python crée le fichier locales-reconf.started, la boucle s'arrête et le lanceur est supprimé.
# Vérification : si on est dans une session live le programme quitte en silence
if [ -d "/live" ]; then
exit 0
fi
# Lancement du programme Python GTK3 en arrière-plan
/usr/local/bin/locales-reconfiguration.py &
# Attente de l'apparition du fichier locales-reconf.started
# (signale que Python est bien démarré)
while [ ! -f "/tmp/locales-reconf.started" ]; do
sleep 0.5
done
# Python est lancé : on supprime le lanceur automatique
rm /etc/xdg/autostart/locales-reconfiguration.desktop
Le & après la commande de lancement de Python est indispensable : sans lui, bash resterait bloqué à attendre que Python se termine et n'atteindrait jamais la boucle while. Premier plan est le comportement par défaut de bash, le signe & en fin de ligne change ce comportement en lançant la commande en arrière-plan.
Le ! devant -f signifie "tant que le fichier n'existe PAS" : la boucle tourne jusqu'à ce que Python signale son démarrage. exit 0 dans le bloc if [ -d "/live" ] arrête immédiatement le script avec un code de retour 0 : la convention Unix pour pas d'erreur, rien à faire ici.
Démarrages suivants
Le fichier /etc/xdg/autostart/locales-reconfiguration.desktop n'existe plus — le programme ne se lance plus automatiquement. Il reste accessible depuis les menus, section Préférences, via /usr/share/applications/locales-reconfiguration.desktop.
Avant une reconstruction d'image ISO
/!\ À ajouter au script dans le workflow Git /!\ : Le script de nettoyage pré-snapshot restaurera le fichier /etc/xdg/autostart/locales-reconfiguration.desktop afin que le mécanisme soit intact pour le prochain utilisateur.
Préparer le squelette du script Python
L'on vérifie la présence des paquets nécessaires : $ apt policy python3-gi python3-gi-cairo gir1.2-gtk-3.0. Cela doit retourner installé, candidat, avec les numéros de versions.