Intéressé par des cours d'informatique en ligne ?
Visitez mon nouveau site https://www.yesik.it !

Zenity.jpg

Zenity — Zenity est une dépendance de nombreux paquets. A l'occasion vous verrez peut-être apparaître son nom lors de l'installation d'un logiciel.

Quand on installe un paquet avec le gestionnaire de paquets apt(8), celui-ci indique la liste des dépendances nécessaires. Or, l'examen de cette liste est parfois l'occasion de découvrir un paquet mystère. Un de ceux dont le nom ne vous dit rien – mais qui vous intrigue au point de vouloir en savoir plus. C'est ainsi que j'ai découvert Zenity.

Après une rapide recherche, une partie du voile est levée: en deux mots, Zenity permet d'afficher des boîtes de dialogues Gtk+ à partir de la ligne de commande ou de scripts shell [1]. Voici qui mérite de s'y attarder quelques minutes...


Remarque:

Quitte à faire mon bigot, un petit mot d'avertissement. Comme souvent, ça n'est pas parce que c'est possible qu'il faut forcément le faire.

Une partie de la philosophie Unix réside dans la possibilité de combiner des programmes pour effectuer des tâches complexes sans nécessairement requérir une action (ou la simple présence) de l'utilisateur. Ce qui s'oppose à un autre système d'exploitation répandu qui ouvre des boîtes de dialogues pour un oui ou pour un non.

Utiliser Zenity pour ajouter une interface graphique à vos scripts shell, c'est un peu pactiser avec le diable. Ça peut être so cool – mais il ne faut sans doute pas en abuser!

Messages

sh$ zenity --info \
           --text "You are now using Zenity to display Gtk+ dialogs"
sh$ zenity --warning \
           --text "You are now using Zenity to display Gtk+ dialogs"
sh$ zenity --error \
           --text "You are now using Zenity to display Gtk+ dialogs"

L'utilisation la plus simple de Zenity est pour afficher un message à l'utilisateur. Ce type de dialogue permet d'afficher un texte sans offrir de choix à l'utilisateur autre que valider le message.

Zenity offre trois variantes de dialogue pour cette utilisation. Celles-ci se distinguent par l'icône associée et sont à choisir en fonction de l'importance (ou de la gravité) du message à afficher:

info
Pour rapporter une information à l'utilisateur.
warning
Pour signaler un avertissement. Traditionnellement, c'est une situation qui n'est pas commune, mais qui n'empêche pas de continuer l'exécution du programme.
error
Pour signaler une erreur. La situation rapportée empêchera certainement la poursuite normale des opérations.

Normalement, une boîte de dialogue de message ne devrait pas aiguiller d'une manière ou d'une autre le déroulement d'un programme. Malgré cela, Zenity permet de récupérer la manière dont la boîte de dialogue a été fermée. Si l'utilisateur a fermé celle-ci en cliquant sur le bouton de validation Ok, Zenity se termine avec pour résultat le code 0. Ce qui en terminologie shell signifie tout s'est bien passé. Cependant, l'utilisateur a aussi la possibilité de fermer cette boite de dialogue en cliquant sur la case de fermeture. Dans ce cas, Zenity renvoie le code 1. Comme avec tout programme, ces codes de retour permettent de combiner Zenity avec d'autres commandes du shell à l'aide des opérateurs && et || ou encore avec des structures de contrôle:

sh$ zenity --info --text "You are now using Zenity to display Gtk+ dialogs" \
     && echo Ok \
     || echo Cancel
sh$ if zenity --warning --text "Some files are missing."
    then
         echo "Never mind"
    fi


Question

Si les messages permettent de fournir une information à l'utilisateur, Zenity peut aussi être utilisé pour permettre à celui-ci de répondre à des questions:

sh$ zenity --question --text="File already exists.\nContinue?"

Comme je l'ai évoqué plus haut, Zenity communique avec son environnement grâce au code de retour. Ici encore, cliquer sur Ok termine Zenity avec le code 0. Cliquer sur Cancel ou sur la croix de fermeture de la fenêtre termine Zenity avec le code 1:

sh$ if zenity --question --text="File already exists.\nContinue?"
    then
        echo "Ok to proceed..."
    else
        echo "Abort."
    fi

Sélection de fichiers

Une tâche commune dans un programme doté d'une interface graphique est la sélection d'un fichier. Zenity offre cette possibilité avec le dialogue --file-selection. Celui-ci propose plusieurs variantes et options, parmi lesquelles:

# Choisir un fichier existant
sh$ zenity --file-selection
# Choisir un dossier
sh$ zenity --file-selection --directory
# Choisir un nouveau nom de fichier
sh$ zenity --file-selection --save

Comme toujours, cliquer sur Ok termine Zenity avec le code de retour 0. Annuler le termine avec le code 1. La documentation de Zenity rapporte également que le code -1 peut être renvoyé en cas d'erreur.

Quand à la sélection effectuée par l'utilisateur, celle-ci est simplement écrite sur la sortie standard. Il est donc possible d'utiliser les mécanismes de redirection ou de capture du shell pour traiter le choix de l'utilisateur. Par exemple:

sh$ FILE=`zenity --file-selection` && cat "$FILE"

Date

Très pratique aussi, Zenity offre un dialogue de sélection de date:

sh$ zenity --calendar \
           --text "Select a date" \
           --date-format "%d/%m/%Y"
23/11/2010

L'option --date-format permet de spécifier le format de la date renvoyée. Celui-ci est exprimé sur une forme compatible avec celles acceptées par la fonction strftime.

