Gtk2Hs Tutorial

5.2 File Selection

Files and directories (folders) are essential to almost every
computer program and Gtk contains many components to facilitate
their handling. User selection of files and folders in Gtk2Hs is
implemented through the
FileChooser interface. Basically there are four
modes, as expressed in the
FileChooserAction type. Its constructors are:

FileChooserActionOpen used to let the user open a
file

FileChooserActionSave used to let the user save a
file

FileChooserActionSelectFolder used to let a user
select a directory

FileChooserActionCreateFolder used to let a user
create a directory

The
FileChooser interface has attributes, methods and
signals, but is not itself a widget. There are three widgets that
use the interface in different manners, the
FileChooserWidget ,
FileChooserButton and
FileChooserDialog . Which widget you use may also
restrict which
FileChooserActionType is allowed. As you'll see in
the examples below, a widget for saving a file or selecting a
directory can also contain a button which lets the user create a
directory. Therefore the FileActionCreateFolder constructor will
probably never be used in any of your programs.

It is important to note that, while the widgets do not save or
open files by themselves, the creation of directories (by the
user) is actually implemented through the widgets.

Our first example will use a
FileChooserWidget , which can be in Open or Save
mode.

fileChooserWidgetNew :: FileChooserAction -> IO FileChooserWidget

We use
FileChooserActionOpen here, and when the user
definitely chooses a file by doubleclicking it or pressing the
Enter key, the
onFileActived signal is emitted. Then we use:

From the filepath, the program can then open the file, or
possibly do something else. The format of the filepath may depend
on the platform and is determined by the G_FILENAME_ENCODING
environment variable. There are also functions in
FileChooser for URI (Uniform Resource Identifier)
formats, but those are not discussed here.

You can determine whether the user can select multiple files
or not with:

Another feature is the use of filters to show only files of a
certain type, either by specifying a MIME type, a pattern or a
custom format. File filters are documented in
Graphics.UI.Gtk.Selectors.FileFilter.

The following code snippet, from the example below,
illustrates filters. The last line just adds the filter to the
file chooser widget and, as with the extra widget, visual placing
is done automatically.

In the example this is used to preview graphics files. The
example uses an
Image widget (documented in
Graphics.UI.Gtk.Display.Image) like used before in Chapter 4.1.
There we used
imageNewFromFile to add graphics to a button; here we
construct an empty
Image widget.

To update it regularly, we have the
onUpdatePreview signal, which is emitted whenever the
user changes the file selection by moving the mouse or
accelerator keys. Therefore this signal is more general than the
name suggests, but here it is actually used for viewing. The code
snippet is:

There are functions and attributes to control the display, for
example, what happens when a file is selected which is not a
graphics file, but they are not really needed. In the test of the
code below, non graphics files were just ignored, or indicated by
a standard icon. This is how it all looked:

Note that the user can also add and delete bookmarks, and
FileChooser has functions to manage this as well. But
this feature is not treated in the
FileChooserWidget example, which has the following
source code:

Note: With Gtk2Hs 0.9-12 and GHC 6.1 on FC 6, multiple file
selection worked visually (Ctrl and Shift keys indicated
multiples as expected), but the list of file paths only contained
the path of the last file.

The second way to use the
FileChooser interface is through a
FileChooserButton .

The
String parameter is the name of the browse dialog
that pops up when the user select the 'other...' option after
pressing the button. In the example below we constructed a file
chooser button with FileChooserActionSelectFolder. This is how
the button looked after selecting directory "Test".

This is how the dialog looked:

As you can see, there is a "Create Folder" button at the top
right hand side of the dialog window and this can be used to
actually create a new directory. This is what happened when I
tried to create an existing folder:

Creating or overwriting an existing directory makes no sense
and would be dangerous, so Gtk2Hs automatically takes care of it
and notifies the user. When the user selects an existing
directory the
onCurrentFolderChanged signal is emitted and the
program can take the appropriate action. Creating a directory
automatically selects it, so in that case
onCurrentFolderChanged can be used as well. Here is
the example code:

The third way to use the
FileChooser interface is through a
FileChooserDialog . It can be constructed in the open
or save mode, and is usually applied from a menu or a
toolbar.

FileChooserDialog implements both
FileChooser and
Dialog . Recall from Chapter 4.5 that a dialog is a
composite widget with buttons, usually implemented with
dialogRun, which produces responses of type
ResponseId . A
FileChooserDialog is constructed with:

All you have to do is specify the names of the buttons and
their responses in the fourth argument, and they will
automatically be implemented.

The example takes
FileChooserActionSave and the dialog has three
buttons. This is what it looks like:

As you can see there is a button at the top right to create a
folder. As in the example before, trying to create a folder which
already exists results in an error message. Overwriting a file,
however, makes sense and is allowed by default. You can make the
user confirm any overwite of a file with:

Note: When testing with Gtk2Hs 0.9-12 and GHC 6.1 on FC6,
pressing the Enter key to save a file had no effect. When a file
was chosen which already existed, pressing the Save
button had no effect the first time, but pressing again produced the
confirmation dialog. My own thought is that this might have
something to do with the
onConfirmOverwrite signal and its second argument of
type
IO FileChooserConfirmation. Its use is unclear to me,
and the fault may be with my code.