Zenity, diálogos para GNOME , Cinnamon, MATE…

Este es uno de los capítulos del tutorial Diálogos para scripts. Encontrarás los enlaces a todos los de capítulos, al final de este artículo.

Si en el capítulo anterior, te mostré una opción para crear cuadros de diálogo que se integraban perfectamente con el entorno de escritorio KDE, en este caso tienes una opción que se integra perfectamente con GNOME, Mate, Cinnamon, etc. Esta herramienta es zenity y utiliza la librería GTK para estos menesteres. De nuevo con esta herramienta puedes crear diálogos para tus scripts, que en este caso se integrarán perfectamente con los entornos de escritorio mencionados anteriormente. Así, aunque he titulado este capítulo del tutorial como diálogos para GNOME, lo cierto es que zenity no se circunscribe únicamente a este entorno de escritorio, sino que es válido para cualquier otro, sin embargo, se integra mejor con los escritorios basados en GTK.

Diálogos para GNOME con zenity

Diálogos para GNOME con zenity

Zenity

Zenity es una revisión de gdialog que a su vez es la implementación de GNOME de dialog, que te permite crear diálogos desde la línea de comandos para tus scripts realizados en Bash, o en cualquier otro shell que utilices.

Como con las otras herramientas que hemos visto en los distintos capítulos del tutorial, Zenity, te va a permitir crear diferentes tipos de diálogos mas o menos simples. Diálogos simples que te van a permitir interactuar de forma gráfica con el usuario.

Instalación de Zenity

Lo primero y principal, antes de ponerte a dotar a tus scripts en Bash de una interfaz gráfica con Zenity, es por supuesto instalarlo. Indicarte que esta herramienta se encuentra en los repositorios oficiales de Ubuntu, y de la mayoría de distribuciones. En este sentido, su instalación es tan sencilla como ejecutar la siguiente instrucción en el caso de que te encuentres en Debian, Ubuntu, Linux Mint, etc,

sudo apt install zenity

En el caso de que te encuentres en RedHat o CentOs, la instalación de Zenity, la puedes realizar ejecutando la siguiente instrucción,

sudo yum install zenity

Un diálogo sencillo

Al igual que hemos hecho con el resto de herramientas, te voy a mostrar todas las posibilidades de Zenity con diferentes ejemplos. Esto te va a permitir que te hagas una idea de las posibilidades de esta herramienta, y por otro lado te permitirá ver como integrarlo con tus propios scripts.

Por supuesto que al tratarse de un la implementación de GNOME de dialog su uso es muy similar, tal y como puedes ver ya desde el primer ejemplo que te muestro. Aunque presenta algunas modificaciones, tal y como el título, y algunos otros detalles.

zenity --info \
       --title="https://www.atareao.es" \
       --width=250 \
       --text="Este es el mensaje que se muestra"
Un diálogo para mostrar información

Indicarte que tanto los parámetros --title como --width son totalmente opcionales. Sin embargo, he preferido incluirlos en este primer ejemplo, para que veas como utilizarlos.

Por otro lado, además de --info que es el que te muestra el icono de información también puedes utilizar --warning y --error, que te muestran cuadros de diálogo de aviso y de error. Básicamente se trata del mismo cuadro de diálogo, pero donde cambia el icono de información por uno de aviso o de error, respectivamente. Así, por ejemplo, el de error tendría un aspecto como el que puedes ver a continuación,

zenity --error \
       --title="https://www.atareao.es" \
       --width=250 \
       --text="Este es el <b>mensaje</b> que se muestra"
Un diálogo para mostrar informacion con formateo de texto

Si te fijas en el texto del cuadro de diálogo, la palabra mensaje va entre etiquetas, como si fuera html. Lo cierto es que los cuadros de diálogo de Zenity, admiten algo similar, que se conoce como lenguaje de marcado Pango que tiene una sintaxis muy similar. Así, por ejemplo, b es para texto en negrita, i es para cursiva, tt para utilizar una fuente mono espacio y mas. No solo esto, sino que también puedes llamar la atención del usuario cambiando el color del texto, e incluso el fondo del texto.

En cualquier caso te recomiendo que visites la página de GNOME donde habla del lenguaje de marcado Pango, y encontrarás referencia a todo lo que indico anterirmente y mucho mas.

Preguntando al usuario

