Directory/file browser as TreeView



Don't know if this is worthy of a/the cookbook or wiki somewhere, and it certainly needs tidying up (having 
to store the directory path as a hidden column seems rather hackish to me - but I couldn't work out how to 
get the parent from an iter) but having sort of got my head around TreeModel/TreeView/TreeStore to code a 
directory tree viewer I thought I'd save someone else the trouble.

Improvements, of course, are welcome.

Jeff

#!/usr/bin/perl

use warnings;
use strict;
use Gtk2 -init;
use Gtk2::SimpleList;

use constant TRUE  => 1;
use constant FALSE => 0;

my $window = Gtk2::Window -> new;
$window -> signal_connect ( 'delete_event', sub { Gtk2 -> main_quit; } );
$window -> set_default_size (800, 600);
my $hpaned = Gtk2::HPaned -> new;
$window -> add ( $hpaned );

my $scwin_dirs = Gtk2::ScrolledWindow -> new;
$scwin_dirs -> set_policy ('automatic', 'automatic');
$hpaned -> pack1 ($scwin_dirs, TRUE, TRUE);

# Directory name, full path
my $tree_store = Gtk2::TreeStore->new('Glib::String', 'Glib::String');
my $tree_view = Gtk2::TreeView->new($tree_store);
my $column = Gtk2::TreeViewColumn->new_with_attributes('', Gtk2::CellRendererText->new(), text => "0");
$tree_view->append_column($column);
$tree_view->set_headers_visible(FALSE);
$tree_view->signal_connect (button_release_event => \&cd);
$tree_view->signal_connect ('row-expanded' => \&populate_tree);

my $child = $tree_store->append(undef);
$tree_store->set($child, 0, '/', 1, '/');
add_to_tree($tree_store, $child, '/', '/');

$scwin_dirs -> add($tree_view);

my $scwin_files = Gtk2::ScrolledWindow -> new;
$scwin_files -> set_policy ('automatic', 'automatic');
$hpaned -> pack2 ($scwin_files, TRUE, TRUE);

my $slist = Gtk2::SimpleList -> new('Filename' => 'text');
$scwin_files -> add_with_viewport($slist);

$window -> show_all;
Gtk2 -> main;


sub add_to_tree {
 my ($tree_store, $parent, $dir, $path) = @_;
 
 my $tree_model = $tree_view->get_model();

# If $parent already has children, then remove them first
 my $child = $tree_model->iter_children ($parent);
 while ($child) {
  $tree_store->remove ($child);
  $child = $tree_model->iter_children ($parent);
 }
 
# Add children from directory listing
 opendir(DIRHANDLE, $path) || die "Cannot open directory: $!\n";
 foreach my $subdir (sort readdir(DIRHANDLE)) {
  if ($subdir ne '.' and $subdir ne '..'
                                    and -d $path.$subdir and -r $path.$subdir) {
   my $child = $tree_store->append($parent);
   $tree_store->set($child, 0, $subdir, 1, "$path$subdir/");
  }
 }
 closedir(DIRHANDLE);
}


# Directory expanded. Populate subdirectories in readiness.

sub populate_tree {

# $iter has been expanded
 my ($tree_view, $iter, $tree_path) = @_;
 my $tree_model = $tree_view->get_model();
 my ($dir, $path) = $tree_model->get($iter);

# for each of $iter's children add any subdirectories
 my $child = $tree_model->iter_children ($iter);
 while ($child) {
  my ($dir, $path) = $tree_model->get($child, 0, 1);
  add_to_tree($tree_store, $child, $dir, $path);
  $child = $tree_model->iter_next ($child);
 }
 return;
}


# Load $slist with all filenames in selected directory

sub cd {
 my $tree_model = $tree_view->get_model();
 my $selection = $tree_view->get_selection();
 my $iter = $selection->get_selected();
 my $path = $tree_model->get($iter, 1);

# Display list of files
 chdir $path;
 @{$slist->{data}} = <*>;
 return;
}



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]