Problem
You want to allow user to filter by file type (e.g. listing only HTML files or image files) when selecting a file using GtkFileChooser as shown below:
Solution
- We create a file chooser dialog with GtkFilechooserdialog.
- Create a file filter using GtkFilefilter
- There are three ways of adding file filters:
- GtkFilefilter::add_pattern() e.g. "*.txt"
- GtkFilefilter::add_mime_type() e.g. "text/plain"
- GtkFilefilter::add_pixbuf_formats() - display all images of formats that GdkPixbif supports
Sample Code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 21 22 23 24 25 26 28 29 32 33 34 35 36 37 38 39 40 41 42 43 44 46 47 48 52 53 54 55 56 57 58 59 60 62 63 64 65 66 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 87 89 90 91 92 93 94 100 101 102 103 107 108 109 111 112 113 114 115 116 117 118 119 120 121 123 124 125 126 127 128 129 130 131 132 133 134 135 138 139 140 146 147 149 151 152 153 154 155 156 158 165 166 167 169 170 174 175 176 177 178 179 181 184 185 191 192 193 194 195 196 197 198 199 200 201 202 203 204 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 256 257 258 260 261 262 263 264 266 267 268 | <?php $window = new GtkWindow(); $window->set_size_request(400, 150); $window->connect_simple('destroy', array('Gtk','main_quit')); $window->add($vbox = new GtkVBox()); $accel_group = new GtkAccelGroup(); $window->add_accel_group($accel_group); // define menu definition $menu_definition = array( '_File' => array('_New|N', '_Open|O', '_Close|C', '<hr>', '_Save|S', 'Save _As','<hr>', 'E_xit'), '_Edit' => array('Cu_t|X', '_Copy|C', '_Paste|V', '<hr>', 'Select _All|A', '<hr>', '_Undo|Z','_Redo|Y'), '_Test' => array('Test_1|1', 'Test_2|2', 'Test_3|3', '<hr>', array('Selection 1', 'Selection 2', 'Selection 3'), '<hr>', 'Test_4|4') ); $menu = new Menu($vbox, $menu_definition, $accel_group); // display title $title = new GtkLabel(" Open a file with GtkFileChooser". "with filter by file type using GtkFileFilter"); $title->modify_font(new PangoFontDescription("Times New Roman Italic 10")); $title->modify_fg(Gtk::STATE_NORMAL, GdkColor::parse("#0000ff")); $vbox->pack_start($title); $vbox->pack_start(new GtkLabel("Press Ctrl-O to open the file chooser")); $vbox->pack_start(new GtkLabel("")); $window->show_all(); Gtk::main(); // class Menu class Menu { var $prev_keyval = 0; var $prev_state = 0; var $prev_keypress = ''; function Menu($vbox, $menu_definition, $accel_group) { $this->menu_definition = $menu_definition; $menubar = new GtkMenuBar(); $vbox->pack_start($menubar, 0, 0); foreach($menu_definition as $toplevel => $sublevels) { $top_menu = new GtkMenuItem($toplevel); $menubar->append($top_menu); $menu = new GtkMenu(); $top_menu->set_submenu($menu); // let's ask php-gtk to tell us when user press the 2nd Alt key $menu->connect('key-press-event', array(&$this, 'on_menu_keypress'), $toplevel); foreach($sublevels as $submenu) { if (strpos("$submenu", '|') === false) { $accel_key = ''; } else { list($submenu, $accel_key) = explode('|', $submenu); } if (is_array($submenu)) { // set up radio menus $i=0; $radio[0] = null; foreach($submenu as $radio_item) { $radio[$i] = new GtkRadioMenuItem($radio[0], $radio_item); $radio[$i]->connect('toggled', array(&$this, "on_toggle")); $menu->append($radio[$i]); ++$i; } $radio[0]->set_active(1); // select the first item } else { if ($submenu=='<hr>') { $menu->append(new GtkSeparatorMenuItem()); } else { $submenu2 = str_replace('_', '', $submenu); $submenu2 = str_replace(' ', '_', $submenu2); $stock_image_name = 'Gtk::STOCK_'.strtoupper($submenu2); if (defined($stock_image_name)) { $menu_item = new GtkImageMenuItem( constant($stock_image_name)); } else { $menu_item = new GtkMenuItem($submenu); } if ($accel_key!='') { $menu_item->add_accelerator("activate", $accel_group, ord($accel_key), Gdk::CONTROL_MASK, 1); } $menu->append($menu_item); $menu_item->connect('activate', array(&$this, 'on_menu_select')); $this->menuitem[$toplevel][$submenu] = $menu_item; } } } } } // process radio menu selection function on_toggle($radio) { $label = $radio->child->get_label(); $active = $radio->get_active(); echo("radio menu selected: $label\n"); } // process menu item selection function on_menu_select($menu_item) { $item = $menu_item->child->get_label(); echo "menu selected: $item\n"; if (method_exists($this, $item)) $this->$item(); if ($item=='E_xit') Gtk::main_quit(); } // let user choose a file with a file chooser dialog function _Open() { file_open(); } // processing of menu keypress function on_menu_keypress($menu, $event, $toplevel) { if (!$event->state & Gdk::MOD1_MASK) return false; // get the ascii equivalent of the keypress $keypress = ''; if ($event->keyval<255) { $keypress = chr($event->keyval); // ascii equivalent $keypress = strtolower($keypress); // convert to lowercase } $match = 0; // flag to see if there's a match foreach($this->menu_definition[$toplevel] as $submenu) { if (!preg_match("/.*_([a-zA-Z0-9]).*/", "$submenu", $matches)) continue; $key2 = strtolower($matches[1]); if ($keypress==$key2) { if (strpos("$submenu", '|') === false) { $accel_key = ''; } else { list($submenu, $accel_key) = explode('|', $submenu); } $menuitem = $this->menuitem[$toplevel][$submenu]; $menuitem->activate(); $menu->popdown(); $match = 1; break; } } return $match; } } function file_open() { global $dialog; $dialog = new GtkFileChooserDialog("File Open", null, Gtk::FILE_CHOOSER_ACTION_OPEN, array(Gtk::STOCK_OK, Gtk::RESPONSE_OK), null); $hbox = new GtkHBox(); $dialog->vbox->pack_start($hbox, 0, 0); $hbox->pack_start(new GtkLabel('File type:'), 0, 0); // create a combobox listing the available filter options $combobox = &GtkComboBoxEntry::new_text(); // note 1 $combobox->append_text("All Files"); $combobox->append_text("Text Files"); $combobox->append_text("HTML Files"); $combobox->append_text("PHP Files"); $combobox->append_text("Image Files"); $combobox->get_child()->set_text('All Files'); $combobox->connect('changed', 'on_change_filter'); // note 2 $hbox->pack_start($combobox, 0, 0); $dialog->show_all(); if ($dialog->run() == Gtk::RESPONSE_OK) { $selected_file = $dialog->get_filename(); // get the selected filename echo "selected_file = $selected_file\n"; } $dialog->destroy(); } function on_change_filter($combobox) { $model = $combobox->get_model(); // get the model $selected_value = $model->get_value( $combobox->get_active_iter(), 0);// note 3 echo "selected_value = $selected_value\n"; $filter = new GtkFileFilter(); // note 4 switch($selected_value) { // note 5 case 'All Files': $filter->add_pattern("*"); // note 5 break; case 'Text Files': $filter->add_pattern("*.txt"); // note 5 break; case 'HTML Files': $filter->add_mime_type("text/html"); // note 5 break; case 'PHP Files': $filter->add_pattern("*.php"); // note 5 break; case 'Image Files'; $filter->add_pixbuf_formats(); // note 5 break; } global $dialog; $dialog->set_filter($filter); // note 6 } ?> |
Output
As shown above.
Explanation
This example makes use of the code in the article How to open a file with GtkFileChooser? to set up the menu and display a FileChooser dialog.
What's new here:
- Create a combobox and insert all the available filter options.
- Call the function
on_change_filter()
when user selects a filter. - Get user selection.
- Create a new file filter.
- Set the filter accordingly. Note the three different ways of setting file filters.
- Go ahead and filter the files!
Read more...