If you are a Gtk+ veteran, you may be familiar with the feeling of inferiority coming over you when using the Gtk2::FileSelection
widget. This widget looked like a typical Tk design and was not very flexible.
Today we are blessed with the more functional and appealing Gtk2::FileChooser
interface and the widgets making use of it. They are the Gtk2::FileChooserWidget
, Gtk2::FileChooserDialog
, and Gtk2::FileChooserButton
.
This lesson will show the reader how to utilize these classes.
We create a simple program which shows the two types of Gtk2::FileChooserButton
s. It also shows the effect that different values of the 'action'
property have on the appearance of the Gtk2::FileChooserDialog
.
Table 20-1. Gtk2
object classes used
Gtk2 Class Name |
---|
Gtk2::Window |
Gtk2::VBox |
Gtk2::HBox |
Gtk2::Frame |
Gtk2::FileChooserButton |
Gtk2::FileChooserDialog |
Gtk2::Button |
Gtk2::MessageDialog |
The program can be found here: 'gtk2_file_chooser.pl'
1 #! /usr/bin/perl -w 2 3 use strict; 4 use Gtk2 '-init'; 5 use Glib qw/TRUE FALSE/; 6 7 #standard window creation, placement, and signal connecting 8 my $window = Gtk2::Window->new('toplevel'); 9 $window->signal_connect('delete_event' => sub { Gtk2->main_quit; }); 10 $window->set_border_width(5); 11 $window->set_position('center_always'); 12 13 #add and show the vbox 14 $window->add(&ret_vbox); 15 $window->show(); 16 17 #our main event-loop 18 Gtk2->main(); 19 20 sub ret_vbox { 21 22 my $vbox = Gtk2::VBox->new(FALSE,5); 23 24 #*************************************** 25 #Show the filechooserbuttons (open and select-folder action types) 26 my $frm_fl_chooser_button = Gtk2::Frame->new('Gtk2::FileChooserButton'); 27 $frm_fl_chooser_button->set_border_width(5); 28 29 my $hbox_fl_chooser_button = Gtk2::HBox->new(FALSE,5); 30 $hbox_fl_chooser_button->set_border_width(10); 31 32 #Open a file dialog button-----> 33 my $fc_btn_file =Gtk2::FileChooserButton->new ('select a file' , 'open'); 34 $fc_btn_file->set_filename("/etc/passwd"); 35 $hbox_fl_chooser_button->pack_start($fc_btn_file,TRUE,TRUE,6); 36 37 #Open a folder dialog button----> 38 my $fc_btn_folder =Gtk2::FileChooserButton->new ('select a folder' , 'select-folder'); 39 $hbox_fl_chooser_button->pack_start($fc_btn_folder,TRUE,TRUE,6); 40 41 $frm_fl_chooser_button->add($hbox_fl_chooser_button); 42 $vbox->pack_start($frm_fl_chooser_button,FALSE,FALSE,6); 43 44 #*************************************** 45 #Show the filechooserdialog action types (open save select-folder create-folder) 46 my $frm_fl_chooser_dialog = Gtk2::Frame->new('Gtk2::FileChooserDialog Incarnations'); 47 48 my $hbox_fl_chooser_dialog = Gtk2::HBox->new(FALSE,5); 49 $hbox_fl_chooser_dialog->set_border_width(10); 50 51 #Open----> 52 my $btn_open = Gtk2::Button ->new('_Open'); 53 $btn_open->signal_connect('clicked' => 54 sub{ show_chooser('File Chooser type open','open',ret_png_filter()) }); 55 $hbox_fl_chooser_dialog->pack_start($btn_open,TRUE,TRUE,6); 56 57 #Save----> 58 my $btn_save = Gtk2::Button->new('_Save'); 59 $btn_save->signal_connect('clicked' => 60 sub{ show_chooser('File Chooser type save','save') }); 61 $hbox_fl_chooser_dialog->pack_start($btn_save,TRUE,TRUE,6); 62 63 #Select Folder----> 64 my $btn_select_folder = Gtk2::Button->new('S_elect Folder'); 65 $btn_select_folder->signal_connect('clicked' => 66 sub{ show_chooser('File Chooser type select-folder','select-folder') }); 67 $hbox_fl_chooser_dialog->pack_start($btn_select_folder,TRUE,TRUE,6); 68 69 #Create Folder----> 70 my $btn_create_folder = Gtk2::Button->new('_Create Folder'); 71 $btn_create_folder->signal_connect('clicked' => 72 sub{ show_chooser('File Chooser type create-folder','create-folder') }); 73 $hbox_fl_chooser_dialog->pack_start($btn_create_folder,TRUE,TRUE,6); 74 75 $frm_fl_chooser_dialog->add($hbox_fl_chooser_dialog); 76 $vbox->pack_start($frm_fl_chooser_dialog,FALSE,FALSE,6); 77 78 79 $vbox->show_all(); 80 return $vbox; 81 } 82 83 sub show_chooser { 84 #--------------------------------------------------- 85 #Pops up a standard file chooser-------------------- 86 #Specify a header to be displayed------------------- 87 #Specify a type depending on your needs------------- 88 #Optionally add a filter to show only certain files- 89 #will return a path, if valid---------------------- 90 #--------------------------------------------------- 91 92 my($heading,$type,$filter) =@_; 93 #$type can be: 94 #* 'open' 95 #* 'save' 96 #* 'select-folder' 97 #* 'create-folder' 98 my $file_chooser = Gtk2::FileChooserDialog->new ( 99 $heading, 100 undef, 101 $type, 102 'gtk-cancel' => 'cancel', 103 'gtk-ok' => 'ok' 104 ); 105 (defined $filter)&&($file_chooser->add_filter($filter)); 106 107 #if action = 'save' suggest a filename 108 ($type eq 'save')&&($file_chooser->set_current_name("suggeste_this_file.name")); 109 110 my $filename; 111 112 if ('ok' eq $file_chooser->run){ 113 $filename = $file_chooser->get_filename; 114 print "filename $filename\n"; 115 } 116 117 $file_chooser->destroy; 118 119 if (defined $filename){ 120 if ((-f $filename)&&($type eq 'save')) { 121 my $overwrite =show_message_dialog( $window, 122 'question' 123 ,'Overwrite existing file:'."<b>\n$filename</b>" 124 ,'yes-no' 125 ); 126 return if ($overwrite eq 'no'); 127 } 128 return $filename; 129 } 130 return; 131 } 132 133 sub show_message_dialog { 134 #--------------------------------------------------- 135 #you tell it what to display, and how to display it 136 #$parent is the parent window, or "undef" 137 #$icon can be one of the following: a) 'info' 138 # b) 'warning' 139 # c) 'error' 140 # d) 'question' 141 #$text can be pango markup text, or just plain text, IE the message 142 #$button_type can be one of the following: a) 'none' 143 # b) 'ok' 144 # c) 'close' 145 # d) 'cancel' 146 # e) 'yes-no' 147 # f) 'ok-cancel' 148 #--------------------------------------------------- 149 150 my ($parent,$icon,$text,$button_type) = @_; 151 152 my $dialog = Gtk2::MessageDialog->new_with_markup ($parent, 153 [qw/modal destroy-with-parent/], 154 $icon, 155 $button_type, 156 sprintf "$text"); 157 my $retval = $dialog->run; 158 $dialog->destroy; 159 return $retval; 160 } 161 162 163 sub ret_png_filter { 164 #---------------------------------------- 165 #Returns a filter, filtering only png files 166 #---------------------------------------- 167 168 my $filter = Gtk2::FileFilter->new(); 169 $filter->set_name("Images"); 170 $filter->add_mime_type("image/png"); 171 172 return $filter; 173 }
The following widgets make use of the Gtk2::FileChooser
interface: Gtk2::FileChooserDialog
, Gtk2::FileChooserButton
, Gtk2::FileChooserWidget
.
This means that the methods and properties available to the Gtk2::FileChooser
should also be available to these widgets.
Depending how the widget makes use of the Gtk2::FileChooser
interface, it may enable / disable the use of certain properties. The 'set_current_name'
method for instance can't be used if the 'action'
property is set to 'open'
.
The Gtk2::FileChooserButton
can be constructed using a few methods. The one we use automatically creates a Gtk2::FileChooserDialog
and associates it with the Gtk2::FileChooserButton
.
Remember: The only actions |
Talking about 'set_current_name'
. This is used to suggest a name when saving a file.
The Gtk2::FileChooser
has a property 'do-overwrite-confirmation'
. It seems that setting this to TRUE will ask for confirmation when a user selected a file already in existence. ('action'
must also be equal to 'save'
)
The tests I've done could not get this working, thus in the sample program, when an existing file is chosen the yes/no question is invoked in code.
Rather than creating a Gtk2::FileChooserDialog
each time you need one, it is good practice to have a sub that takes certain arguments to manipulate the appearance of the Gtk2::FileChooserDialog
and return the value specified.
On the Gtk2::FileChooserDialog
POD page, you will see the following: * ... (list) list of button-text => response-id pairs
. This will typically be an 'ok' and 'cancel' button.
'gtk-cancel' => 'cancel', 'gtk-ok' => 'ok'
The Gtk2::FileChooserWidget
was not used directly, but it is used inside the Gtk2::FileChooserDialog
. You may use it on its own, but the Gtk2::FileChooserDialog
is just way more convienient.
Adding a Gtk2::FileFilter
to the Gtk2::FileChooser
will let the Gtk2::FileChooser
show only those file types we asked for.
Two methods are generally used to add a filetype to a Gtk2::FileFilter
.
The recommended one is 'add_mime_type'
. This will let the filechooser 'look into' a file, thus if you have a .png file without the .png eextension, it will still show when you specified the following:
$filter->add_mime_type("image/png");
The other method is 'add_pattern'
. This method makes use of wild charts. Typical sample code will look as follows:
$filter->add_pattern("*.png"); $filter->add_pattern("*.jpg"); $filter->add_pattern("*.gif"); $filter->add_pattern("*.tif"); $filter->add_pattern("*.xpm"); $filter->add_pattern("*.bmp");Note that they can be stacked!
With the addition of Gtk2::FileChooser
to the newer versions of Gtk+, we finally do not have to be ashamed any more when asking someone to open or save a file in our program. Gtk2::FileChooser
was dearly needed and is just as dearly appreciated!