in reply to Re: Perl::Tk and Win32::Perms Startup help
in thread Perl::Tk and Win32::Perms Startup help

Hi .dave.

This is what I have done so far:
use Tk; use strict; use Tk::Text; use Tk::Frame; use File::Find; use Tk::Scrollbar; use Tk::Adjuster; use Win32::Perms; my $path = shift @ARGV; my $mw = new MainWindow; $mw->geometry('500x400'); my $left_frame = $mw->Frame; my $adjuster = $mw->Adjuster(-widget=> $left_frame, -side=>'left'); my $right_frame = $mw->Frame; 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',); $list_box->insert('end', sort keys %dirs); $list_box->bind('<ButtonRelease-1>',sub {get_perms();}); $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); my $perms = new Win32::Perms($path) || die "\n$^E\n"; print "Path: " . $perms->Path(); my $counter = $perms->Get(\ my @list); $output_text->delete('0.1','end'); foreach my $item (@list) { while (my ($field, $value) = each %$item) { next if ($field !~ /account|access/i ); $output_text->insert('end', $field.": ".$value.",\t"); } $output_text->insert('end',"\n"); } }

This script will create two windows, the one on the left is where all the directories will be displayed and on the right is where the users or groups that have access to the directory will be displayed.

Now: what I would like to achieve are the following :

1-On the right windows, displaying users and groups as Icons (like an icon with a drawing of face for a users and two faces for a group-similar to what you get in User Manager) instead of displaying them in text.

2- Clicking on a user icon and dragging it then dropping it on an icon representing a group will move the user to that group.

3- On the left Window, where the directory structures are displayed, I would like to have a display similar to what you get if you had used Tk::DirTree -if I can. Also a single click on a directory will display the user permissions on the right window (which the script does that anyway) and double click will assign a variable to the selected path, so I can do other things with that path.

4- Instead of passing the path as @ARGV, it would be better if I could have an entry field (in the top left hand corner of the window) where I can pass the path in there and bind the Enter (or Return) key to that field.

Once I get the hang of the above points, I can contribute towards answering similar quires on PerlMonks –Hopefully ;-)

Many Thanks,I just can't express how much I do appreciate your help.

