blackadder has asked for the wisdom of the Perl Monks concerning the following question:

Hi O’Holy Ones
I am new in Perl::Tk stuff so please your help is sooooo highly appreciated (and please patience with me).
I have been trying without success to modify the script below (which I have nicked from the Widgets Demo ‘image demo #2’). So that, it will take a path as an input parameter, then the frame where it displays files will only display directories and sub directories (no files – for this I am hoping to use this cool Tk::DirTree extension). And when a directory or subdirectory selected (by clicking on the desired object), it will display user or group ACE permission information instead of displaying an Image. I have already written a script in pure Perl that does all the above, however a GUI for the script is highly required now, and I am completely lost with it.
use File::Basename; use subs qw/image2_load_dir image2_load_image/; use vars qw/$TOP/; sub image2 { my($demo) = @_; $TOP = $MW->WidgetDemo( -name => $demo, -text => 'This demonstration allows you to view images usi +ng a Tk "photo" image. First type a directory name in the listbox, t +hen type Return to load the directory into the listbox. Then double- +click on a file name in the listbox to see that image.', -title => 'Image Demonstration #2', -iconname => 'image2', ); my $dir_label = $TOP->Label(-text => 'Directory:'); my $demo_img = Tk->findINC('demos/images'); my $dir_name = $TOP->Entry(-width => 30, -textvariable => \$demo_i +mg); my $frog0 = $TOP->Frame; my $frog = $frog0->Frame; my $file_label = $frog->Label(-text => 'File:'); my $f = $frog->Frame; my(@pl) = qw/-side top -anchor w/; $dir_label->pack(@pl); $dir_name->pack(@pl); # All these "frog" and "toad" frames are just to repackage the lis +tbox # and image side by side so they fit within an SVGA screen. $frog0->pack; $frog->pack(qw/-side left/); my $toad = $frog0->Frame; $toad->pack(qw/-side right/); $file_label->pack(@pl); $f->pack(@pl); my $f_list = $f->Listbox(-width => 20, -height => 10); $dir_name->bind('<Return>' => [\&image2_load_dir, $f_list, \$demo_ +img]); my $f_scroll = $f->Scrollbar(-command => [$f_list => 'yview']); $f_list->configure(-yscrollcommand => [$f_scroll => 'set']); @pl = qw/-side left -fill y -expand 1/; $f_list->pack(@pl); $f_scroll->pack(@pl); $f_list->insert(0, qw(earth.gif earthris.gif mickey.gif teapot.ppm +)); my $image2a = $TOP->Photo; $f_list->bind('<Double-1>' => [\&image2_load_image, $image2a, \$de +mo_img]); my $image_label = $toad->Label(-text => 'Image:'); my $image = $toad->Label(-image => $image2a); @pl = qw/-side top -anchor w/; $image_label->pack(@pl); $image->pack(@pl);} # end image2 sub image2_load_dir { # This procedure reloads the directory listbox from the directory # named in the demo's entry. # # Arguments: # e - Reference to entry widget. # l - Reference to listbox widget. # dir_name - Directory name reference. my($e, $l, $dir_name) = @_; $l->delete(0, 'end'); my $i; local *DIR; opendir DIR, $$dir_name; foreach $i (sort readdir DIR) { $l->insert('end', $i); } closedir DIR; } # end image2_load_dir sub image2_load_image { # Given the name of the toplevel window of the demo and the mouse # position, extracts the directory entry under the mouse and loads # that file into a photo image for display. # # Arguments: # l - Reference to listbox widget. # i - Reference to image object. # dir_name - Directory name reference. my($l, $i, $dir_name) = @_; my $e = $l->XEvent; my($x, $y) = ($e->x, $e->y); $i->configure(-file => "$$dir_name/" . $l->get("\@$x,$y")); # NOTE: $l->get('active') works just as well. } # end image2_load_imag

Replies are listed 'Best First'.
Re: Perl::Tk help to startup.
by hiseldl (Priest) on Jul 15, 2002 at 17:13 UTC
    Here's an example of a listbox with directories only, and when you click on an item, it will show information in the text widget.

    • "...it will take a path as an input parameter <on the command line>, then the frame where it displays files will only display directories and sub directories..."
    • "...when a directory or subdirectory selected (by clicking on the desired object), it will display <file stat> ... information..."
    #!perl -w use strict; use File::Find; use Tk; use Tk::Frame; use Tk::Text; use Tk::Scrollbar; use Tk::Adjuster; # Main Window my $mw = new MainWindow; $mw->geometry('400x300'); # Main Frame my $lf = $mw->Frame; # Left Frame; my $aj = $mw->Adjuster(-widget => $lf, -side => 'left'); my $rf = $mw->Frame; # Right Frame; # Args my $path = $ARGV[0]; # path passed in on the cmd line # create list of directories my %dirs; find(sub {$dirs{$File::Find::dir}++;}, $path); my($ListBox) = $lf->Scrolled('Listbox', -height => '0', -width => '0', -scrollbars => 'e', ); my($OutputText) = $rf->Scrolled('Text', -height => '1', -width => '1', -scrollbars => 'osoe', ); # Load dir names into the listbox $ListBox->insert('end', keys %dirs); # Left mouse button calls display sub $ListBox->bind('<ButtonRelease-1>', sub { OnShowFileAttr(); } ); # Pack everything $lf->pack(qw/-side left -fill y/); $aj->pack(qw/-side left -fill y/); $rf->pack(qw/-side right -fill both -expand 1/); $ListBox ->pack(qw/-side left -fill both -expand 1/); $OutputText->pack(qw/-side bottom -fill both -expand 1/); # Start the main event loop MainLoop; exit 0; sub OnShowFileAttr { my ($index) = $ListBox->curselection(); my $filestats = join ":", lstat($ListBox->get($index)); $OutputText->insert('end', $filestats."\n"); }
    The OnShowFileAttr method is where you will want to add your file/dir stat information retrieval. The $ListBox->get($index) will contain the item selected.

    This is just a rudimentary script, but it should be less confusing, and hopefully meets your requirements.

    --
    .dave.

      Dave: Thank you x 1000^100 times.

      I have modified the sub OnShowFileAttr to get_perms (which retrieves ACE permission information on the selected object)

      However, if I may, I have the following questions:

      1- every time an object is selected (in the left box), the script will add it to the bottom of the box list on the right. How can I get the script to refresh rather than add it to the end of the list, the reason is if I click on an object, I only need to see it once rather than adding it to the end of the list each time I click on he object?

      2- The Directory list is not sorted in the in the order they appear (i.e c:/, then sub directories in that folder) how can I tie it up so they are sorted in the oder they appear?

      3- I would like to represent account permission information in a graphical form, ie if its a user account then an Icon representing a single user will appear, or else and Icon representing a group instead?

      4- Finally, is it possible (once point 3 implemented) I can move a user account by clicking a dragging then dropping it on top a group Icon? For example if the path c$:/temp has User_a and Group_a allowed to access it, then I drag user_a and drop it on top of the icon representing Group_a, so the path will only show Group_a have accesxs permission and within this group user_a will reaside?

      Your help is like a life line to me at the moment. So Thank you very much in advance.
      use Tk; use strict; use File::Find; use Tk::Frame; use Tk::Text; use Tk::Scrollbar; use Tk::Adjuster; use Win32::Perms; my $path = shift @ARGV; my $mw = new MainWindow; #main frame $mw->geometry('400x300'); my $left_frame = $mw->Frame; #left frame my $adjuster = $mw->Adjuster(-widget=> $left_frame, -side=>'left'); my $right_frame = $mw->Frame; #left frame # create a list of directories my %dirs; find(sub { $dirs{$File::Find::dir}++;}, $path); my ($list_box) = $left_frame->Scrolled('Listbox', -height=>'0', -width=>'0', -scrollbars=>'e', ); my ($output_text) = $right_frame->Scrolled('Text', -height=>'1', -width=>'1', -scrollbars=>'osoe',); #Load dir names into the list box $list_box->insert('end', keys %dirs); $list_box->bind('<ButtonRelease-1>',sub {get_perms();}); #pack everything $left_frame->pack(qw/-side left -fill y/); $adjuster->pack(qw/-side left -fill y/); $right_frame->pack(qw/-side right -fill both -expand 1/); $list_box->pack(qw/-side left -fill both -expand 1/); $output_text->pack(qw/-side bottom -fill both -expand 1/); + MainLoop; exit 0; sub get_perms { my ($indx) = $list_box->curselection(); my $path = $list_box->get($indx); print $path; my $perms = new Win32::Perms($path) || die "\n$^E\n"; my $counter = $perms->Get(\ my @list); foreach my $item (@list) { while (my ($f, $v) = each %$item) { next if ($f !~ /account|access/i ); $output_text->insert('end', $f.": ".$v."\n"); } } }