Si además de informar al usuario de un evento, quieres ir un paso mas allá y preguntar al usuario para que tome una decisión, puedes utilizar el diálogo --question, tal y como ves en el siguiente ejemplo,

zenity --question \
       --title="https://www.atareao.es" \
       --width=250 \
       --text="¿Quieres continuar?"
ans=$?
if [ $ans -eq 0 ]
then
    echo "Si que quiere continuar"
else
    echo "No quiere continuar"
fi
Un diálogo para preguntar al usuario

De nuevo, tienes que fijarte en que en caso de que el resultado sea 0 indica que ha pulsado el botón Si y en otro caso, habrá pulsado el botón No.

En este caso, puedes personalizar los botones ok y cancel añadiendo las correspondientes etiquetas, y también tienes otras opciones para no utilizar Pango. Así, por ejemplo, puedes personalizar el diálogo de la siguiente manera,

texto="¿<span weight=\"bold\" foreground=\"green\">Seguro</span> que quieres?"
zenity --question \
       --title="https://www.atareao.es" \
       --width=250 \
       --ok-label="Continuar" \
       --cancel-label="Abandonar" \
       --text="${texto}"
ans=$?
if [ $ans -eq 0 ]
then
    echo "Si que quiere continuar"
else
    echo "No quiere continuar"
fi
Un diálogo para preguntar al usuario pero con estilo con Zenity

Pidiendo información al usuario

El siguiente paso es preguntar al usuario por su nombre, o por cualquier otro dato que tenga que introducir. El funcionamiento de este cuadro de diálogo es similar al que has podido ver en otros capítulos del tutorial. En este sentido, si el resultado es distinto de 0 el usuario no quiere decirnos su nombre. Mientras que si el resultado es igual a 0 entonces la variable contendrá el contenido del campo. Por ejemplo,

nombre=$(zenity --entry \
                --title="https://www.atareao.es" \
                --width=250 \
                --ok-label="Aceptar" \
                --cancel-label="No te lo quiero decir" \
                --text="¿Cual es tu nombre?")
ans=$?
if [ $ans -eq 0 ]
then
    echo "Su nombre es: ${nombre}"
else
    echo "No me quiere decir su nombre"
fi
Un diálogo para preguntar un dato

Por supuesto, y como no podía ser de otra manera, también tienes el correspondiente diálogo para facilitar al usuario que introduzca una contraseña. Aquí tienes un ejemplo,

password=$(zenity --password \
                  --title="https://www.atareao.es" \
                  --width=250 \
                  --ok-label="Aceptar" \
                  --cancel-label="No te la quiero decir" \
                  --text="Introduce la contraseña:")
ans=$?
if [ $ans -eq 0 ]
then
    echo "Tu contraseña es: ${password}"
else
    echo "No me quiere decir su contraseña"
fi
Un diálogo para preguntar una contraseña

Elegir entre diferentes opciones

Otra cuestión interesante es pedir al usuario que elija entre diferentes opciones. En este caso, al igual que con otras herramientas del tutorial, también puedes definir si el usuario solo puede elegir una o varias de las opciones que le ofreces.

componente=$(zenity --list \
                    --title="https://www.atareao.es" \
                    --height=200 \
                    --width=100 \
                    --ok-label="Aceptar" \
                    --cancel-label="Cancelar" \
                    --text="Selecciona un componente para tu pizza:" \
                    --radiolist \
                    --column="" \
                    --column="Componente" \
                    1 "Jamón" 2 "Queso" 3 "Huevo")
ans=$?
if [ $ans -eq 0 ]
then
    echo "Has elegido: ${componente}"
else
    echo "No has elegido ningún componente"
fi
Un diálogo para preguntar al usuario que elija una opción de varias con Zenity

Si en lugar de utilizar --radiolist utilizas --checklist podrás elegir varias opciones de forma simultánea. Lo que has elegido lo recogerás en la variable separados por | por defecto, o por otro carácter si lo defines. Un ejemplo,

componente=$(zenity --list \
                    --title="https://www.atareao.es" \
                    --height=200 \
                    --width=100 \
                    --ok-label="Aceptar" \
                    --cancel-label="Cancelar" \
                    --text="Selecciona un componente para tu pizza:" \
                    --checklist \
                    --column="" \
                    --column="Componente" \
                    --column="Calorías" \
                    1 "Jamón" 100 2 "Queso" 150 3 "Huevo" 125)
ans=$?
if [ $ans -eq 0 ]
then
    echo "Has elegido: ${componente}"
