Hi!

I just notices that I replied to one person only. Maybe there is someone on
the list who can help me further. I'm still stuck with the problem :-(

The term "to run locally" matches my script. Please find the script below.
(NB: The script is intended for the German Perl Community, so there were
german comments and variable names only. I translated most of them, but
there surely are some left.)

Basically, a Tk main window is created with a menu, a notebook with tabs for
each watched file and a giant textarea for each file.
Using the menu, you can remove and add files.

I'm using ActiveState Perl and it's Tk. If you are using another Tk, I think
you have to adjust this line: use POE qw( Loop::TkActiveState
Wheel::FollowTail ); I don't know exactly how, I think you can simply omit
the Loop::TkActiveState.

Best regards,
Alex

[code]
#!perl

=head1 NAME

apacheLogParser_tk.pl - a programm to watch files

=head1 DESCRIPTION

Somewhere in this code, you can specify a list of files to be watched.
Search for "my $logdateien".

=cut

use strict;
use warnings;
use Config::Auto;
use Data::Dumper qw/Dumper/;
use File::Spec;
use utf8;

use vars qw($VERSION);
$VERSION = 0.3;

# Tk support is enabled if the Tk module is used before POE itself.
use Tk;
use Tk::ToolBar;
use Tk::StatusBar;

# except when it isn't...
#
# ActiveState does something funky such that if you don't include #
Loop::TkActiveState here Loop::Tk won't be detected.  The good news # is
that it does not appear to be necessary to special case this for # other
platforms.
#
# Are you using a non-ActiveState Perl? Then you have to adjust this line!
use POE qw( Loop::TkActiveState Wheel::FollowTail );

