strange behaviour with p_bar update



Hi all..

I've got a perl script that reads in the output from running another
program and displays it in a textview within a scrolled window. 

There is also a fixed-time progress bar that runs for a certain period
of time whenever the external program is called. When I detect the
external program has finished or caused an error, I call the progress
bar update function with an argument to remove itself from being called
again and again. (i.e return FALSE)

It _does not_ work, the progress bar continues to get updated. I'm sure
there is a way to do what I want. Can somebody shed some light?

start-test.pl::
#!/usr/bin/perl -w

use Data::Dumper;
use FindBin;
use Glib 1.040, qw(TRUE FALSE);
use Gtk2 -init;

use IO::File;

# if( $> ) {
#       die "Sorry only root must execute $FindBin::Script\n\n" unless (-r
$device && -w $device);
# }

# create the main window
my $window = Gtk2::Window->new;
$window->signal_connect(delete_event => sub{exit});
$window->set_resizable( FALSE );
$window->set_size_request( 400, 300 );
$window->set_title("FlashGTK ;)");

# add vbox to contain the SW and button
my $vbox = Gtk2::VBox->new;
$window->add($vbox);

# add a combobox with the device list
#my $model = Gtk2::ListStore->new( 'Glib::String' );
#foreach (qw!/dev/sda /dev/sdb /dev/sdc /dev/sdd!) {
#       $model->set( $model->append, 0, $_ );
#}

#my $combo = Gtk2::ComboBox->new( $model );
my $combo = Gtk2::ComboBox->new_text;
$combo->append_text( '/dev/sda' );
$combo->append_text( '/dev/sdb' );
$combo->append_text( '/dev/sdc' );
$combo->append_text( '/dev/sdd' );
$combo->set_active( 0 );
$vbox->pack_start( $combo, FALSE, FALSE, 0 );

# SW container and textview inside it
my $scroller = Gtk2::ScrolledWindow->new;
$vbox->pack_start( $scroller, TRUE, TRUE, 0 );
my $textview = Gtk2::TextView->new;
my $buffer = $textview->get_buffer;
my $end_marker = $buffer->create_mark('end', $buffer->get_end_iter,
FALSE);
$buffer->signal_connect(insert_text => sub{
#               $textview->scroll_to_mark($buffer->get_mark('end'), 0.0, TRUE, 0,
0.5);
                $textview->scroll_mark_onscreen( $end_marker );
        });
$scroller->add($textview);

# progress bar
my $pbar = Gtk2::ProgressBar->new();
$vbox->pack_start( $pbar, FALSE, FALSE, 0 );

# GO button
my $button = Gtk2::Button->new('go');
$button->signal_connect(clicked => \&button_handler);
$vbox->pack_start($button, FALSE, FALSE, 0);

# show window and start the gtk main loop
$window->show_all;
Gtk2->main;
exit;

sub button_handler()
{
        $button->set_sensitive(FALSE);
        Glib::Timeout->add( 120, \&pbar_update );
        $pbar->set_text( "...flashing..." );
#       Gtk2->main_iteration while Gtk2->events_pending;

        my $buff = $textview->get_buffer;
        $buff->insert($buff->get_end_iter, "Starting installation...\n");


        my $fh = new IO::File;
        my $pid = $fh->open( "-|" );
        die "fork failed:: $!\n" unless defined $pid;

        if( $pid == 0 )
        {
                # child
#               open $chfh, "unbuffer ./instflash|";
                open $chfh, "unbuffer false|";
                while( !eof($chfh) )
                {
                        my $data = <$chfh>;

                        if( defined $data )
                        {
                                print "Perl:: $data";
                        }
                }

                close( $chfh );
                exit;
        }
        else
        {
                # parent
                Glib::IO->add_watch( fileno $fh, [qw/in hup err/], \&watch_callback,
$fh );
        }
}


sub pbar_update
{
        my $arg = shift;
#       print "\$arg==>$arg<==\n";

#       return FALSE if defined( $arg );

        my $newval = $pbar->get_fraction + 0.005;
        $newval = 2 if defined( $arg );
        print "\$newval ==> $newval\n";
        if( $newval > 1.0 )
        {
                $button->set_sensitive( TRUE );
                $pbar->set_fraction( 0 );
                $pbar->set_text( " " );
                return FALSE;
        }

        $pbar->set_fraction( $newval );
        return TRUE;
}

sub watch_callback
{
        my ($fd, $condition, $fh) = @_;

        if( $condition >= 'in' )
        {
                my $data = <$fh>;
                if( defined $data )
                {
                        my $buffer = $textview->get_buffer;
                        $buffer->insert( $buffer->get_end_iter, $data );
                }
        }

        if( $condition >= 'hup' or $condition >= 'err' )
        {
                pbar_update( 'stop' );
                $fh->close;
                $fh = undef;
        }

        if( $fh )
        {
                return TRUE;
        }
        else
        {
                return FALSE;
        }
}
::end-test.pl

Currently I'm exec'ing /bin/false which returns unsuccessfully
immediately. hence i should see my progress bar stop as soon as it
starts. I can see the button being set to sensitive when the external
program finishes, just the progress bar doesn't stop.

For those who think using /bin/false is a bad idea, a simple script like
this will suffice::
#!/bin/bash
echo "blah blah"
sleep 5
/bin/false
# exit -2 <-- this'll work too

Regards,
Imran




[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]