Gtk2-Ex-TickerView
view release on metacpan or search on metacpan
examples/poe-yahoo-quotes.pl view on Meta::CPAN
like the C library etc does. (Or if the first there is a local name server
then make sure it forwards somewhere for hostnames it doesn't handle.)
The only tricky bit for POE and Gtk together is to note that some POE things
can only be done from within a POE "current session". So the HTTP request
in refresh_start() can't be initiated directly from the $refresh_button Gtk
signal handler, instead that signal handler must POE::Kernel->post() a POE
event which is queued and then from the main loop is dispatched to
'refresh_start' in $session. $session->postback creates an anonymous subr
which does the post() -- it's a convenient way to create that glue when you
don't need anything else in the Gtk handler.
POE HTTP is happy to send out multiple requests simultaneously and if you
click the Refresh button a few times fast then that's what you get. In a
real program you might want only one refresh in progress, or some limit on
them. If you set $refresh_button to insensitive with
$refresh_button->set_sensitive(0) then it stops the user clicking again,
though as of Gtk 2.12 there's a long standing Gtk bug where if the mouse is
in the button when you turn it back sensitive again then clicking does
nothing until the user moves out and back in. (Botched maintenance of the
"armed" ready-to-click.)
=head1 SEE ALSO
L<Gtk2::Ex::TickerView>,
L<POE>,
L<POE::Component::Client::HTTP>,
L<POE::Component::Client::DNS>
=cut
#-----------------------------------------------------------------------------
use strict;
use warnings;
use Gtk2 '-init';
use Gtk2::Ex::TickerView;
use POE 'Loop::Glib';
use URI::Escape;
my @symbols = ('^FTSE', 'GM', 'BHP.AX', 'TSCO.L', 'XAUUSD=X', 'CLZ11.NYM');
if (@ARGV) {
@symbols = @ARGV;
}
# "f=" format is
# s symbol
# l1 last price
# c1 change from yesterday's close
#
my $url = 'http://download.finance.yahoo.com/d/quotes.csv?f=sl1c1&e=.csv&s='
. join(',', map {URI::Escape::uri_escape($_)} @symbols);
print "Yahoo URL $url\n";
#-----------------------------------------------------------------------------
# $session is the toplevel POE session. Posting 'refresh_start' to it
# starts a refresh of the quotes. 'refresh_response' receives its callbacks
# from the HTTP component.
#
# $session is kept alive by the postback() held in the $refresh_button,
# otherwise session_start() would want to refcount_increment(). Because
# $refresh_button is in a global variable it in turn stays alive forever,
# hence the use of UIDESTROY in the $toplevel widget destroy handler to shut
# down everything.
#
my $session = POE::Session->create
(inline_states => { _start => \&session_start,
refresh_start => \&refresh_start,
refresh_response => \&refresh_response,
});
#-----------------------------------------------------------------------------
my $toplevel = Gtk2::Window->new('toplevel');
$toplevel->set_default_size (350, -1);
$toplevel->signal_connect
(destroy => sub { POE::Kernel->signal ($session, 'UIDESTROY') });
# column 0 is the symbol, column 1 the displayed symbol+price+change string
my $liststore = Gtk2::ListStore->new ('Glib::String', 'Glib::String');
foreach my $symbol (@symbols) {
$liststore->set ($liststore->append, 0=>$symbol, 1=>"$symbol ...");
}
my $vbox = Gtk2::VBox->new;
$toplevel->add ($vbox);
my $ticker = Gtk2::Ex::TickerView->new (model => $liststore);
$vbox->pack_start ($ticker, 1,1,0);
my $renderer = Gtk2::CellRendererText->new;
$renderer->set (background => 'black',
foreground => 'white',
xpad => 8);
$ticker->pack_start ($renderer, 0);
$ticker->set_attributes ($renderer, text => 1); # display column 1
my $hbox = Gtk2::HBox->new;
$vbox->pack_start ($hbox, 1,1,0);
my $refresh_button = Gtk2::Button->new_from_stock ('gtk-refresh');
$hbox->pack_start ($refresh_button, 0,0,0);
$refresh_button->signal_connect
(clicked => $session->postback('refresh_start'));
my $quit_button = Gtk2::Button->new_from_stock ('gtk-quit');
$hbox->pack_start ($quit_button, 0,0,0);
$quit_button->signal_connect (clicked => sub { $toplevel->destroy });
my $status_label = Gtk2::Label->new;
$hbox->pack_start ($status_label, 1,1,0);
#-----------------------------------------------------------------------------
my $http_created;
sub session_start {
my $kernel = $_[KERNEL];
$kernel->delay('refresh_start', 1); # initial refresh after 1 second
}
sub refresh_start {
my ($kernel) = $_[KERNEL];
( run in 0.461 second using v1.01-cache-2.11-cpan-39bf76dae61 )