YAD: Yet Another Dialog Program


by Daniel Meiß-Wilhelm (leiche)

What is it?

If you search in our repositories, you will find it under Development/Tools. The description follows:

Display graphical dialogs from shell scripts or command line. Yad is a fork of Zenity with many improvements, such as custom buttons, additional dialogs, popup menu in notification icon and more.

CLI usage example:

yad --image=dialog-question --text='how are you?'

When you now open a terminal and type

yad --image=dialog-question --text='how are you?’

you will see this:

Now you can see it is a dialog for bash, or command line interface.

What can we do with it?

I’m sure it will help us to make some commands easier to handle.

Some samples are sleeptimer, alert_clock, update-notifier, the latest version of screenie, and some more, not forgetting repair-database from glamdring.

I will pick alert_clock to show how it works.

If you have installed alert_clock, you get the following main window:

I know we all read the magazine, and know the articles of the Command Line Interface article series, by Peter Kelly (critter), that ran in The PCLinuxOS Magazine in 2009 and 2010, so we can start directly with yad.

One thing, typing yad --help in a terminal/console gives a lot of information about using yad.

Here we go...

At first we need some variables, and to define it for a first command. A script often begins like this:

#!/bin/bash

#

# Alarm clock for PCLinuxOS

#

# Don't miss important times and events. Turn your computer

# into the perfect wake up system. Set the alarm and get the

# Pizza out of the oven in perfect time.

#

# Author: D.M-Wilhelm (Leiche)

# Email: meisssw01 at gmail.com

# Licence: GPL

# First build: May Wed 11 2011

# Last build: Jul Sun 10 2011

# fixed icon display in systray, move zenity,

# based now on yad.

#

Encoding=UTF-8

#

# i18n - Internationalization - Internationalisierung

#

export TEXTDOMAIN=alert_clock

export TEXTDOMAINDIR="/usr/share/locale"

#

# define some variables - Definierung einiger Variablen

#

TITLE=alert_clock

VERSION=0.33

ICON=/usr/share/icons/wecker.png

#

For now, we are only interested in the variables.

Why?

When we define this, we must not write all the lines in our script. We need only to change the variables. We change the version, as in the example, because we have to add new features. So we define it as

VERSION=0.33+

We can define it also as

YAD=$(yad --title=’alert_clock 0.33’ --window-icon=”/usr/share/icons/wecker.png”)

The main window of alert_clock looks as follows:

function menu {

COUNTDOWN=$(yad --entry --text $"Enter minutes...!" --title="$TITLE"" $VERSION" --window-icon=$ICON \

                        --image=$ICON \

                        --button=$"Change:2" \

                        --button=$"Test:3" \

                        --button="gtk-ok:0" \

                        --button="gtk-close:1" \

                   )

If you now add } in the bottom line, and write menu on the next line, you can run this main window.

Notice: the script must be executable: the simplest way is to right click on script properties > permissions > Make the file executable.

Tip: Install Geany from Synaptic, and generate a file for testing, to see how YAD works.

Save it as sample alert_test, make it executable, and run it with “F5”. Does the main window display? If not, you get messages in an xterminal listing what has gone wrong. In the following picture can you see that I have forgotten { in line 8, and get the messages:

./alert_test: line 15: syntax error near unexpected token `$'COUNTDOWN=$(yad --entry --text "Enter minutes...!" --title="$TITLE"" $VERSION" --window-icon=$ICON \t\t\t--image=$ICON \t\t\t--button="Change:2" \t\t\t--button="Test:3" \t\t\t--button="gtk-ok:0" \t\t\t--button="gtk-close:1" \t\t   )''
./alert_test: line 15: `                   )'


Notice: You will not see the icon wecker.png, if you not have installed alert_clock.

Tip: for localization you must set a $ by --text $“bla”. If it is not set, you get no translation for it.

I removed now $, and we get only the original description.

Now our main window is displayed, but two of four buttons are not working. Can you figure out which of our buttons are not working?

If you guessed that the Change and Test are not working, then you guessed correctly. We must give them a job (task).

At line 15 set your cursor after ), and press <enter> tab. Type the following in your script:

ret=$?

[[ $ret -eq 1 ]] && exit 0

#

#change sound - Sound ändern

#