Comme pour la sélection de fichiers, le choix de l'utilisateur est récupéré sur la sortie standard. Par exemple, si vous voulez une interface conviviale pour filtrer le contenu de /var/log/syslog vous pourriez utiliser Zenity ainsi:

sh$ DATE=`zenity --calendar \
                    --text "Select a date" \
                    --date-format "%b %e"` \
          && sudo cat /var/log/syslog | grep "^${DATE}"

Listes

Avec les listes, nous abordons sans doute le dialogue le plus complexe de Zenity. Celui-ci permet à l'utilisateur de choisir une ou plusieurs valeurs dans une liste. En fait de liste, il s'agit plutôt d'un tableau dans lequel l'utilisateur va pouvoir sélectionner une ou plusieurs lignes.

Le nombre de colonnes de ce tableau est déterminé par le nombre d'options --column présentes. Quand au nombre de lignes, il est déduit du nombre de colonnes et du nombre de valeurs à afficher. Celles-ci peuvent être fournies sur la ligne de commande – ou via l'entrée standard à raison d'une valeur par ligne. Ainsi les deux commandes ci-dessous affichent la même boîte de dialogue:

sh$ (
        echo apple
        echo red
        echo peer
        echo yellow
        echo grapes
        echo blue
    ) | zenity --list --column=fruit --column=color
sh$ zenity --list --column=fruit --column=color \
        apple red peer yellow grapes blue

Par défaut, Zenity envoie sur la sortie standard le contenu de la première colonne de la ligne sélectionnée.

Piège:

Lorsque le dialogue s'ouvre, aucune ligne n'est sélectionnée. Si l'utilisateur valide alors sans avoir sélectionné la moindre ligne, rien n'est envoyé sur la sortie standard. Vous devez donc prendre garde à gérer ce cas particulier:

FRUIT=`zenity --list --column=fruit --column=color apple red peer yellow grapes blue` && \
case "${FRUIT}" in                               
    "") echo "Don't you like fruits?"
    ;;
    *) echo "I like ${FRUIT} too!"
    ;;
esac

Enfin, il est aussi possible d'autoriser la sélection de plusieurs lignes avec l'option --checklist. Cette option permet une variante de la liste qui remplace la première colonne par des cases à cocher. Offrant par là même l'occasion à l'utilisateur de sélectionner plusieurs valeurs. Avec cette variante, le contenu en entrée des cellules de la première colonne doit être TRUE ou FALSE selon que vous souhaitez la case cochée par défaut ou pas. Dans ce cas, en sortie est renvoyé le contenu de la seconde colonne de chaque ligne sélectionnée. Et si plusieurs lignes sont cochées les différents résultats sont renvoyés séparés par un | (pipe):

sh$ zenity --list \
           --checklist \
           --text="What is you favorite pet?" \
           --column=Favorite --column=Pet \
           TRUE cat FALSE dog TRUE fish TRUE bird FALSE mouse
cat|fish|bird

Remarque:

Le séparateur par défaut peut être remplacé grâce à l'option --separator:

sh$ zenity --list \
           --checklist \
           --separator='*' \
           --text="What is you favorite pet?" \
           --column=Favorite --column=Pet \
           TRUE cat FALSE dog TRUE fish TRUE bird FALSE mouse
cat*fish*bird

Saisie de texte

Jusqu'à présent, nous avons permis à l'utilisateur de faire un choix parmi ceux proposés. Mais parfois il est souhaitable de permettre une saisie libre de texte. C'est ce que permet le dialogue --entry:

sh$ NAME=`zenity --entry --text "Please, enter your name:"`
sh$ if [ $? = 0 ]
    then
        echo "Hello ${NAME}"
    fi

Ce dialogue offre en plus deux options intéressantes:

--entry-text=DEFAULT_VALUE
Pour présenter un texte par défaut
--hide-text
Pour cacher le texte lors de la saisie (à la manière des champs password dans les formulaires web).

En ce qui concerne cette dernière option, ayez bien conscience qu'il ne s'agit que de dissimuler le texte aux yeux indiscrets lors de la saisie. Par contre, en mémoire le texte n'est pas crypté. Et c'est bien le texte en clair qui est renvoyé par Zenity sur la sortie standard!

Conclusion

Dans ce rapide tour d'horizon, je n'ai abordé que les fonctions de base proposées par Zenity. Je vous renvoie sur la documentation citée en référence pour plus de détails ou pour les options que j'ai passées sous silence. Par ailleurs, Zenity propose aussi une aide en ligne:

sh$ zenity --help

Pour avoir l'aide spécifique à un dialogue, vous pouvez aussi utiliser à la place l'option --help-DIALOG:

 --help-calendar             Show calendar options
 --help-entry                Show text entry options
 --help-error                Show error options
 --help-info                 Show info options
 --help-file-selection       Show file selection options
 --help-list                 Show list options
 --help-question             Show question options
 --help-warning              Show warning options

Ceci dit, Zenity n'a certainement pas la prétention de fournir toutes les subtilités de la programmation d'interfaces graphiques pour le shell! Et les dialogues proposés restent très simples. Comme vous l'avez constaté, il s'agit plutôt de fournir les quelques dialogues de base les plus utiles. Et je rappellerais aussi l'avertissement que j'avais fait en tout début: il n'est pas dans l'esprit Unix d'avoir des utilitaires qui interagissent avec l'utilisateur à l'aide de boîtes de dialogues. Malgré tout, Zenity peut avoir son utilité lors de l'écriture de scripts pour des utilisateurs finaux plus habitués à l'interface graphique qu'à la ligne de commande.

Ressources