else
    echo "No has elegido ningún componente"
fi
Un diálogo para que el usuario elija en base a información

Indicarte que además en este segundo ejemplo, he añadido una columna adicional, para que tengas información sobre las calorías del producto. Eso si, no te dejes guiar por estos valores, porque los he puesto completamente al azar. Cualquier parecido con la realidad es pura coincidencia.

Respecto a los valores que devuelve, indicarte que por defecto devuelve los de la primera columna. En el ejemplo que te he puesto, te devolvería Jamón, o Queso, o incluso en el caso de que seleccionaras los dos, te devolvería Jamón|Queso. Pero, puedes elegir la columna que tu quieras utilizando la opción --print-column, de forma que si seleccionas la opción ALL te devolverá todas las columnas.

¿Como seleccionar archivos?

Otra interesante utilidad que le puedes dar a esta herramienta, es para seleccionar archivos y directorios. Para el caso de archivos, y utilizando el modo de abrir o seleccionar, tienes algunas opciones interesantes, como son,

  • --multiple que te permite seleccionar varios archivos de forma simultánea
  • --file-filter con el que puedes definir un patrón de filtrado, tal y como te muestro en el ejemplo a continuación.
  • --save para el caso de que lo quieras mostrar sea el típico diálogo de Guardar como.
  • --confirm-overwrite para confirmar en el caso de que el archivo ya exista.
archivo=$(zenity --file-selection \
                 --title="https://www.atareao.es" \
                 --height=200 \
                 --width=100 \
                 --text="Selecciona un archivo:" \
                 --file-filter="scripts | *.sh")
ans=$?
if [ $ans -eq 0 ]
then
    echo "Has elegido este archivo: ${archivo}"
else
    echo "No has elegido ningún archivo"
fi
Un diálogo para que el usuario seleccione un archivo

Por otro lado, si lo que quieres es seleccionar un directorio, tienes que utilizar la opción --directory tal y como te muestro en el siguiente ejemplo,

directorio=$(zenity --file-selection \
                    --title="https://www.atareao.es" \
                    --height=200 \
                    --width=100 \
                    --text="Selecciona un directorio:" \
                    --directory)
ans=$?
if [ $ans -eq 0 ]
then
    echo "Has elegido este directorio: ${directorio}"
else
    echo "No has elegido ningún directorio"
fi
Un diálogo para que el usuario seleccione un directorio con Zenity

Decirte que en el caso de que selecciones un archivo, realmente estás seleccionando el directorio que contiene el archivo. Pienso, y es una opinión personal, que no se deberían mostrar archivos, sino solo directorios.

Elegir colores

Como no todo en esta vida consiste en introducir datos o seleccionar entre diferentes opciones, zenity también te ofrece otros cuadros de diálogos alternativos. En este caso, tienes el de seleccionar color, como el que te muestro en el siguiente ejemplo,

color=$(zenity --color-selection \
               --title="https://www.atareao.es" \
               --height=200 \
               --width=100 \
               --text="Selecciona un color:")
ans=$?
if [ $ans -eq 0 ]
then
    echo "Has elegido este color: ${color}"
else
    echo "No has elegido ningún color"
fi
Un diálogo para seleccionar un color

Si lo que quieres es mostrar la paleta de colores, en ese caso tienes que utilizar la opción --show-palette, y el resultado será similar al que ves en la siguiente captura de pantalla.

Un diálogo para seleccionar un color de una paleta de colores

Mostrando el progreso de tus trabajos

Por supuesto que Zenity también tiene su cuadro de diálogo para mostrar progreso, sin embargo, en este punto te tengo que decir, que el de kdialog me resulta mucho, pero que mucho mas interesante y currado que este… Habría que buscar una solución para el caso de diálogos con GNOME, y otros derivados, y conseguir una mejor integración.

Así, para mostrar el progreso, puedes hacer algo similar a lo que te muestro a continuación. El inconveniente de esto, es que los porcentajes los estimas tu, con lo que el usuario puede terminar bastante desorientado.

(
sleep 1
echo "10"
echo "# Paso 1"; sleep 1
echo "20"
echo "# Paso 2"; sleep 1
echo "30"
echo "# Paso 3"; sleep 1
echo "50"
echo "# Paso 4"; sleep 1
echo "70"
echo "# Paso 5"; sleep 1
echo "90"
echo "# Terminado"
echo "100"
) |
zenity --progress \
  --title="https://www.atareao.es" \
  --text="Iniciando el proceso" \
  --percentage=0

