AW: Q: add and remove wheels dynamically

"Alex" <[email protected]> Sun, 22 Jul 2012 10:34:00 +0200
Newsgroups gmane.comp.lang.perl.poe
Message-ID <[email protected]>
------=_NextPart_000_0001_01CD67F5.8222A750
Content-Type: text/plain;
	charset="iso-8859-1"
Content-Transfer-Encoding: quoted-printable

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

=3Dhead1 NAME

apacheLogParser_tk.pl - a programm to watch files

=3Dhead1 DESCRIPTION

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

=3Dcut

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

use vars qw($VERSION);
$VERSION =3D 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 =3D [
	File::Spec->catfile(qw(c: Apache logs error.log)),
	#File::Spec->catfile(qw(c: Apache logs access.log)), ];

# Dubletten entfernen
my %seen =3D ();
@{$logdateien} =3D 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 =3D>
      { _start      =3D> \&ui_start,
        ev_count    =3D> \&ui_count,
        ev_clear    =3D> \&ui_clear,
        got_line    =3D> \&updateLog_line,
        got_error   =3D> \&updateLog_error,
      },
      args =3D> \@{$logdateien},
  );

# Run the program until it is exited.

$poe_kernel->run();
exit 0;




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

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




=3Dhead2 METHODEN

=3Dhead3 ui_start

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

=3Dcut

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

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

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

    my $menuitems =3D [
        [Cascade =3D> "~File", -menuitems =3D>
            [
                [Button =3D> "~Add file", -command =3D> sub{
                    my $file =3D =
$poe_main_window->getOpenFile(-filetypes =3D>
$log_file_types);
                    if( $file ) {
                        # Eine Datei wurde ausgew=E4hlt. Diese soll nun =
auch
geloggt werden.
                        push @{$logdateien}, $file;
                        add_file_to_watchlist( $heap, $file );
                        print Dumper $heap->{wheel}->{$file};
                    }
                    return 1;
                }],
                [Button =3D> "~Remove file", -command =3D> sub{
                    my $aktuelle_seite =3D $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 =3D> ""],
                [Button =3D> "~Beenden", -command =3D> sub{ exit(0); =
return 1;
}],
            ],
        ],
    ];
    my $menu =3D $poe_main_window->Menu(-menuitems =3D> $menuitems);
    $poe_main_window->configure(-menu =3D> $menu);
   =20
    # Loop starten
    $kernel->yield("ev_count");
} # /ui_start




=3Dhead3 ui_count

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

=3Dcut

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




=3Dhead3 ui_clear

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

=3Dcut

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




=3Dhead3 updateLog_line

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

=3Dcut

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

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

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

} # /updateLog_line




=3Dhead3 updateLog_error

No idea what this is about

=3Dcut

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

-----Urspr=FCngliche Nachricht-----
Von: Rocco Caputo [mailto:[email protected]]=20
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 <[email protected]>

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