my $logdateien = [
        File::Spec->catfile(qw(c: Apache logs error.log)),
        #File::Spec->catfile(qw(c: Apache logs access.log)), ];

# Dubletten entfernen
my %seen = ();
@{$logdateien} = grep { ! $seen{ $_ }++ } @{$logdateien}; undef %seen;

foreach( @{$logdateien} ) {
    die "Logdatei [$_] existiert nicht!\n" unless -e $_; }

# Create the session that will drive the user interface.
POE::Session->create(
    inline_states =>
      { _start      => \&ui_start,
        ev_count    => \&ui_count,
        ev_clear    => \&ui_clear,
        got_line    => \&updateLog_line,
        got_error   => \&updateLog_error,
      },
      args => \@{$logdateien},
  );

# Run the program until it is exited.

$poe_kernel->run();
exit 0;




sub add_file_to_watchlist {
    my ($heap, $logdatei) = @_;
    
    $heap->{notebookSeiten}{$logdatei}{seite} =
$heap->{notebook}->add($logdatei, -label => $logdatei,);
    $heap->{notebookSeiten}{$logdatei}{scr_txt} =
$heap->{notebookSeiten}{$logdatei}{seite}->Scrolled(
        Text => -scrollbars => 'se',
    )->pack(-expand => 1, -fill => 'both',);
    
    # -- Buttons
    $heap->{notebookSeiten}{$logdatei}{btn_frame} =
$heap->{notebookSeiten}{$logdatei}{seite}->Frame();
    $heap->{notebookSeiten}{$logdatei}{clear_btn} =
$heap->{notebookSeiten}{$logdatei}{btn_frame}->Button(
        -text => 'Anzeige leeren',
        -command => sub{
 
$heap->{notebookSeiten}{$logdatei}{scr_txt}->Subwidget('scrolled')->delete("
0.0", "end");
        },
    )->pack(-side => 'left',);
    $heap->{notebookSeiten}{$logdatei}{btn_frame}->pack(-side => 'left',);

    # -- create Wheel
    $heap->{wheel}->{$logdatei} = POE::Wheel::FollowTail->new(
        Filename   => $logdatei,
        InputEvent => 'got_line',
        ErrorEvent => 'got_error',
        SeekBack   => 1024,
    );
    
    return;
} # /add_file_to_watchlist




=head2 METHODEN

=head3 ui_start

Populate the GUI. For each file in \@logdateien, we create a new tab.

=cut

sub ui_start {
    my ( $kernel, $session, $heap ) = @_[ KERNEL, SESSION, HEAP ];

    # -- adjust window size
    die "could not create a main Tk window" unless defined $poe_main_window;
    $poe_main_window->configure(-width => 1280, -height => 480,);
    $poe_main_window->packPropagate(0);
    $poe_main_window->gridPropagate(0);
    
    # -- create Tk GUI
    require Tk::NoteBook;
    $heap->{notebook} = $poe_main_window->NoteBook();
    foreach my $logdatei ( @{$logdateien} ) {
        add_file_to_watchlist( $heap, $logdatei );
    }
    $heap->{notebook}->pack(-expand => 1, -fill => 'both',);
    
    
    # -- Statusbar
    #   -> for the UI-Counter
    $heap->{statusbar} = $poe_main_window->StatusBar();
    $heap->{statusbar}->addLabel(
        -relief         => 'flat',
        -text           => "Welcome to the statusbar",
    );
    
    $heap->{statusbar}->addLabel(
        -text           => 'Frame:',
        -width          => '10',
        -anchor         => 'center',
    );
    
    $heap->{statusbar}->addLabel(
        -width          => 20,
        -anchor         => 'center',
        -textvariable   => \$heap->{counter},
        -foreground     => 'blue',
    );
    
    $heap->{statusbar}->addLabel(
        -width          => 10,
        -anchor         => 'center',
        -text           => "Clear",
        -foreground     => 'blue',
        -command        => $session->postback("ev_clear"),
        -event          => '<Button-1>',
    );
    
    $heap->{first} = 0;

    # -- Menu erstellen
    $poe_main_window->update();
    my $log_file_types = [
        ['Log Files',       ['.log', '.txt']],
        ['All Files',        '*',           ],
    ];

    my $menuitems = [
        [Cascade => "~File", -menuitems =>
            [
                [Button => "~Add file", -command => sub{
                    my $file = $poe_main_window->getOpenFile(-filetypes =>
$log_file_types);
                    if( $file ) {
                        # Eine Datei wurde ausgewählt. Diese soll nun auch
geloggt werden.
                        push @{$logdateien}, $file;
                        add_file_to_watchlist( $heap, $file );
                        print Dumper $heap->{wheel}->{$file};
                    }
                    return 1;
                }],
                [Button => "~Remove file", -command => sub{
                    my $aktuelle_seite = $heap->{notebook}->raised();
                    if( $aktuelle_seite ) {
                        $heap->{notebook}->delete($aktuelle_seite);
                        delete $heap->{notebookSeiten}{$aktuelle_seite};
                        delete $heap->{wheel}->{$aktuelle_seite};
                        #die('doesn\'t work yet ;-(');
                    }
                    return 1;
                }],
                [Separator => ""],
                [Button => "~Beenden", -command => sub{ exit(0); return 1;
}],
            ],
        ],
    ];
    my $menu = $poe_main_window->Menu(-menuitems => $menuitems);
    $poe_main_window->configure(-menu => $menu);
    
    # Loop starten
    $kernel->yield("ev_count");
} # /ui_start




=head3 ui_count

Handle the "ev_count" event by increasing a counter and displaying its new
value.

=cut

sub ui_count {
    $_[HEAP]->{counter}++;
    $_[KERNEL]->yield("ev_count");
} # /ui_count




=head3 ui_clear

Handle the "ev_clear" event by clearing and redisplaying the counter.

=cut

sub ui_clear {
    $_[HEAP]->{counter} = 0;
} # /ui_clear




=head3 updateLog_line

Inserts the new lines from the watched file into the textare on the related
notebook tab.

=cut

sub updateLog_line {
    my ( $kernel, $session, $heap ) = @_[ KERNEL, SESSION, HEAP ];
    
    my $eingabe = $_[ARG0];

    my @eingaben = split m/\\r, /, $eingabe;    

    foreach my $eing ( @eingaben ) {
 
$heap->{notebookSeiten}{$logdateien->[($_[ARG1]-1)]}{scr_txt}->insert("end",
"normal: $eing\n") if $heap->{first}++;
    }

} # /updateLog_line




=head3 updateLog_error

No idea what this is about

=cut

sub updateLog_error {
    warn "$_[ARG0]\n";
} # /pdateLog_error
[/code]

-----Ursprüngliche Nachricht-----
Von: Rocco Caputo [mailto:rcap...@pobox.com] 
Gesendet: Mittwoch, 13. Juni 2012 22:24
An: POE Mailing List
Betreff: Re: Q: add and remove wheels dynamically

Can you reduce the program to something I can run locally to see what's
going on?  The parts you've quoted aren't enough context for me to answer
your question.

What you want to do should work fine.  So the best answer I have (with the
information you've given) is "you're doing... something... wrong."

--
Rocco Caputo <rcap...@pobox.com>

On Jun 12, 2012, at 16:10, Alex wrote:

> Hi!
> 
> I have written a small Tk GUI that follows some log files. I would 
> like to add the possibility to add and remove files on-the-fly.
> To do this, I added a menu where a user is provided with two menu 
> items for
> this:
> 
> [snip]
>    my $logfiles = [ ... ]; # my personal list of files
> 
>    my $log_file_types = [
>        ['Log Files',       ['.log', '.txt']],
>        ['All Files',        '*',           ],
>    ];
> 
>    my $menuitems = [
>        [Cascade => "~Datei", -menuitems =>
>            [
>                [Button => "~Add file", -command => sub{
>                    my $file = $poe_main_window->getOpenFile(-filetypes 
> => $log_file_types);
>                    if( $file ) {
>                        # A file has been selected to be followed
>                        push @{$logfiles}, $file;
>                        add_file_to_watchlist( $heap, $file );
>                    }
>                    return 1;
>                }],
>                [Button => "~Remove file", -command => sub{
>                        my $ident = magic_way_to_get_this();
>                        delete $heap->{wheel}->{$ident};
>                    }
>                    return 1;
>                }],
>                [Separator => ""],
>                [Button => "~Exit program", -command => sub{ exit(0); 
> return 1; }],
>            ],
>        ],
>    ];
>    my $menu = $poe_main_window->Menu(-menuitems => $menuitems);
>    $poe_main_window->configure(-menu => $menu);
> 
> sub add_file_to_watchlist {
>    my ($heap, $logfile) = @_;
> 
>    # this ethod is called during the initial set-up, too.
>    # some stuff here...
> 
>    # -- create new wheel
>    $heap->{wheel}->{$logdatei} = POE::Wheel::FollowTail->new(
>        Filename   => $ logfile,
>        InputEvent => 'got_line',
>        ErrorEvent => 'got_error',
>        SeekBack   => 1024,
>    );
> 
>    return;
> } # /add_file_to_watchlist
>    [/snip]
> 
> However, when I remove a file and add it again, it's not followed. If 
> I add another file, it's not followed either.
> How do I do this? Is it possible?
> 
> The code (the uncut version) works fine when the program starts up. 
> Only adding files after the event loop has started doesn't work. Why?
> 
> What is the proper way of saying: "hey Perl, stop following that file" 
> and "hey Perl, start following this file" while the POE event loop is
running?
> 
> Best regards,
> Alex
> 

-----
E-Mail ist virenfrei.
Von AVG überprüft - www.avg.de
Version: 2012.0.2180 / Virendatenbank: 2433/5067 - Ausgabedatum: 13.06.2012 
#!perl

=head1 NAME

apacheLogParser_tk.pl - a programm to watch files

=head1 DESCRIPTION

Somewhere in this code, you can specify a list of files to be watched. Search 
for "my $logdateien".

=cut

use strict;
use warnings;
use Config::Auto;
use Data::Dumper qw/Dumper/;
use File::Spec;
use utf8;

use vars qw($VERSION);
$VERSION = 0.3;

# Tk support is enabled if the Tk module is used before POE itself.
use Tk;
use Tk::ToolBar;
use Tk::StatusBar;

# except when it isn't...
#
# ActiveState does something funky such that if you don't include
# Loop::TkActiveState here Loop::Tk won't be detected.  The good news
# is that it does not appear to be necessary to special case this for
# other platforms.
#
# Are you using a non-ActiveState Perl? Then you have to adjust this line!
use POE qw( Loop::TkActiveState Wheel::FollowTail );

my $logdateien = [
        File::Spec->catfile(qw(c: Apache logs error.log)),
        #File::Spec->catfile(qw(c: Apache logs access.log)),
];

# Dubletten entfernen
my %seen = ();
@{$logdateien} = grep { ! $seen{ $_ }++ } @{$logdateien};
undef %seen;

foreach( @{$logdateien} ) {
    die "Logdatei [$_] existiert nicht!\n" unless -e $_;
}

# Create the session that will drive the user interface.
POE::Session->create(
    inline_states =>
      { _start      => \&ui_start,
        ev_count    => \&ui_count,
        ev_clear    => \&ui_clear,
        got_line    => \&updateLog_line,
        got_error   => \&updateLog_error,
      },
      args => \@{$logdateien},
  );

# Run the program until it is exited.

$poe_kernel->run();
exit 0;




sub add_file_to_watchlist {
    my ($heap, $logdatei) = @_;
    
    $heap->{notebookSeiten}{$logdatei}{seite} = 
$heap->{notebook}->add($logdatei, -label => $logdatei,);
    $heap->{notebookSeiten}{$logdatei}{scr_txt} = 
$heap->{notebookSeiten}{$logdatei}{seite}->Scrolled(
        Text => -scrollbars => 'se',
    )->pack(-expand => 1, -fill => 'both',);
    
    # -- Buttons
    $heap->{notebookSeiten}{$logdatei}{btn_frame} = 
$heap->{notebookSeiten}{$logdatei}{seite}->Frame();
    $heap->{notebookSeiten}{$logdatei}{clear_btn} = 
$heap->{notebookSeiten}{$logdatei}{btn_frame}->Button(
        -text => 'Anzeige leeren',
        -command => sub{
            
$heap->{notebookSeiten}{$logdatei}{scr_txt}->Subwidget('scrolled')->delete("0.0",
 "end");
        },
    )->pack(-side => 'left',);
    $heap->{notebookSeiten}{$logdatei}{btn_frame}->pack(-side => 'left',);

    # -- create Wheel
    $heap->{wheel}->{$logdatei} = POE::Wheel::FollowTail->new(
        Filename   => $logdatei,
        InputEvent => 'got_line',
        ErrorEvent => 'got_error',
        SeekBack   => 1024,
    );
    
    return;
} # /add_file_to_watchlist




=head2 METHODEN

=head3 ui_start

Populate the GUI. For each file in \@logdateien, we create a new tab.

=cut

sub ui_start {
    my ( $kernel, $session, $heap ) = @_[ KERNEL, SESSION, HEAP ];

    # -- adjust window size
    die "could not create a main Tk window" unless defined $poe_main_window;
    $poe_main_window->configure(-width => 1280, -height => 480,);
    $poe_main_window->packPropagate(0);
    $poe_main_window->gridPropagate(0);
    
    # -- create Tk GUI
    require Tk::NoteBook;
    $heap->{notebook} = $poe_main_window->NoteBook();
    foreach my $logdatei ( @{$logdateien} ) {
        add_file_to_watchlist( $heap, $logdatei );
    }
    $heap->{notebook}->pack(-expand => 1, -fill => 'both',);
    
    
    # -- Statusbar
    #   -> for the UI-Counter
    $heap->{statusbar} = $poe_main_window->StatusBar();
    $heap->{statusbar}->addLabel(
        -relief         => 'flat',
        -text           => "Welcome to the statusbar",
    );
    
    $heap->{statusbar}->addLabel(
        -text           => 'Frame:',
        -width          => '10',
        -anchor         => 'center',
    );
    
    $heap->{statusbar}->addLabel(
        -width          => 20,
        -anchor         => 'center',
        -textvariable   => \$heap->{counter},
        -foreground     => 'blue',
    );
    
    $heap->{statusbar}->addLabel(
        -width          => 10,
        -anchor         => 'center',
        -text           => "Clear",
        -foreground     => 'blue',
        -command        => $session->postback("ev_clear"),
        -event          => '<Button-1>',
    );
    
    $heap->{first} = 0;

    # -- Menu erstellen
    $poe_main_window->update();
    my $log_file_types = [
        ['Log Files',       ['.log', '.txt']],
        ['All Files',        '*',           ],
    ];

    my $menuitems = [
        [Cascade => "~File", -menuitems =>
            [
                [Button => "~Add file", -command => sub{
                    my $file = $poe_main_window->getOpenFile(-filetypes => 
$log_file_types);
                    if( $file ) {
                        # Eine Datei wurde ausgewählt. Diese soll nun auch 
geloggt werden.
                        push @{$logdateien}, $file;
                        add_file_to_watchlist( $heap, $file );
                        print Dumper $heap->{wheel}->{$file};
                    }
                    return 1;
                }],
                [Button => "~Remove file", -command => sub{
                    my $aktuelle_seite = $heap->{notebook}->raised();
                    if( $aktuelle_seite ) {
                        $heap->{notebook}->delete($aktuelle_seite);
                        delete $heap->{notebookSeiten}{$aktuelle_seite};
                        delete $heap->{wheel}->{$aktuelle_seite};
                        #die('doesn\'t work yet ;-(');
                    }
                    return 1;
                }],
                [Separator => ""],
                [Button => "~Beenden", -command => sub{ exit(0); return 1; }],
            ],
        ],
    ];
    my $menu = $poe_main_window->Menu(-menuitems => $menuitems);
    $poe_main_window->configure(-menu => $menu);
    
    # Loop starten
    $kernel->yield("ev_count");
} # /ui_start




=head3 ui_count

Handle the "ev_count" event by increasing a counter and displaying
its new value.

=cut

sub ui_count {
    $_[HEAP]->{counter}++;
    $_[KERNEL]->yield("ev_count");
} # /ui_count




=head3 ui_clear

Handle the "ev_clear" event by clearing and redisplaying the counter.

=cut

sub ui_clear {
    $_[HEAP]->{counter} = 0;
} # /ui_clear




=head3 updateLog_line

Inserts the new lines from the watched file into the textare on the related 
notebook tab.

=cut

sub updateLog_line {
    my ( $kernel, $session, $heap ) = @_[ KERNEL, SESSION, HEAP ];
    
    my $eingabe = $_[ARG0];

    my @eingaben = split m/\\r, /, $eingabe;    

    foreach my $eing ( @eingaben ) {
        
$heap->{notebookSeiten}{$logdateien->[($_[ARG1]-1)]}{scr_txt}->insert("end", 
"normal: $eing\n") if $heap->{first}++;
    }

} # /updateLog_line




=head3 updateLog_error

No idea what this is about

=cut

sub updateLog_error {
    warn "$_[ARG0]\n";
} # /pdateLog_error


Reply via email to