Xdialog, ventanas en scripts

Imagen de joseluis
0 puntos

En este remedo de artículo (por llamarlo de alguna forma) intentaré hacer un esbozo de lo que se puede hacer con la herramienta Xdialog.

A través de Xdialog se puede conseguir introducir ventanas (o diálogos) en un shell-script para hacer más "amigable" la interacción con el usuario.

En Ubuntu viene instalado por defecto la aplicación Zenity, que sirve para lo mismo que Xdialog pero tiene menos opciones, si alguien tiene interés en utilizar Zenity mejor que lea el artículo de Milmazz Zenity, mejorando la presencia de tus scripts. Además Xdialog es bastante compatible con dialog la aplicación de diálogos en modo texto (utiliza las librerías curses para mostrar los diálogos), por lo que un script con Xdialog se podría adaptar facilmente para tenerlo preparado para ejecutarlo en modo texto mediante dialog.

¿Qué necesitamos para hacer algo con Xdialog?

  • Conocimientos de shell-scripts
  • Obviamente tener instalado xdialog (y si no se tiene se soluciona facilmente con un sudo apt-get install xdialog)
  • Editor de texto: vi(m), emacs, joe, gedit, kate, scite o el que más nos guste.

Pero, antes de seguir, quizás sería conveniente responder a la pregunta...

¿Qué es Xdialog?

Xdialog es una aplicación que lanza ventanas o diálogos que se pueden incluir dentro de un shell-script en lugar de los tradicionales comandos para mostrar información (echo) o recoger variables (read).

Es decir si tenemos un script que le pide el nombre al usuario, en lugar de lanzar el típico read nombre se podrá lanzar Xdialog con los parámetros apropiados para que nos muestre una ventanita donde podamos escribir el nombre solicitado.

Primeros ejemplos

Vamos a ejecutar ahora unos ejemplos sencillos para ver como se muestran estos diálogos.

Ejecutar en un terminal lo siguiente:

Xdialog --title "Mi primer Xdialog" --msgbox "Hola mundo" 0 0

Otra forma similar a la anterior pero poniendo duración al mensaje:

Xdialog --title "Mi primer Xdialog con caducidad" \
  --infobox "Hola mundo. \nEste mensaje desaparecerá en 5000 milisegundos" 0 0 5000

Si lo que queremos es un poco de interacción, por ejemplo haciendo una pregunta que se responda con un "Sí/No" podemos ejecutar:

Xdialog --title "Un Xdialog con pregunta" \
  --yesno "¿Quieres continuar con la charla?" 0 0

Antes de seguir vamos a echar un vistazo a los comandos anteriores
En todos ellos hay un parámetro que se llama --title al que le sigue siempre un texto entrecomillado.
Como parece lógico suponer mediante ese parámetro fijamos el título de la ventana que va a mostrar Xdialog

También en todos los comandos que llevamos hasta ahora hay un par de ceros.
Estos números indican el tamaño de la ventana que vamos a mostrar, al poner 0 en los dos lo único que se le dice a Xdialog es que ajuste automáticamente el tamaño teniendo en cuenta lo que tiene que mostrar.

El resto de parámetros que le pasamos a Xdialog va en función del tipo de ventana que queremos mostrar:

  • msgbox -> muestra un mensaje hasta que cerramos la ventana
  • infobox -> muestra un mensaje hasta que cerramos la ventana o se cumpla el tiempo máximo que se le ha puesto (en milisegundos). En el ejemplo el tiempo es el 5000 que aparece al final
  • yesno -> muestra un mensaje y dos botones, uno para la opción Yes y otro para la opción No, según pulsemos a un botón o a otro devolverá la opción elegida.
  • ...

Recoger el resultado de Xdialog
Dependiendo del tipo de ventana podremos encontrar el resultado en la variable especial $? o bien en la salida estándar de errores.

- Un ejemplo del primer caso:

Xdialog --title "Un Xdialog con pregunta" \
   --yesno "¿Quieres continuar con la charla?" 0 0

resultado=$?
  • Si resultado contiene un 0 => Ha pulsado el botón SI
  • Si resultado contiene un 1 => Ha pulsado el botón NO
  • Si resultado contiene un 255 => Ha pulsado la tecla ESC

- Un ejemplo del segundo caso:

Xdialog --title "Titulo" --combobox "Selección de un valor" \
   0 0 "Valor 1" "Valor 2" "Valor 3" "Valor 4" "Valor 5" 2>/tmp/xdialog.tmp

resultado=`cat /tmp/xdialog.tmp`

Es decir redirigimos la salida estándar de errores (stderr) a un fichero y posteriormente cargamos el fichero en una variable

Opciones de Xdialog

Vamos a ver ahora más opciones de ejecución para el Xdialog.

Pedir un campo (el equivalente al read variable):

Xdialog --title "Titulo de la ventana" --inputbox "Introduce tu nombre" 0 0

Igual que antes pero sin botón de Cancelar:

Xdialog --title "Titulo de la ventana" --no-cancel --inputbox "Introduce tu nombre" 0 0

