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

Respected Monks

*I humbly ask for your Enlightenment please – I am quit confused on how to proceed and having spend all day today trying to no avail*

I have this bit of Tk code
use strict; use vars qw/@winbcp_info/; use Tk (); use Tk::TList; use Tk::HList; my $mw = Tk::MainWindow->new(); my $image = $mw->Getimage('folder'); #my $tlist = $mw->TList(-orient => 'vertical'); my $label = $mw->Label(-width=>15); my $hlist = $mw->HList( -itemtype => 'text', -separator => '/', -selectmode => 'single', -browsecmd => sub { my $file = shift; $label->configure(-text=> +$file); }); open (LST, "L:\\ceas\\Farringdon deployment\\Raj\\IED_IPB_TEST.CSV")|| +die "$^E : $!\n"; chomp (my @work_file=<LST>); for (@work_file) { my $data = {}; ($data->{business_unit}, $data->{group_name}, $data->{functions},) = split (/,/,$_); push (@winbcp_info, $data); } for my $text ( @winbcp_info ) { # $tlist->insert('end', -itemtype=>'imagetext', -image=>$image, -tex +t=>$text->{business_unit}); $hlist->add($text->{business_unit}, -text=>$text); }
And I have this bit of data
Dept Group Function IT, Projects, SAN/NAS, IT, Development, GUI, IT, Security, HR, Admin, West HR, Management, West Legal, Admin, FirmWide, Legal, Compliance,
How can I present this data in a Hierarchical folder presentation?

I have tried TList and HList as you see above but they did not work - The Tlist listed all the data in Hexadecimal format. While the HList failed to display anything.

Is there a way where I can present the data in Hierarchical format, similar to DirTree does? Moreover, how can I do this (with DirTree I can change Directory like this; $tk{dir_tree}->chdir( $dr{PATH} ); however I am not sure on how to do this with a list of hashes)?

This is one vital bit of Perl/Tk that I need urgently to know how its done Please.

Thanks In advance

Blackadder

