Using Zenity with Pdmenu (HPR Show 2877)

Zenity is a rather cool program that will display GTK+ dialogs from a script

Dave Morriss


Table of Contents

Overview

I use pdmenu a lot to help me do work on my main desktop PC. I did an HPR show on pdmenu on 13 December 2017 and the author Joey Hess responded in show 2459.

In the intervening time I have also integrated Zenity into my menus. This is a GUI tool which generates a number of different pop-up windows known as dialogs, which can display information, or into which information can be typed. The capabilities provided by pdmenu are a little too basic to enable me to do what I need to do.

I thought it might be of interest to show some examples of how I use this tool with pdmenu.

What is Zenity?

According to the manual:

Zenity is a rewrite of gdialog, the GNOME port of dialog which allows you to display dialog boxes from the command line and shell scripts.

Zenity runs on Linux, BSD and Windows, and a port to Mac OS X is available.

It’s invoked from the command line or a script as:

zenity [options]

The most important option is one that defines what type of dialog is required. The types are:

Dialog Option Description
--calendar Display calendar dialog
--entry Display text entry dialog
--error Display error dialog
--file-selection Display file selection dialog
--info Display info dialog
--list Display list dialog
--notification Display notification
--progress Display progress indication dialog
--question Display question dialog
--text-info Display text information dialog
--warning Display warning dialog
--scale Display scale dialog
--color-selection Display color selection dialog
--password Display password dialog
--forms Display forms dialog

I will not go into lot of detail here because the manpage covers the subject well, as does the online manual. I will show a couple of examples of how I use Zenity dialogs with Pdmenu.

Each of these dialog selection options takes a set of further options which control the configuration and behaviour of the dialog window.

There are a few general options:

Option Description
--title Window title for the dialog box
--window-icon=ICONPATH Set the window icon.
--width=WIDTH Set the dialog width
--height=HEIGHT Set the dialog height
--timeout=TIMEOUT Set the dialog timeout in seconds

The Calendar dialog

This takes the following options:

Option Description
--text=STRING Set the dialog text
--day=INT Set the calendar day
--month=INT Set the calendar month
--year=INT Set the calendar year
--date-format=PATTERN Set the format for the returned date

Any of the options --day=INT, --month=INT or --year=INT will default to the values for the current day if omitted.

The format of the date returned can be controlled with the --date-format=PATTERN option which uses the strftime codes, like %Y for the 4-digit year.

Example:

$ zenity --calendar --title=Test --date-format='%Y-%m-%d'
2019-07-25
Zenity Calendar Dialog
Zenity Calendar Dialog

How I use the Calendar Dialog with Pdmenu

Here is a menu definition from my .pdmenurc file:

#
# Menu cnews3 - Update Wiki from wiki.db
#
menu:cnews3:Update Wiki from wiki.db:Update Wiki from wiki.db
    exec:Update the _Wiki for this month:display:$HOME/HPR/Community_News/update_wiki
    exec:Update the Wiki for any _month:pause:\
        rep=$(zenity --calendar --title='Update Wiki' --text="Select a month" --date-format='01-%b-%Y') &&\
        { echo "$rep"; $HOME/HPR/Community_News/update_wiki "$rep"; }
    nop:--
    exit:E_xit Update Wiki from wiki.db

I keep a SQLite database of HPR shows and my notes about them and use the notes when I am recording the monthly Community News episodes.

I have a script which will update a MediaWiki Wiki on one of my Raspberry Pis from this database, and that’s what’s being done here. I have a Wiki page per month of HPR shows and update these individually. That way I have the shows and my notes all organised together.

Pdmenu sub-menu
Pdmenu sub-menu

For the action "Update the Wiki for any month" the menu will show a Zenity calendar and will return the date of the start of the month as '01-Jul-2019' for example.

Notice that zenity is being invoked in a command substitution, and the result is being stored in a variable called rep. The statement setting this variable may succeed (with a value in $rep) or may fail. The && { list } part at the end handles the success case. In it the date returned is echoed (so I know what it is) and is passed to a script that updates the wiki for the particular month.

All I have to do to update a particular month when presented with the calendar dialog is to click the '<' or '>' sign to the left or right of the month name and it moves backward or forward one month. I then click 'OK' when I have found the month I need, paying no heed to the day since it’s replaced by '01' in the menu.

The Forms Dialog

This takes the following options:

Option Description
--text=STRING Set the dialog text
--add-entry=FIELDNAME Add a new Entry in forms dialog
--add-password=FIELDNAME Add a new Password Entry in forms dialog
--add-calendar=FIELDNAME Add a new Calendar in forms dialog
--separator=STRING Set output separator character
--forms-date-format=PATTERN Set the format for the returned date

This dialog lets you assemble some other dialog types into a form.

Example:

$ zenity --forms --text="Name and DoB" --add-entry=FirstName --add-entry=LastName \
--add-calendar=DoB --forms-date-format='%Y-%m-%d'
Joe|Bloggs|2000-04-01
Zenity Forms Dialog
Zenity Forms Dialog

How I use the Forms Dialog with Pdmenu

Here is a piece of a menu definition from my .pdmenurc file:

    exec:_Collect JSON from IA:pause:\
        rep=$(zenity --forms --text='Enter show numbers' --add-entry=Start --add-entry=End) &&\
        $HOME/HPR/InternetArchive/collect_show_data "${rep%|*}" "${rep#*|}"

I keep another SQLite database with information about HPR shows which have been written to the Internet Archive (archive.org). I have scripts which collect data from archive.org in the JSON format, save it in a file and then add it to my database.

The above menu fragment takes in the start and end show numbers in a range that has been uploaded (usually a week’s worth, 5 shows at a time), then it queries archive.org for details of shows.

This is what the full menu looks like:

Pdmenu for IA management
Pdmenu for IA management

The following dialog is shown to enable show number entry:

Zenity range dialog
Zenity range dialog

Note that after '&&' in the menu definition we do not need enclosing curly braces since there is only one command.

Note also that the zenity call returns two numbers separated by the default separator ('|'). These are separated out when calling the script that does the work, making use of the shell’s parameter substitution facilities. See the Bash Tips shows on HPR, particularly episode 1648 (Remove matching prefix pattern and Remove matching suffix pattern).

Summary

I need menus since I can never remember what I am supposed to do to carry out workflows and other processes! My motto is “If in doubt, write a script”!

The facilities in Pdmenu for prompting and gathering information are a bit too basic for my needs, but Zenity does a fine job for me here. OK, so it has moved me away from my usual preference for command-line stuff, but I find this to be a great compromise!

One slight grumble about Pdmenu is that the shell it uses to run commands is 'sh', not 'bash', so some of the Bashisms I’d like to use are not available. It’s not hampering me too much now, and when it does I’ll maybe consider changing the source of pdmenu to do what I want if I can.