O si queremos que aparezca un valor inicial:

Xdialog --title "Titulo de la ventana" --inputbox \
   "Introducir el nombre que quieres dar a tu máquina" 0 0 "localhost"

O si queremos ocultar el valor introducido (verificarlo, ver como quitar el check de ocultar tipado)

Xdialog --title "Titulo de la ventana" --password --inputbox "Introduce tu password" 0 0

Podemos pedir en la misma ventana dos y hasta tres campos sin más que utilizar la opción --2inputsbox o --3inputsbox:

Xdialog --title "Titulo de la ventana" --password --password \
      --3inputsbox "Datos del usuario" 0 0 "Usuario" "" \
           "Password" "" "Repite la Password" ""

Elegir un valor de un campo seleccionable:

Xdialog --title "Titulo de la ventana" --combobox "Nivel de estudios" 0 0 \
    "Primaria" "Secundaria" "Bachillerato" "Universitario" "Postgrado"

Elegir un valor de una lista:

Xdialog --title "Titulo de la ventana" --menubox "Nivel de estudios" 0 0 0 \
            "primaria" "Primaria" "secundaria" "Secundaria" \
            "bachillerato" "Bachillerato" "universitario" "Universitario" \
            "postgrado" "Postgrado"

El tercer cero se refiere a la altura del menú, igualmente poniendo 0 le dejamos a Xdialog que lo ajuste automáticamente.

Elegir un valor de un rango numérico (corriendo una barra horizontal):

Xdialog --title "Titulo de la ventana" --rangebox "¿Qué nota le das a esta charla" 0 0 1 10 2

En el ejemplo se muestra una barra en el que el extremo inferior es 1 y el superior es 10. El valor inicial es 2.

Elegir un valor de un rango numérico (aumentando/disminuyendo los números) (revisar):

Xdialog --title "Titulo de la ventana" --spinbox "¿Qué nota le das a esta charla" 0 0 1 10 2 "Nota"

De forma similar a la opción inputbox, existen también --2rangesbox, --3rangesbox, --2spinsbox y --3spinsbox.

Mostrar el contenido de un fichero

Xdialog --title "Titulo de la ventana" --textbox ${HOME}/.bashrc 0 0

Editar el contenido de un fichero

Xdialog --title "Titulo de la ventana" --editbox ${HOME}/.bashrc 0 0

En este caso para que se guarden los cambios es preciso "capturarlos" de stderr y volcarlos en el fichero:

Xdialog --title "Titulo de la ventana" --editbox ${HOME}/.bashrc 0 0 2>/tmp/bashrc
cp /tmp/bashrc ${HOME}/.bashrc

Mostrar un fichero al que están continuamente añadiendo líneas al final (por ejemplo un log) al estilo de tail -f:

Xdialog --title "Titulo de la ventana" --tailbox ${HOME}/mifichero.log 0 0

Para probar lo anterior podemos hacer lo siguiente:

touch ${HOME}/mifichero.log
Xdialog --title "Titulo de la ventana" --tailbox ${HOME}/mifichero.log 0 0 &
echo "Esta linea debe salir en la ventana del Xdialog" >> ${HOME}/mifichero.log

Hemos lanzado Xdialog en background (el & del final) para poder liberar el terminal y poder añadir una línea al fichero mientras la ventana del Xdialog sigue abierta. Otra opción hubiera sido lanzar el Xdialog (sin el &) en un terminal y el echo en otro.

Ver un log de systema:

Xdialog --title "Titulo de la ventana" --logbox /var/log/syslog 0 0

Chequear una opción (o más de una) entre varias posibilidades:

Xdialog --title "Titulo de la ventana" --checklist \
                  "¿Qué distribuciones de GNU/Linux usas?" 0 0 0 \
                  "Debian" "Mamá Debian" "off" \
                  "Ubuntu" "Ubuntu por supuesto" "on" \
                  "Fedora" "Fedora también existe" "off" \
                  "Ninguna" "No uso GNU/Linux" "unavailable"

Devuelve las opciones separadas por el carácter /
Es decir si ha marcado Debian y Ubuntu devolverá:
Debian/Ubuntu

Chequear una opción entre varias:

Xdialog --title "Titulo de la ventana" --radiolist \
                  "¿Qué distribuciones de GNU/Linux usas?" 0 0 0 \
                  "Debian" "Mamá Debian" "off" \
                  "Ubuntu" "Ubuntu por supuesto" "on" \
                  "Fedora" "Fedora también existe" "off" \
                  "Ninguna" "No uso GNU/Linux" "unavailable"

Seleccionar un fichero

Xdialog --title "Titulo de la ventana" --fselect ${HOME} 0 0

Devuelve el nombre completo (ruta incluida) del fichero seleccionado

Seleccionar un directorio

Xdialog --title "Titulo de la ventana" --dselect ${HOME} 0 0

Mostrar un calendario para marcar un día:

Xdialog --title "Titulo de la ventana" --calendar "Calendario" 0 0 28 11 2007