Replies are listed 'Best First'.
Re: Displaying a list of hashes in TK in a Hierarchical folder presentation
by Crian (Curate) on Sep 14, 2004 at 10:50 UTC

    Here is an example for HList:

    use Tk; use Tk::HList; $top = new MainWindow; $hlist = $top->Scrolled("HList", -header => 1, -columns => 4, -scrollbars => 'osoe', -width => 70, -selectbackground => 'SeaGreen3', )->pack(-expand => 1, -fill => 'both'); $hlist->header('create', 0, -text => 'From'); $hlist->header('create', 1, -text => 'Subject'); $hlist->header('create', 2, -text => 'Date'); $hlist->header('create', 3, -text => 'Size'); $hlist->add(0); $hlist->itemCreate(0, 0, -text => "test\@email.de"); $hlist->itemCreate(0, 1, -text => "Re: HList?"); $hlist->itemCreate(0, 2, -text => "1999-11-20"); $hlist->itemCreate(0, 3, -text => "1432"); $hlist->add(1); $hlist->itemCreate(1, 0, -text => "dummy\@foo.com"); $hlist->itemCreate(1, 1, -text => "Re: HList?"); $hlist->itemCreate(1, 2, -text => "1999-11-21"); $hlist->itemCreate(1, 3, -text => "2335"); MainLoop();

    You can leave some column values blank for hierachical purpose.

    And here is how it looks like: link

    Here is an other example, not fine, but with hierachical structure:

    #!/usr/bin/perl use strict; use warnings; use diagnostics; use Tk; require Tk::HList; my $top = MainWindow->new(-title=>"FileSelector"); my $h = $top->Scrolled('HList', -drawbranch => 1, -separator => '/', -indent => 15, -command => \&show_or_hide_dir, ) ->pack(-fill => 'both', -expand => 'y', ); my $xpm = <<'END'; /* XPM */ static char *test[]={ "32 32 11 1", ". c None", "# c #000000", "h c #004000", "g c #004040", "f c #404000", "e c #808080", "i c #a0a0a4", "c c #c0c000", "d c #ffff00", "b c #ffffc0", "a c #ffffff", "................................", "................................", "................................", "................................", ".............#....###...........", "............#a##.#aba##.........", "...........#aaaa#aaaaaa##.......", "..........#aaaa#aaaaaaaba##.....", ".........#aaaa#aaaaaaaaaaab##...", "........#aaba#aaaaaaabaabaaaa##.", ".......#aaba#baaaaa#baaaaaabaaa#", "......#aaaa#aaaaab#a##baaaaaaa#.", ".....#aaba#aacbba#aaaa##baaab#..", "....#bbaa#abaacc#aaaaaaa##aa#...", "...#bbbb#aaabaa#aaabaaaaaa##....", "..#bbbb#bacaaa#aaaaaaaabaaaa##..", ".#bbbb#bbaacc#aacaaaaaaaaaaaba#.", "#ddbb#bbbbba#aaaaccaaaaaaaaaaaa#", "#edddfgcbbbfaacaaaaccaaaaaaaaa#e", ".#hedddfhcfabaaccaaabccaaaaaa#e.", "...##edddhaacbbaaccbaaaccaab#i..", ".....##e#baaaccabaaccbaabaa#i...", "......##bacbaabccbaaaccabb#e....", "......#bbbbccaabbccaaaaab#i.....", ".....#bbbbbbbccabbaccaab#i......", ".....#ebbbbbbbbccbaabba#i.......", "......##ebbbbbbbbccaabhe........", "........##ebbbbbbbbbb#e.........", "..........##ibbbbbbbhe..........", "............##ebbbb#e...........", "..............#hee#i............", "................##i............."}; END my %icons; #$icons{"open"} = $top->Bitmap(-file => './open_folder.xbm'); #$icons{"closed"} = $top->Bitmap(-file => './folder.xbm'); $icons{"open"} = $top->Pixmap(-data => $xpm); $icons{"closed"} = $top->Pixmap(-data => $xpm); #show_or_hide_dir("c:\\programme"); show_or_hide_dir(@ARGV); #show_or_hide_dir("p:"); #show_or_hide_dir("/temp"); MainLoop(); #--------------------------------------------------------------------- +-- sub show_or_hide_dir { my $path = $_[0]; print "PATH:".$path; return if (! -d $path); if ($h->info('exists', $path)) { my $next_entry = $h->info('next', $path); if (!$next_entry || (index ($next_entry, "$path/") == -1)) { $h->entryconfigure($path, '-image' => $icons{"open"}); add_dir_contents($path); my $path1 = $path; my $path2 = $path; my @du = ("du", "-b", "-h", $path1, $path2); my $dirSize = system(@du) == 0 or die "system @du failed: +$?"; } else { $h->entryconfigure($path, '-image' => $icons{"closed"}); $h->delete('offsprings', $path); } } else { die "'$path' is not a directory\n" if (! -d $path); $h->add($path, -itemtype => 'imagetext', -image => $icons{"open"}, -text => $path, ); add_dir_contents($path); } } sub add_dir_contents { my $path = $_[0]; my $oldcursor = $top->cget('-cursor'); $top->configure(-cursor => 'watch'); $top->update(); my @files = <$path/*>; foreach my $file (@files) { $file =~ s|//|/|g; #$file =~ /^\s*$/; print "FILE:".$file."\n\n"; (my $text = $file) =~ s|^.*/||g; if (-d $file) { $h->add($file, -itemtype => 'imagetext', -image => $icons{"closed"}, -text => $text, ); } else { $h->add($file, -itemtype => 'text', -text => $text, ); } } $top->configure(-cursor => $oldcursor); } # sub add_dir_contents

    Here is a possible solution:

    #!/usr/bin/perl use strict; use warnings; use Tk; use Tk::HList; my @data; while (<DATA>) { next if m~^\s*$~; my ($bu, $gn, $fu) = split /,/; s~^\s+|\s+$~~g for ($bu, $gn, $fu); push @data, {business_unit => $bu, group_name => $gn, functions => $fu, }; } @data = sort { $a->{business_unit} cmp $b->{business_unit}} @data; my $top = new MainWindow; my $hlist = $top->Scrolled("HList", -header => 1, -columns => 4, -scrollbars => 'osoe', -width => 70, -selectbackground => 'SeaGreen3', ) ->pack(-expand => 1, -fill => 'both', ); { my $count = 0; for my $key (qw/business_unit group_name functions/) { $hlist->header('create', $count++, -text => $data[0]->{$key}); } } { my $count = 0; my $old = ''; for my $d (@data[1..$#data]) { $hlist->add($count); if ($old ne $d->{business_unit}) { my $count2 = 0; for my $key (qw/business_unit group_name functions/) { $hlist->itemCreate($count, $count2++, -text => $d->{$k +ey}); } } else { my $count2 = 1; for my $key (qw/group_name functions/) { $hlist->itemCreate($count, $count2++, -text => $d->{$k +ey}); } } ++$count; $old = $d->{business_unit}; } } MainLoop(); __DATA__ Dept, Group, Function IT, Projects, SAN/NAS, IT, Development, GUI, IT, Security, HR, Admin, West HR, Management, West Legal, Admin, FirmWide, Legal, Compliance,
      This is very Good to know,...I will be needing to represent some other data in a table form soon,...Thanks for this but What I need is a way to represent the data in a directory tree like hierrachy structure, not a table. Extactly like DirTree does with a given directory but instead of file directories, I have my Business units, groups and functions.

      Is this possible in Perl.Tk!!!!
      Blackadder