> Hi!
>=20
> I have written a small Tk GUI that follows some log files. I would=20
> 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=20
> items for
> this:
>=20
> [snip]
>    my $logfiles =3D [ ... ]; # my personal list of files
>=20
>    my $log_file_types =3D [
>        ['Log Files',       ['.log', '.txt']],
>        ['All Files',        '*',           ],
>    ];
>=20
>    my $menuitems =3D [
>        [Cascade =3D> "~Datei", -menuitems =3D>
>            [
>                [Button =3D> "~Add file", -command =3D> sub{
>                    my $file =3D =
$poe_main_window->getOpenFile(-filetypes=20
> =3D> $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 =3D> "~Remove file", -command =3D> sub{
>                        my $ident =3D magic_way_to_get_this();
>                        delete $heap->{wheel}->{$ident};
>                    }
>                    return 1;
>                }],
>                [Separator =3D> ""],
>                [Button =3D> "~Exit program", -command =3D> sub{ =
exit(0);=20
> return 1; }],
>            ],
>        ],
>    ];
>    my $menu =3D $poe_main_window->Menu(-menuitems =3D> $menuitems);
>    $poe_main_window->configure(-menu =3D> $menu);
>=20
> sub add_file_to_watchlist {
>    my ($heap, $logfile) =3D @_;
>=20
>    # this ethod is called during the initial set-up, too.
>    # some stuff here...
>=20
>    # -- create new wheel
>    $heap->{wheel}->{$logdatei} =3D POE::Wheel::FollowTail->new(
>        Filename   =3D> $ logfile,
>        InputEvent =3D> 'got_line',
>        ErrorEvent =3D> 'got_error',
>        SeekBack   =3D> 1024,
>    );
>=20
>    return;
> } # /add_file_to_watchlist
>    [/snip]
>=20
> However, when I remove a file and add it again, it's not followed. If=20
> I add another file, it's not followed either.
> How do I do this? Is it possible?
>=20
> The code (the uncut version) works fine when the program starts up.=20
> Only adding files after the event loop has started doesn't work. Why?
>=20
> 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?
>=20
> Best regards,
> Alex
>=20

-----
E-Mail ist virenfrei.
Von AVG =FCberpr=FCft - www.avg.de
Version: 2012.0.2180 / Virendatenbank: 2433/5067 - Ausgabedatum: =
13.06.2012=20

------=_NextPart_000_0001_01CD67F5.8222A750
Content-Type: text/plain;
	name="apache_log_parser_en-wip.pl.txt"
Content-Transfer-Encoding: quoted-printable
Content-Disposition: attachment;
	filename="apache_log_parser_en-wip.pl.txt"

#!perl

=3Dhead1 NAME

apacheLogParser_tk.pl - a programm to watch files

=3Dhead1 DESCRIPTION

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

=3Dcut

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

use vars qw($VERSION);
$VERSION =3D 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 =3D [
	File::Spec->catfile(qw(c: Apache logs error.log)),
	#File::Spec->catfile(qw(c: Apache logs access.log)),
];

# Dubletten entfernen
my %seen =3D ();
@{$logdateien} =3D 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 =3D>
      { _start      =3D> \&ui_start,
        ev_count    =3D> \&ui_count,
        ev_clear    =3D> \&ui_clear,
        got_line    =3D> \&updateLog_line,
        got_error   =3D> \&updateLog_error,
      },
      args =3D> \@{$logdateien},
  );

# Run the program until it is exited.

$poe_kernel->run();
exit 0;




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

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




=3Dhead2 METHODEN

=3Dhead3 ui_start

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

=3Dcut

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

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

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

    my $menuitems =3D [
        [Cascade =3D> "~File", -menuitems =3D>
            [
                [Button =3D> "~Add file", -command =3D> sub{
                    my $file =3D =
$poe_main_window->getOpenFile(-filetypes =3D> $log_file_types);
                    if( $file ) {
                        # Eine Datei wurde ausgew=C3=A4hlt. Diese soll =
nun auch geloggt werden.
                        push @{$logdateien}, $file;
                        add_file_to_watchlist( $heap, $file );
                        print Dumper $heap->{wheel}->{$file};
                    }
                    return 1;
                }],
                [Button =3D> "~Remove file", -command =3D> sub{
                    my $aktuelle_seite =3D $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 =3D> ""],
                [Button =3D> "~Beenden", -command =3D> sub{ exit(0); =
return 1; }],
            ],
        ],
    ];
    my $menu =3D $poe_main_window->Menu(-menuitems =3D> $menuitems);
    $poe_main_window->configure(-menu =3D> $menu);
   =20
    # Loop starten
    $kernel->yield("ev_count");
} # /ui_start




=3Dhead3 ui_count

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

=3Dcut

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




=3Dhead3 ui_clear

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

=3Dcut

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




=3Dhead3 updateLog_line

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

=3Dcut

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

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

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

} # /updateLog_line




=3Dhead3 updateLog_error

No idea what this is about

=3Dcut

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



------=_NextPart_000_0001_01CD67F5.8222A750--