if [ "$?" = -1 ] ; then
        zenity --error \
          --text="Update canceled."
fi
Un diálogo para una barra de progreso con Zenity

Seleccionando números enteros

Existen diferentes opciones para que un usuario introduzca un número entero, empezando por utilizar una caja de texto. Sin embargo, el problema de esto, es que posteriormente, necesitas comprobar, si el valor introducido es un número, y no solo esto, sino que está entre los valores permitidos. Me refiero, por ejemplo, al caso, que preguntes al usuario que introduzca un número de 1 a 10.

En el caso de Zenity, tienes un cuadro de diálogo que se adecua precisamente a esto. Te permite que el usuario pueda introducir un número entero entre dos valores concretos. Se trata de --scale. Así, en el caso que te acabo de comentar, podrías utilizar el siguiente ejemplo,

numero=$(zenity --scale \
                --title="https://www.atareao.es" \
                --text="Elige un numero de 1 a 10" \
                --min-value=1 \
                --max-value=10 \
                --value=3)
ans=$?
if [ $ans -eq 0 ]
then
    echo "Has elegido este numero: ${numero}"
else
    echo "No has elegido ningún numero"
fi
Un diálogo para seleccionar un número

Preguntando al usuario por una fecha

Algo con lo que me suelo pelear son con las fechas. Realmente es algo que siempre me ha resultado problemático. Empezando por los formatos y terminando por las zonas horarias. Es algo que siempre me suele dar problemas. Por supuesto, si pones las cosas mas o menos sencillas todo suele ir algo mejor. Así, si utilizas un diálogo como --calendar esto te resultará algo mas sencillo. Así, por ejemplo, para preguntar una fecha al usuario, puedes utilizar algo como lo que te muestro a continuación,

fecha=$(zenity --calendar \
               --title="https://www.atareao.es" \
               --text="Elige una fecha")
ans=$?
if [ $ans -eq 0 ]
then
    echo "Has elegido este fecha: ${fecha}"
else
    echo "No has elegido ninguna fecha"
fi
Un diálogo para elegir una fecha

Formularios con Zenity

Por último, y para terminar este capítulo del tutorial, los formularios. Esta es una opción que no está disponible en todos las herramientas que hemos visto y que veremos en los próximos capítulos. Sin embargo, creo que es una opción, no solo necesaria, sino imprescindible. Y digo que es imprescindible, porque me resulta, un tanto infumable para un usuario, tener que introducir diferentes datos en diferentes cuadros de diálogo, cuando se podría introducir todo en uno. Es mas, creo que, mostrar muchos diálogos, puede llevar al usuario a abandonar la aplicación.

Así, como ejemplo, te muestro un cuadro de diálogo para preguntar a un usuario por sus datos personales, y como extraerlos posteriormente, en el caso de que el usuario pulse el botón de Aceptar,

datos=$(zenity --forms \
               --title="https://www.atareao.es" \
               --text="Introduce los siguientes datos" \
               --add-entry="Nombre" \
               --add-entry="Apellido" \
               --add-password="Contraseña" \
               --add-calendar="Fecha de nacimiento")
ans=$?
if [ $ans -eq 0 ]
then
    echo "Has introducido los siguientes datos:"
    IFS="|" read -r -a array <<< "$datos"
    echo Nombre: "${array[0]}"
    echo Apellido: "${array[1]}"
    echo Contraseña: "${array[2]}"
    echo Fecha de nacimiento: "${array[3]}"
else
    echo "Has cancelando"
fi
Un diálogo para crear un calendario con Zenity

Conclusión

Como ves, y tal y como te he indicado en el artículo, Zenity, intenta seguir el comportamiento de su antecesor dialog, y es realmente sencillo de utilizar. Por supuesto, se integra perfectamente con el entorno de escritorio GNOME y con otros entornos de escritorio derivados, como puede ser Cinnamon o MATE.

De todas las opciones que ofrece Zenity, probablemente la que mas me ha llamado la atención es la posibilidad de hacer formularios, y la que mas me ha defraudado es la barra de progreso. En este sentido, la barrad de progreso de kdialog va a la cabeza de todas estas herramientas, al menos desde mi punto de vista, claro.


Imagen de portada de Med Badr Chemmaoui en Unsplash

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *