Multiple-item data entry with YAD
By Bob Mesibov, published 07/04/2014 in Tutorials
YAD (Yet Another Dialog) creates GUI dialogs for data entry, user notification, etc. It was written by Victor Ananjevsky and is described as a fork of Zenity. In fact, it greatly extends Zenity and has a very large number of handy options. Here I explain how to build a multiple-item data entry form with YAD (version 0.20.3 from the Debian stable repository).
I'll start simple. In a shell script, the command
yad --form --field="Last name"
builds a simple data entry dialog with the cursor in a field box labelled Last name:
If I click Cancel, the dialog box disappears. If I enter 'Smith' and click OK, the dialog disappears and Smith| is returned:
Even at this early stage, YAD has 27 options (!), all listed in the YAD man page (under General options) and on this webpage. Here I'll use just three general options. --text= adds an introductory text string, --title="" replaces the word 'YAD' in the title bar with a blank, and --image= puts a smiley icon at top left in the dialog:
yad --title="" --text="Please enter your details:" \
--image="/usr/share/icons/Tango/scalable/emotes/face-smile.svg" \
--form \
--field="Last name"
[The tiny green icon at the left end of the title bar is yad.png, and lives in /usr/share/icons/hicolor/16x16/apps/ on my Debian system. It can be replaced with the option, --window-icon= followed by the path to an alternative icon.]
Next, I'll add another data entry field and increase the width of the dialog to 400 pixels:
yad --width=400 --title="" --text="Please enter your details:" \
--image="/usr/share/icons/Tango/scalable/emotes/face-smile.svg" \
--form \
--field="Last name" \
--field="First name"
If I enter 'Smith' after Last name and 'Jack' after First name and click OK, YAD returns Smith|Jack|. As you can see, YAD's default separator for data items is the pipe character (|). I can change the separator in the return string from pipe to tab (for example), by specifying --separator="\t", but I'll leave it here as a pipe.
The next field will take advantage of one of YAD's 'field type' options for the form dialog. There are 14 of these options, each specified by a code following a colon in the field designator. I'll add the date field type with :DT. This puts a little calendar icon in the field, which when clicked opens a standard GTK calendar:
yad --width=400 --title="" --text="Please enter your details:" \
--image="/usr/share/icons/Tango/scalable/emotes/face-smile.svg" \
--form \
--field="Last name" \
--field="First name" \
--field="Date of birth":DT
If I enter 8 September 1991, YAD shows '08/09/91' in the Date of birth field entry box and returns Smith|Jack|08/09/91|. That's YAD's default date format, which I can change with the --date-format= option using a different strftime code. (See the date command man page for codes.) I prefer '8 September 1991' format, so:
yad --width=400 --title="" --text="Please enter your details:" \
--image="/usr/share/icons/Tango/scalable/emotes/face-smile.svg" \
--form --date-format="%-d %B %Y" \
--field="Last name" \
--field="First name" \
--field="Date of birth":DT
The next field we'll add is a combo box, or drop-down list. To specify a combo box field, just add :CB to the field designator. However, there are several additional wrinkles to comb out. The first is that the drop-down list of choices is fed to YAD as a string separated (by default) by exclamation marks (!). For example, for the field --field="Last holiday":CB we might specify 'Gold Coast!Bali!Phuket!Sydney'.
The second wrinkle is that to attach 'Gold Coast!Bali!Phuket!Sydney' to the combo box field, I also have to tell each of the other fields what to do. I do that after listing the fields, like this:
yad --width=400 --title="" --text="Please enter your details:" \
--image="/usr/share/icons/Tango/scalable/emotes/face-smile.svg" \
--form --date-format="%-d %B %Y" \
--field="Last name" \
--field="First name" \
--field="Date of birth":DT \
--field="Last holiday":CB \
"" "" "" 'Gold Coast!Bali!Phuket!Sydney'
In the last line of the code, "" means that the field entry box will be empty when displayed. I could also put some text in those blanks, like 'Click calendar icon' in the 'Date of birth' field:
yad --width=400 --title="" --text="Please enter your details:" \
--image="/usr/share/icons/Tango/scalable/emotes/face-smile.svg" \
--form --date-format="%-d %B %Y" \
--field="Last name" \
--field="First name" \
--field="Date of birth":DT \
--field="Last holiday":CB \
"" "" "Click calendar icon" 'Gold Coast!Bali!Phuket!Sydney'
I can change the combo box list separator from ! to another character with the --item-separator= option. Here I'll change it to a comma with --item-separator=",". YAD also has an 'editable' option for combo boxes, specified as :CBE. If I add 'other' as a holiday option, the user can choose that option (or any other in the list) and edit it, and the user's edit will be returned. For example, with this code:
yad --width=400 --title="" --text="Please enter your details:" \
--image="/usr/share/icons/Tango/scalable/emotes/face-smile.svg" \
--form --date-format="%-d %B %Y" --item-separator="," \
--field="Last name" \
--field="First name" \
--field="Date of birth":DT \
--field="Last holiday":CBE \
"" "" "Click calendar icon" "Gold Coast,Bali,Phuket,Sydney,other"
I can choose 'other', delete it and type in 'Melbourne':
Probably the most useful combo box trick is that the combo box list can be read from a variable, keeping the code clearer:
holidays=$(echo "Gold Coast,Bali,Phuket,Sydney,other")
yad --width=400 --title="" --text="Please enter your details:" \
--image="/usr/share/icons/Tango/scalable/emotes/face-smile.svg" \
--form --date-format="%-d %B %Y" --item-separator="," \
--field="Last name" \
--field="First name" \
--field="Date of birth":DT \
--field="Last holiday":CBE \
"" "" "Click calendar icon" "$holidays"
The last field I'll add to the form is a multi-line text entry one, of type :TXT. Note below that I've also added another field 'placeholder' in the last line of the code for the new, last field:
holidays=$(echo "Gold Coast,Bali,Phuket,Sydney,other")
yad --width=400 --title="" --text="Please enter your details:" \
--image="/usr/share/icons/Tango/scalable/emotes/face-smile.svg" \
--form --date-format="%-d %B %Y" --item-separator="," \
--field="Last name" \
--field="First name" \
--field="Date of birth":DT \
--field="Last holiday":CBE \
--field="List your 3 favourite foods:":TXT \
"" "" "Click calendar icon" "$holidays" ""
These entries:
return Smith|Jack|8 September 1991|Melbourne|Mum's bangers and mash\nLamb curry\nHawaiian-style pizza|. In other words, the newlines in the entered, multi-line text are reported by YAD as newline characters (\n).
Yet another nice feature of YAD is shown in the image below, which comes from one of my scripts to manage scientific data.
Notice how the first three fields are grayed-out? The entries in these three fields come from other dialogs and were fed to this YAD dialog as the variables genus, species and event. Here are the relevant parts of the code:
yad --form --separator='\t' \
--field="Genus":RO \
--field="Species":RO \
--field="Event code":RO \
...
$genus $species $event "" 'ANIC!AusMus!NMV!QldMus!QVMAG!SAM!WAM!other' "" "" 'R. Mesibov!other' "" "" ""
The field type option used for the three fields is :RO, which means 'read-only'. It's a way of putting data items from other sources into YAD 'as-is', so that the YAD output string contains the accumulated results of those earlier inputs and those of the current one.
In summary, YAD is an excellent choice for getting multiple-item user input in a single GUI dialog. Developer Victor Ananjevsky must have gone quietly mad coding all the 'if' cases for the dozens of YAD options, but that flexibility that results makes this a great little program.