if [[ $ret -eq 2 ]]; then

    CHANGE=$(yad --title="$TITLE"" $VERSION" --window-icon=$ICON \

                --file --width=600 --height=500 \

                --text=$"<b>Choose your own audio file as alert!</b>

________________________________________________")

                if [ -z "$CHANGE" ];then

                exec alert_clock

                exit 0

                else

                mkdir $HOME/.config/alert-clock

                rm -rf $HOME/.config/alert-clock/alert sleep 1

                ln -s "$CHANGE" $HOME/.config/alert-clock/alert

                yad --title $"$TITLE"" $VERSION" \

            --button="gtk-ok:0" \

            --width 300 \

            --window-icon=$ICON \

            --text=$"Your own sound is set!!"

                fi

menu                

fi

#

#Test sound - Klang testen

#

if [[ $ret -eq 3 ]]; then

        if [ -f $HOME/.config/alert-clock/alert ]; then

        SOUND="$HOME/.config/alert-clock/alert"

        else

        SOUND='/usr/share/alert_clock/alarm.ogg'

        fi

mplayer "$SOUND" | yad --title $"$TITLE"" $VERSION" \

                 --button="gtk-ok:0" \

                 --width 300 \

                 --window-icon=$ICON \

                 --text=$"Exit sound test!!"

killall mplayer

menu                

fi

Press “F5” tab, to run your script. Click on Test button, if you have installed alert_clock, you will now hear a sound output IF your mixer settings are correctly set. Follow the output from Geany:

Can't open joystick device /dev/input/js0: No such file or directory
Can't init input joystick
mplayer: could not connect to socket
mplayer: No such file or directory
Failed to open LIRC support. You will not be able to use your remote control.

MPlayer interrupted by signal 13 in module: play_audio
mplayer: no process found

If you have no sound or wrong file is loaded, you could see the following output messages:

Can't open joystick device /dev/input/js0: No such file or directory
Can't init input joystick
mplayer: could not connect to socket
mplayer: No such file or directory
Failed to open LIRC support. You will not be able to use your remote control.
Invalid seek to negative position ffffffffffffffff!
mplayer: no process found

To set your own alert sound, click on the Change button. After you change your sound, test it again, to hear if it is working well for you.

But how well does it work now, when I click on the Test or Change button?  

We defined the button as:

--button=$"Change:2" \

--button=$"Test:3" \

and was set here what it will do when we click a button.

ret=$?

So, now if we click on OK or Cancel, they behave the same, since they are the same function.

[[ $ret -eq 1 ]] && exit 0

#

#change sound - Sound ändern

#

if [[ $ret -eq 2 ]];

But our extra buttons have other functions, and this is they are designated as :2 or :3 or :5.

To test, remove :3 by --button=$"Test:3" \. If you now click on the Test button, your script will be closed without any error messages.

I find I must restart alert_clock with exec alert_clock. When we don’t change our audio, we can’t enter a time to set alert_clock in warning mode. This may be due to a bug in YAD.

With the line if [[ $ret -eq 2 ]];, we tell the application what to do when button=change:2 is clicked.

After ]]; comes the command.

then

    CHANGE=$(yad --title="$TITLE"" $VERSION" --window-icon=$ICON \

                --file --width=600 --height=500 \

                --text=$"<b>Choose your own audio file as alert!</b>

________________________________________________")

                if [ -z "$CHANGE" ];then

                exec alert_clock

                exit 0

                else

                mkdir $HOME/.config/alert-clock

                rm -rf $HOME/.config/alert-clock/alert sleep 1

                ln -s "$CHANGE" $HOME/.config/alert-clock/alert

                yad --title $"$TITLE"" $VERSION" \

            --button="gtk-ok:0" \

            --width 300 \

            --window-icon=$ICON \

            --text=$"Your own sound is set!!"

                fi

menu                

fi

Whenever we have a if, we need fi, or our script will end with an error. Used correctly, it is if … ; then … else … fi.

However, feel free to test it with Geany.

At this time, we have a perfectly working main window. Now we need to add the main command, which makes alert_clock work.

Add the following to your script:

if [ "$COUNTDOWN" = "" ];then

exit

else

echo you enter "$COUNTDOWN" minutes

TIMER=$(echo $(($COUNTDOWN*60)))

TASK1=$(date -s "+$TIMER seconds" 2>/dev/null | cut -d " " -f4)

exec 3> >(yad --notification --command=CMD --image=$ICON --listen)

echo tooltip: $"Alarm clock was set to $COUNTDOWN minutes and notifiers at $TASK1!" >&3

#sleep $TIMER

while [ $TIMER -ge 1 ]

do

   echo -n "$TIMER "  

sleep 1

   TIMER=$[$TIMER-1]

done

exec 3>&-

and start it. If you get the error messages  ./alert_test: line 82: syntax error: unexpected end of file, don’t despair. We must make sure that the last line is our script is fi.

You have now this result:

If you don’t get something similar to that pictured above, you have a typing error, or no icon. When the count is gone to zero, our program closes without error messages, and without the alert.

To get alert output add to your script:

#

#check which sound - auf Audio prüfen

#

if [ -f $HOME/.config/alert-clock/alert ]; then

        SOUND="$HOME/.config/alert-clock/alert"

        else

qqq        SOUND='/usr/share/alert_clock/alarm.ogg'

fi

This is needed for our sound.

#

#alert output - Alarm Ausgabe

#

(mplayer -loop 0 "$SOUND") | yad --title $"$TITLE"" $VERSION" \

                 --button="gtk-ok:0" \

                 --width 300 --image=$ICON \

                 --window-icon=$ICON \

                 --text=$"<b>Time is over!!</b>"

                 exit;

fi

exit

Test it again. Do you now hear an alert?

If not, check the messages that are generated when you run it from terminal.

Whenever you need a script, use YAD, Zenity, gtkdialog or kdialog. This will make your day much simpler.

By the way, you can download this script from my web site.

Good luck.