Re: Displaying a list of hashes in TK in a Hierarchical folder presentation
by zejames (Hermit) on Sep 14, 2004 at 11:08 UTC
    Here is a solution to your problem :

    use strict; use vars qw/%hash/; use Tk; use Tk::TList; use Tk::HList; my $mw = MainWindow->new(); my $image = $mw->Getimage('folder'); my $tlist = $mw->TList(-orient => 'vertical'); my $label = $mw->Label(-width=>15); my $hlist = $mw->HList( -itemtype => 'text', -separator => '!', -selectmode => 'single', -browsecmd => sub { my $file = shift; $label->configure(-text=> +$file); }); chomp (my @work_file=<DATA>); for (@work_file) { next if ($_ !~ m!,!); @data = split (/[,\s]+/,$_); $ref = \%hash; foreach (@data) { $ref->{$_} = {} if (not defined $ref->{$_}) $ref = $ref->{$_}; } } foreach my $bu (keys %hash) { $hlist->add($bu, -text=>$bu); foreach my $group (keys %{$hash{$bu}}) { $hlist->add("$bu!$group", -text => $group); foreach my $function (keys %{$hash{$bu}->{$group}}) { $hlist->add("$bu!$group!$function", -text => $function); } } } $hlist->pack; $label->pack; MainLoop; __DATA__ Dept Group Function IT, Projects, SAN/NAS IT, Development, GUI IT, Security, HR, Admin, West HR, Management, West Legal, Admin, FirmWide Legal, Compliance,

    There are several things to say :

    • Be careful of the hlist separator, which you chose to be '/', whereas some of your data contains such a character. In my script, I've chosen '!' to be the hlist separator. It is used to build the tree. The '/' is classical as it corresponds to a file system tree.
    • I use 'use Tk;' to import the whole functions of the module.
    • I use a hash reference to build a internal representation of your tree and then go through it to be the hlist

    Some things should be improved though. For example, one could use only one pass to create the hlist, that is build the hash and the hlist is the same loop.

    HTH

    --
    zejames
      Thats cool,...But still not what I am after,...

      If I create a folder on my C drive and call it IT, then inside this folder I create as many folders as as IT has Groups (i.e. I'd creat a folder for Projects, Development,...etc) then inside all these sub folders I would create as many folders as IT Group functions have (i.e. inside Projects folder I create a folder for SAN/NAS and inside developments folder I'd create a folder GUI,...etc.) Then finallt, I'd use Tk::DirTree to represent those folder. This is the way I am after. Is this possible to achieve with some help from you Guys?

      I am sweating over it now guys.

      Thanks
      Blackadder
        In fact that is what my code do. Could you tell us why it does not fit your needs ?

        Kind regards

        --
        zejames