Replies are listed 'Best First'.
Tk drag and drop (DND) using TList
by hiseldl (Priest) on Jul 21, 2002 at 01:36 UTC
    I cleaned up the variable spaces and put the Tk refs in the %tk hash, the data references in the %dr hash, and the image references in the %im hash.

    You will need to change GetUsers, GetGroups, and AddUserToGroup to suit your needs. So, here's the latest edition with points 1,2,3, and 4 included.

    #! perl -w # This script will create two windows, the one on the left is where al +l # the directories will be displayed and on the right is where the user +s # or groups that have access to the directory will be displayed. # Now: what I would like to achieve are the following : # 1-On the right windows, displaying users and groups as Icons (like a +n # icon with a drawing of face for a users and two faces for a # group-similar to what you get in User Manager) instead of displaying # them in text. # 2- Clicking on a user icon and dragging it then dropping it on an ic +on # representing a group will move the user to that group. # 3- On the left Window, where the directory structures are displayed, + I # would like to have a display similar to what you get if you had used # Tk::DirTree -if I can. Also a single click on a directory will displ +ay # the user permissions on the right window (which the script does that # anyway) and double click will assign a variable to the selected path +, # so I can do other things with that path. # 4- Instead of passing the path as @ARGV, it would be better if I cou +ld # have an entry field (in the top left hand corner of the window) wher +e # I can pass the path in there and bind the Enter (or Return) key to # that field. use strict; use Tk 800.005; use Tk::TList; use Tk::DirTree; use Tk::Frame; use Tk::Scrollbar; use Tk::Adjuster; # These are required for drag-n-drop operations use Tk::DragDrop; use Tk::DropSite; use File::Find; use Win32::Perms; # $tk{widget_refs}, $dr{data_refs}, $im{image_refs} use vars qw/%tk %dr %im @users @groups $dnd_token/; $dr{PATH} = shift @ARGV || "."; $dr{perms} = "Permissions: ".$dr{PATH}; $tk{mw} = MainWindow->new(-background => 'white'); $tk{mw}->geometry('500x400'); $tk{top_frame} = $tk{mw}->Frame; $tk{left_frame} = $tk{mw}->Frame; $tk{adjuster} = $tk{mw}->Adjuster(-widget=> $tk{left_frame}, -side= +>'left'); $tk{right_frame} = $tk{mw}->Frame; $tk{entry_box} = $tk{top_frame}->Entry(-textvariable=>\$dr{PATH}); $tk{dir_tree} = $tk{left_frame}->Scrolled('DirTree', -height=>'0', -width=>'0', -scrollbars=>'e', ); $tk{output_list} = $tk{right_frame}->Scrolled('TList', -height=>'1', -width=>'1', -scrollbars=>'osoe',); $tk{user_list} = $tk{right_frame}->Scrolled('TList', -height=>'1', -width=>'1', -scrollbars=>'osoe',); $tk{group_list} = $tk{right_frame}->Scrolled('TList', -height=>'1', -width=>'1', -scrollbars=>'osoe',); $tk{user_label} = $tk{right_frame}->Label(-text => "User List:"); $tk{group_label} = $tk{right_frame}->Label(-text => "Group List:"); $tk{output_label} = $tk{right_frame}->Label(-textvariable => \$dr{perm +s}); $im{ONE} = $tk{mw}->Photo(-file => 'one.gif'); $im{GROUP} = $tk{mw}->Photo(-file => 'group.gif'); $tk{dir_tree}->chdir( $dr{PATH} ); $tk{dir_tree}->bind('<ButtonRelease-1>',sub {get_perms();}); $tk{entry_box}->bind('<Key-Return>',sub {OnNewPath();}); $tk{top_frame}->pack(qw/-side top -fill x/); $tk{left_frame}->pack(qw/-side left -fill y/); $tk{adjuster}->pack(qw/-side left -fill y/); $tk{right_frame}->pack(qw/-side right -fill both -expand 1/); $tk{entry_box} ->pack(qw/-side top -fill both -expand 1/); $tk{dir_tree} ->pack(qw/-side left -fill both -expand 1/); $tk{output_label}->pack(qw/-side top -fill both/); $tk{output_list} ->pack(qw/-side top -fill both -expand 1/); $tk{user_label} ->pack(qw/-side top -fill both/); $tk{user_list} ->pack(qw/-side top -fill both -expand 1/); $tk{group_label} ->pack(qw/-side top -fill both/); $tk{group_list} ->pack(qw/-side top -fill both -expand 1/); # Define the source for drags. # Drags are started while pressing the left mouse button and moving th +e # mouse. Then the StartDrag callback is executed. # # The DragDrop method returns a "token", which is a Label widget for # the text or image displayed during the drag action. $dnd_token = $tk{user_list}->DragDrop (-event => '<B1-Motion>', -sitetypes => [qw/Local/], -startcommand => \&DragStart, ); # Define the target for drops. $tk{group_list}->DropSite (-droptypes => [qw/Local/], -dropcommand => [\&Drop, $tk{group_list}, $dnd_token ], ); # Add the users to the user list and the groups to the group list @users = @{&GetUsers()}; map { $tk{user_list}->insert('end', -itemtype=>'imagetext', -text=>"$_", -image=>$im{ONE}) } @users; @groups = @{&GetGroups()}; map { $tk{group_list}->insert('end', -itemtype=>'imagetext', -text=>"$_", -image=>$im{GROUP}) } @groups; MainLoop; exit 0; sub DragStart { my($token) = @_; my $w = $token->parent; # $w is the source listbox my $e = $w->XEvent; my $idx = $w->GetNearest($e->x, $e->y); # get the listbox entry un +der cursor if (defined $idx) { # Configure the dnd token to show the listbox entry $token->configure(-text => $w->entrycget($idx, '-text') ); # Show the token my($X, $Y) = ($e->X, $e->Y); $token->MoveToplevelWindow($X, $Y); $token->raise; $token->deiconify; $token->FindSite($X, $Y, $e); } } # Accept a drop and insert a new item in the destination sub Drop { my($lb, $dnd_source) = @_; my $user_item = $dnd_source->cget('-text'); # figure out where in the group listbox the drop occurred my $y = $lb->pointery - $lb->rooty; my $x = $lb->pointerx - $lb->rootx; my $nearest = $lb->nearest($x,$y); if (defined $nearest) { my $group_item = $lb->entrycget($nearest, '-text'); &AddUserToGroup($user_item, $group_item); $lb->see($nearest); } } sub get_perms { my $path = $tk{dir_tree}->selectionGet(); &ShowPathInfo($path); } # This method is bound to the 'enter' key so that we can update # the path information from the entry widget. sub OnNewPath { $tk{dir_tree}->chdir( $dr{PATH} ); &ShowPathInfo( $dr{PATH} ); } sub ShowPathInfo { my ($path) = @_; my $perms = new Win32::Perms($path) || die "\n$^E\n"; print "Path: " . $perms->Path(); my $counter = $perms->Get(\ my @list); $dr{perms} = "Permisssions: $path"; $tk{output_list}->delete('0.1','end'); $tk{output_list}->insert('end', -itemtype=>'text', -text=>"$path"); foreach my $item (@list) { while (@_ = each %$item) { next unless $_[0] =~ /account|access/i; $tk{output_list}->insert('end', -itemtype=>'imagetext', -text=> $_[0].":". $_[1], -image=>$im{ONE}); } } } sub GetUsers { return [qw/One Two Three/]; } sub GetGroups { return [qw/Blue Green Red/]; } sub AddUserToGroup { my ($user, $group) = @_; # # Do something with $user_item and with $group_item # $dr{perms} = "User $user added to $group"; }
    Enjoy!
    .dave.
      F A N T A S T I C.

      I will get back with my findings as soon as I have debugged and added few bits.
      Thanks are not enogh...
        Hi .dave."Buddy"

        This is what I have done.

        1-I have amended the GetGroups subroutine so that the script will extract local group information, taking in account whether the drive or the path is a local or remote drive, this works fine. However the GetUsers sub doesn’t work, although it worked when I tested it on its own, what I have done there is; I obtained a list of permissions (groups and users generated from the ShowPathInfo sub where it says my $counter = $perms->Get (\@perms_list)) then I obtained a list of local groups the I compared the two list to obtain the items that do not exist in the groups list but they do exist in the @perms_list which means the item is a user so that it can be displayed in the users box in the form.

        2-The DirTree box always picks up the local c:\ drive no matter what I pass to @ARGV, the script will always pick the C drive. I am not sure on how to get the DirTree box to refresh when a new drive is entered in the entry box.

        3-The other thing that I am a bit confused about is that; in the permissions list (the first top box on the right) the access type is displayed with a user icon as well, also any groups displayed in there will be displayed with a user icon rather than group, and if a local group was detected and therefore displayed it the account will come up as unknown.

        I tried various methods to over come the above, unfortunately I was unsuccessful.

        I really appreciate your help in sorting these points.

        Finally, just to let you know that I have written another sub that will remove or add permission. And I would like to bind this script to the right button click of the mouse. So when I point at a user account I can have the option of dragging (this is done an it seems working fine) or removing for this I need the user name (where the mouse is pointing at) and the path to be fed to remove_add_perms.pl sub.

        I wil include this seperate sub on the next posting.

        Thanks very much for your help.

        use strict; use Tk 800.005; use Tk::TList; use Tk::DirTree; use Tk::Frame; use Tk::Scrollbar; use Tk::Adjuster; # These are required for drag-n-drop operations use Tk::DragDrop; use Tk::DropSite; use File::Find; use Win32::Perms; # these are required to obtain group, drive information use Win32::AdminMisc; use Win32::NetAdmin; use Win32::NetResource; # $tk{widget_refs}, $dr{data_refs}, $im{image_refs} use vars qw/%tk %dr %im @users @perms_list @groups $dnd_token $pdc/; $dr{Domain} = Win32::DomainName(); $dr{PATH} = shift @ARGV || "."; $dr{perms} = "Permissions: ".$dr{PATH}; $tk{mw} = MainWindow->new(-background => 'white'); $tk{mw}->geometry('500x400'); $tk{top_frame} = $tk{mw}->Frame; $tk{left_frame} = $tk{mw}->Frame; $tk{adjuster} = $tk{mw}->Adjuster(-widget=> $tk{left_frame}, -side= +>'left'); $tk{right_frame} = $tk{mw}->Frame; $tk{entry_box} = $tk{top_frame}->Entry(-textvariable=>\$dr{PATH}); $tk{dir_tree} = $tk{left_frame}->Scrolled('DirTree', -height=>'0', -width=>'0', -scrollbars=>'e', ); $tk{output_list} = $tk{right_frame}->Scrolled('TList', -height=>'1', -width=>'1', -scrollbars=>'osoe',); $tk{user_list} = $tk{right_frame}->Scrolled('TList', -height=>'1', -width=>'1', -scrollbars=>'osoe',); $tk{group_list} = $tk{right_frame}->Scrolled('TList', -height=>'1', -width=>'1', -scrollbars=>'osoe',); $tk{user_label} = $tk{right_frame}->Label(-text => "User List:"); $tk{group_label} = $tk{right_frame}->Label(-text => "Group List:"); $tk{output_label} = $tk{right_frame}->Label(-textvariable => \$dr{perm +s}); $im{ONE} = $tk{mw}->Photo(-file => 'one.gif'); $im{GROUP} = $tk{mw}->Photo(-file => 'group.gif'); $tk{dir_tree}->chdir( $dr{PATH} ); $tk{dir_tree}->bind('<ButtonRelease-1>',sub {get_perms();}); $tk{entry_box}->bind('<Key-Return>',sub {OnNewPath();}); $tk{top_frame}->pack(qw/-side top -fill x/); $tk{left_frame}->pack(qw/-side left -fill y/); $tk{adjuster}->pack(qw/-side left -fill y/); $tk{right_frame}->pack(qw/-side right -fill both -expand 1/); $tk{entry_box} ->pack(qw/-side top -fill both -expand 1/); $tk{dir_tree} ->pack(qw/-side left -fill both -expand 1/); $tk{output_label}->pack(qw/-side top -fill both/); $tk{output_list} ->pack(qw/-side top -fill both -expand 1/); $tk{user_label} ->pack(qw/-side top -fill both/); $tk{user_list} ->pack(qw/-side top -fill both -expand 1/); $tk{group_label} ->pack(qw/-side top -fill both/); $tk{group_list} ->pack(qw/-side top -fill both -expand 1/); # Define the source for drags. # Drags are started while pressing the left mouse button and moving th +e # mouse. Then the StartDrag callback is executed. # # The DragDrop method returns a "token", which is a Label widget for # the text or image displayed during the drag action. $dnd_token = $tk{user_list}->DragDrop (-event => '<B1-Motion>', -sitetypes => [qw/Local/], -startcommand => \&DragStart, ); # Define the target for drops. $tk{group_list}->DropSite (-droptypes => [qw/Local/], -dropcommand => [\&Drop, $tk{group_list}, $dnd_token ], ); # Add the users to the user list and the groups to the group list @users = GetUsers(); map { $tk{user_list}->insert('end', -itemtype=>'imagetext', -text=>"$_", -image=>$im{ONE}) } @users; @groups = GetGroups(); map { $tk{group_list}->insert('end', -itemtype=>'imagetext', -text=>"$_", -image=>$im{GROUP}) } @groups; MainLoop; exit 0; sub DragStart { my($token) = @_; my $w = $token->parent; # $w is the source listbox my $e = $w->XEvent; my $idx = $w->GetNearest($e->x, $e->y); # get the listbox entry un +der cursor if (defined $idx) { # Configure the dnd token to show the listbox entry $token->configure(-text => $w->entrycget($idx, '-text') ); # Show the token my($X, $Y) = ($e->X, $e->Y); $token->MoveToplevelWindow($X, $Y); $token->raise; $token->deiconify; $token->FindSite($X, $Y, $e); } } # Accept a drop and insert a new item in the destination sub Drop { my($lb, $dnd_source) = @_; my $user_item = $dnd_source->cget('-text'); # figure out where in the group listbox the drop occurred my $y = $lb->pointery - $lb->rooty; my $x = $lb->pointerx - $lb->rootx; my $nearest = $lb->nearest($x,$y); if (defined $nearest) { my $group_item = $lb->entrycget($nearest, '-text'); &AddUserToGroup($user_item, $group_item); $lb->see($nearest); } } sub get_perms { my $path = $tk{dir_tree}->selectionGet(); &ShowPathInfo($path); } # This method is bound to the 'enter' key so that we can update # the path information from the entry widget. sub OnNewPath { $tk{dir_tree}->chdir( $dr{PATH} ); &ShowPathInfo( $dr{PATH} ); } sub ShowPathInfo { my ($path) = @_; my $perms = new Win32::Perms($path) || die "\n$^E\n"; print "Path: " . $perms->Path(); my $counter = $perms->Get(\ @perms_list); $dr{perms} = "Permisssions: $path"; $tk{output_list}->delete('0.1','end'); $tk{output_list}->insert('end', -itemtype=> 'text', -text=> "$path"); foreach my $item (@perms_list) { while (@_ = each %$item) { next unless $_[0] =~ /account|access/i; $tk{output_list}->insert('end', -itemtype=> 'imagetext', -text=> $_[0].":". $_[1], -image=> $im{ONE}); # image ONE if user a +nd image Groupe if it group. } } } sub GetUsers { my %seen =(); # declare a record if an item has been spotted once +before, i.e. duplicate entry in the list my @found = (); # is an item was not found in the gorups list then + that item is a user # now comparing two list (groups and perms list)to obtain users foreach my $item (@perms_list) { $seen{$item} =1; #make a note of items available in both list } foreach my $item (@groups) { unless (! $seen{$item}) #if an item is not seen then it means +it is a user { push (@found, $item); } } return @found; # this will return empty list #[qw/One Two Three/]; } sub GetGroups { my ($srv); print "\nAnalysing $dr{PATH}\n"; # # Check $dr{PATH} before getting local group information, # if (Win32::NetResource::GetUNCName(my $unc, $dr{PATH})) { $unc =~ s/^\\\\(\w)+//; $srv = $&; print "\nPath is $dr{PATH} and server is: $srv\n"; } else { $srv = Win32::NodeName(); print "\nPath is $dr{PATH} and server is: $srv\n"; } if (Win32::AdminMisc::GetGroups("$srv", GROUP_TYPE_LOCAL, \ @group +s)) { print "\n\nThis is the list of groups\n"; foreach my $item (@groups) { print "$item\n"; } } return @groups; #[qw/RED BLUE GREEN/]; } sub AddUserToGroup { my ($user, $group) = @_; # # Do something with $user_item and with $group_item # $dr{perms} = "User $user added to $group"; }