Selecciona la hora (muestra la hora actual)

Xdialog --title "Titulo" --timebox "Selecciona la hora" 0 0

Elegir varias opciones "moviendo" de una ventana a otra:

Xdialog --title "Titulo de la ventana" --buildlist "Distribuciones que uso" \
            0 0 0 "ubuntu" "Ubuntu" "on" "fedora" "Fedora" "off" \
                  "debian" "Debian" "on" "mandriva" "Mandriva" "off"

El resultado lo devuelve de forma similar al checklist, así si ha elegido Fedora y Mandriva devolverá:
fedora/mandriva

Mostrar un árbol

Xdialog --title "Titulo de la ventana" --treeview \
           "Distribuciones según sistema de paquetes" 0 0 0 \
            "Deb" "Paquetes deb" "off" 1 \
              "Debian" "Distribución Debian" "off" 2 \
              "Ubuntu" "Distribución Ubuntu" "off" 2 \
            "Rpm" "Paquetes rpm" "off" 1 \
              "Fedora" "Distribución Fedora" "off" 2 \
              "Mandriva" "Distribución Mandriva" "off" 2

Ejecutando

Xdialog --help

Obtenemos una lista completa de las opciones de Xdialog.

Ejemplo de uso en un shell-script

#!/bin/bashDIR_CONTACTOS=${HOME}/cutre-contactos

DIR_TMP=${DIR_CONTACTOS}/tmp

function nuevoContacto () {

    Xdialog --title "Nuevo contacto" --3inputsbox "Nombre del contacto" 0 0 \
               "Nombre corto" "${nb_corto}" "Nombre completo" "${nb_completo}" \
               "Email" "${email}" 2>${HOME}/cutre-contactos/tmp/nuevo.txt
    ret=$?

    if [ $ret != 0 ]; then
       nuevoContacto
    fi

    nb_corto=`cat ${DIR_TMP}/nuevo.txt | cut -d "/" -f 1`
    nb_completo=`cat ${DIR_TMP}/nuevo.txt | cut -d "/" -f 2`
    email=`cat ${DIR_TMP}/nuevo.txt | cut -d "/" -f 3`

    if [ "${nb_corto}" = "" -o "${nb_completo}" = "" -o "${email}" = "" ]; then
       nuevoContacto
    fi

    if [ -d ${DIR_CONTACTOS}/${nb_corto} ]; then
        Xdialog --title "Contacto ya existe" --msgbox \
            "El contacto ${nb_corto} ya existe" 0 0
        return
    fi

    mkdir ${DIR_CONTACTOS}/${nb_corto}
    echo ${nb_completo} > ${DIR_CONTACTOS}/${nb_corto}/nombre
    echo ${email}  > ${DIR_CONTACTOS}/${nb_corto}/email

}

function borrarContacto() {
   Xdialog --title "Borrar contacto" --infobox "No implementado" 0 0 5000
}

function modificarContacto() {
   Xdialog --title "Modificar contacto" --infobox "No implementado" 0 0 5000
}

function buscarContacto() {
   Xdialog --title "Buscar contacto" --inputbox "Buscar contacto" \
            0 0 "${nb_corto}" 2>${DIR_TMP}/buscar.txt
   if [ $? = 0 ]; then
      nb_corto=`cat ${DIR_TMP}/buscar.txt`
      if [ "${nb_corto}" != "" ]; then
         if [ ! -d ${DIR_CONTACTOS}/${nb_corto} ]; then
            Xdialog --title "Contacto no existe" --msgbox \
                 "El contacto ${nb_corto} no existe" 0 0
            return
         else
            nb_completo=`cat ${DIR_CONTACTOS}/${nb_corto}/nombre`
            email=`cat ${DIR_CONTACTOS}/${nb_corto}/email`
            Xdialog --title "Datos del contacto" --msgbox \
               "Contacto: ${nb_corto}\nNombre: ${nb_completo}\nEmail: ${email}\n" 0 0
         fi
      else
         return
      fi
   fi
}

#Crea en nuestro home los directorios que necesita
mkdir -p ${DIR_TMP} 2>/dev/null

while true ; do
 nb_corto=""
 nb_completo=""
 email=""

 Xdialog --title "Cutre-Contactos" --menubox "Acción a realizar" \
                   0 0 0 "nuevo" "Nuevo Contacto" "borrar" "Borrar Contacto" \
                         "modificar" "Modificar Contacto" \
                         "buscar" "Buscar Contacto" \
                         "salir" "Salir" 2>${DIR_TMP}/accion.txt
 retorno=$?
 if [ $retorno != 0 ]; then
       exit
 fi
 accion=`cat ${DIR_TMP}/accion.txt`
 case $accion in
  nuevo)
     nuevoContacto
   ;;
  borrar)
     borrarContacto
   ;;
  modificar)
        modificarContacto
   ;;
  buscar)
     buscarContacto
   ;;
  *)
     exit 1
   ;;
 esac

done

Referencias

Documentación de Xdialog

Extraido de aquí.