#!/usr/bin/perl -w
#
# yarssr - Yet Another RSS Reader
# Copyright (C) 2004 Lee Aylward <lee@laylward.com>
# http://yarssr.sourceforge.net
# Licensed under the GPL
#

use strict;
use XML::RSS qw( parse );
use Gtk2::TrayIcon;
use Gtk2::GladeXML;
use Gtk2::SimpleList;
use Gnome2::VFS;
use Gnome2;
use Carp;

croak("your version the Gnome2 perl module is old, you need > 0.94")
	if $Gnome2::VERSION < 0.94;

# Shut up annoying XML::RSS warnings.
BEGIN { $SIG{'__WARN__'} = sub {warn $_[0] unless($_[0]=~/1432\.$/) } }
$0 = 'yarssr';

use constant TRUE => 1;
use constant FALSE => 0;
use constant NEW => 2;

my $name = 'yarssr';
my $version = '0.1.5';
my $copyright = 'GNU General Public License (GPL)';
my $comments = 'http://yarssr.sf.net';
my $authors = 'Lee Aylward <lee@laylward.com>

Patches from:
	James Curbo,
	Dan Lenski
	
Debian Package by:
	Joachim Breitner <nomeata@debian.org>';

my $application = Gnome2::Program->init($0, $version);

my %feeds;
my $parser = new XML::RSS;
my $menu;

# Minutes between updates
my $interval = 900000;

# Max number of feeds per site
my $maxfeeds = 6;

# Config file
my $configdir = $ENV{HOME}.'/.yarssr/';
my $config = $ENV{HOME}.'/.yarssr/config';

# Default browser
my $browser = '/usr/bin/mozilla';
my $usegnome;

# Mark entries as new (false at first)
my $marknew = FALSE;

# Gtk 2 stuff
Gtk2->init;
Gnome2::VFS->init;

# Glade setup
my $xml;
{
	local $/ = undef;
	$xml = <DATA>;
}

my $gld = Gtk2::GladeXML->new_from_buffer($xml);
$gld->signal_autoconnect_from_package('main');

# Create windows
my $prefs_window = $gld->get_widget('window_prefs');
$prefs_window->signal_connect('delete-event'=>\&delete_event);
my $add_dialog = $gld->get_widget('add_dialog');
$add_dialog->set_transient_for($prefs_window);
$add_dialog->signal_connect('delete-event'=>\&delete_event);

# SimpleList for displaying feeds
my $feedlist = Gtk2::SimpleList->new (
	'Name'		=> 'text',
	'Enabled'	=> 'bool',
	'Address'	=> 'text',
);

#$feedlist->set_column_editable(0,TRUE);
#$feedlist->set_column_editable(2,TRUE);

$feedlist->set_reorderable(TRUE);
my @columns = $feedlist->get_columns;
$columns[$_]->set_sort_column_id($_) for (0..2);

# Add simplelist to scrolled window in prefs window
my $scrolledwindow = $gld->get_widget('scrolledwindow_feeds');
$scrolledwindow->add($feedlist);

# Create tray inon
my $tray = Gtk2::TrayIcon->new("rss");
my $eventbox = Gtk2::EventBox->new;

# Attach event to show menu
$eventbox->signal_connect("button-release-event", \&menu_show);

# Pixmaps
my @pixmap = ( 
'26 24 30 1',
' 	c None',
'.	c #808080',
'+	c #F4F4E9',
'@	c #000000',
'#	c #515151',
'$	c #555551',
'%	c #6F6F6A',
'&	c #A3A39F',
'*	c #939390',
'=	c #929390',
'-	c #848381',
';	c #848480',
'>	c #838381',
',	c #838480',
'\'	c #838380',
')	c #747471',
'!	c #737471',
'~	c #747371',
'{	c #747470',
']	c #F3F3E8',
'^	c #646461',
'/	c #646561',
'(	c #656561',
'_	c #656460',
':	c #646460',
'<	c #656461',
'[	c #6B6B66',
'}	c #E3E3D9',
'|	c #252525',
'1	c #C8C8BF',
'                          ',
'                          ',
' ........................ ',
' .++++++++++++++++++++++. ',
' .++@+@++@@@++@@@++@@@++. ',
' .++@+@++@+@++@+@++@+@++. ',
' .++@@@++@@@++@@+++@@+++. ',
' .+++@+++@+@++@+@++@+@++. ',
' .+++@+++@+@++@+@++@+@++. ',
' .+@@@@@@@@@@@@@@@@@@@@+. ',
' #++++++++++++++++++++++# ',
' #++++++++++++++++++++++# ',
' #+$$$$$$$$$$+%%%%%%%%%+# ',
' #++++++++++++%&&&&&&&%+# ',
' #+$$$$$$$$$$+%******=%+# ',
' #++++++++++++%-;>,\'>\'%+# ',
' #+$$$$$$$$$$+$)!~{~){%+# ',
' #]]]]]]]]]]]]$^/(_:<:[]# ',
' #}%%%%%%%%%%}$$$$$$$$%}# ',
' #|11111111111111111111|# ',
'  ||||||||||||||||||||||  ',
'                          ',
'                          ',
'                          ');

my @pixmap_new = (
'26 24 21 1',
' 	c None',
'.	c #984848',
'+	c #F1D6D6',
'@	c #000000',
'#	c #5C3434',
'$	c #360000',
'%	c #5D0000',
'&	c #A12A2A',
'*	c #911313',
'=	c #901212',
'-	c #820202',
';	c #650000',
'>	c #640000',
',	c #F0D3D3',
'\'	c #490000',
')	c #4B0000',
'!	c #4C0000',
'~	c #580000',
'{	c #E0A9A9',
']	c #1B0909',
'^	c #C56B6B',
'                          ',
'                          ',
' ........................ ',
' .++++++++++++++++++++++. ',
' .++@+@++@@@++@@@++@@@++. ',
' .++@+@++@+@++@+@++@+@++. ',
' #++@@@++@@@++@@+++@@+++. ',
' #+++@+++@+@++@+@++@+@++. ',
' #+++@+++@+@++@+@++@+@++# ',
' #+@@@@@@@@@@@@@@@@@@@@+# ',
' #++++++++++++++++++++++# ',
' #++++++++++++++++++++++# ',
' #+$$$$$$$$$$+%%%%%%%%%+# ',
' #++++++++++++%&&&&&&&%+# ',
' #+$$$$$$$$$$+%******=%+# ',
' #++++++++++++%-------%+# ',
' #+$$$$$$$$$$+$;;>;>;;%+# ',
' #,,,,,,,,,,,,$\')!)\')\'~,# ',
' #{%%%%%%%%%%{$$$$$$$$%{# ',
' #]^^^^^^^^^^^^^^^^^^^^]# ',
'  ]]]]]]]]]]]]]]]]]]]]]]  ',
'                          ',
'                          ',
'                          ');

my @dot = (
"16 16 28 1",
"       c None",
".      c #A70505",
"+      c #AA0606",
"@      c #AE0808",
"#      c #AF0808",
"\$      c #B50B0B",
"%      c #B60B0B",
"&      c #B90C0C",
"*      c #BB0E0E",
"=      c #BC0E0E",
"-      c #BE1010",
";      c #BF1010",
">      c #C01111",
",      c #C11212",
"'      c #C31414",
")      c #C41515",
"!      c #C51616",
"~      c #C61818",
"{      c #C91C1C",
"]      c #CA1D1D",
"^      c #CB1E1E",
"/      c #CF2626",
"(      c #D12828",
"_      c #D73535",
":      c #D83838",
"<      c #DC4040",
"[      c #DF4A4A",
"}      c #E86B6B",
"                ",
"                ",
"                ",
"                ",
"                ",
"      '!)>      ",
"     )(<:~=     ",
"     )_}[]*     ",
"     ,^/{,\$     ",
"     &;-*%+     ",
"      ##@.      ",
"                ",
"                ",
"                ",
"                ",
"                ");

my @blank = (
"16 16 1 1",
"       c None",
"                ",
"                ",
"                ",
"                ",
"                ",
"                ",
"                ",
"                ",
"                ",
"                ",
"                ",
"                ",
"                ",
"                ",
"                ",
"                ");

# Make pixbufs out of pixmaps
my $pixbuf = Gtk2::Gdk::Pixbuf->new_from_xpm_data(@pixmap);
my $pixbuf_new = Gtk2::Gdk::Pixbuf->new_from_xpm_data(@pixmap_new);
my $dot = Gtk2::Gdk::Pixbuf->new_from_xpm_data(@dot);
my $blank = Gtk2::Gdk::Pixbuf->new_from_xpm_data(@blank);

my $image = Gtk2::Image->new_from_pixbuf($pixbuf);
$eventbox->add($image);

# Add eventbox to tray
$tray->add($eventbox);
$tray->show_all;

read_config();
update_feed_all();

# Now mark them as new
$marknew = TRUE;

# Create timer with specified interval
my $timer = Glib::Timeout->add($interval,\&update_feed_all);

Gtk2->main;
write_config();

# Subroutines
#
#
sub delete_event
{
	$_[0]->hide;
	add_dialog_clear();
	return TRUE;
}

sub read_config
{
	if (! -e $configdir)
	{
		mkdir $configdir 
			or warn "Failed to make config directory: $!\n";
	}
	if (! -e $configdir.'/icons')
	{
		mkdir $configdir.'/icons'
			or warn "Failed to make icons directory: $!\n";
	}
	if (-e $config) {
		open (CONFIG,"<",$config)
			or warn "Failed to open config file for reading: $!\n";
		while(<CONFIG>)
		{	
			chomp;
			if (/^feed=(.*);(.*);(\d)/) 
			{
				push @{$feedlist->{data}}, [$2,$3,$1];
				$feeds{$1} = {
						title => $2,
						enable=> $3,
					};
			}
			elsif (/^interval=(\d+)/)
			{
				$interval = $1;
			}
			elsif (/^maxfeeds=(\d+)/)
			{
				$maxfeeds = $1;
			}
			elsif (/^browser=(.*)/)
			{
				$browser = $1;
			}		
			elsif (/^usegnome=(\d)/)
			{
				$usegnome = $1;
			}
		}
		close(CONFIG)
	}
}

sub write_config
{
	open (CONFIG,">",$config) 
		or warn "Failed to open config file for writing: $!\n";
	print CONFIG "interval=$interval\n";
	print CONFIG "maxfeeds=$maxfeeds\n";
	print CONFIG "browser=$browser\n";
	print CONFIG "usegnome=$usegnome\n";
	for my $url (keys %feeds)
	{
		print CONFIG "feed=".$url.";".$feeds{$url}->{'title'}.
		";".$feeds{$url}->{'enable'}."\n";
	}
	close(CONFIG);
}

sub get_feed_all
{
	for my $url (sort keys %feeds)
	{
		get_feed($url) if ($feeds{$url}->{'enable'} == TRUE);
	}
}

sub get_feed
{
	my ($url,undef) = @_;
	Gtk2->main_iteration while Gtk2->events_pending; 
	my ($content,undef) = get_file($url);

	# Check if we got content
	if ($content)
	{
		# Parse content
		# in eval() because XML::RSS can choke on certain feeds
		eval {parse_feed($content,$url);};
		return;
	}
	else
	{
		# Failed dialog
		warn "Encountered problems downloading $url\n";
		get_feed_failed($url,"An error occured while connecting to $url");
		return;
	}
}

sub get_file
{
	my $url = shift;
	my ($result, $handle, $info);

	($result, $handle) = Gnome2::VFS->open($url, 'read');
	return(FALSE,FALSE) unless ($result eq 'ok');
	
	my $content = '';
	my $bytes_per_iteration = 1024;

	do {
		Gtk2->main_iteration while Gtk2->events_pending; 	
 		my ($tmp_buffer, $tmp_bytes_read);
 		($result, $tmp_bytes_read, $tmp_buffer) =
			$handle->read($bytes_per_iteration);

		$content .= $tmp_buffer;
	} while ($result eq 'ok');
	
	# Get mime type
	($result,$info) = $handle->get_file_info('default');
	my $type = $info->get_mime_type;

	$result = $handle->close();
	return \$content,$type;
}

sub parse_feed
{
	my ($content,$url) = @_;
	
	# Clear old feedorder
	
	# Parse contents with XML::RSS
	$parser->parse($$content);

	# Load parsed data into hash
	for my $count (0 .. $#{$parser->{'items'}})
	{
		my $item = ${$parser->{'items'}}[$count];
		
		unless (exists $feeds{$url}->{'contents'}{$item->{'title'}}) {
			$feeds{$url}->{'contents'}{$item->{'title'}} =  {
				url	=> $item->{'link'},
				title	=> $item->{'title'},
			};
		}
		
		unless (exists $feeds{$url}->{'contents'}{$item->{'title'}}{'read'})
		{
			if ($marknew == TRUE) {
				$feeds{$url}->{'contents'}{$item->{'title'}}{'read'} = FALSE;
			} else {
				$feeds{$url}->{'contents'}{$item->{'title'}}{'read'} = TRUE;
			}
		}
		
		@{$feeds{$url}->{'order'}}[$count] = $feeds{$url}{'contents'}{$item->{'title'}};
	}
	splice @{$feeds{$url}->{'order'}},scalar @{$parser->{'items'}};
}

# Update all of the feeds
#
sub update_feed_all
{
	# Set to red pixmap
	$image->set_from_pixbuf($pixbuf_new);

	# Download all the feeds and recreate the menu
	get_feed_all();
	menu_create();

	# Set to black pixmap
	$image->set_from_pixbuf($pixbuf);
	
	return TRUE;
}

# Update a single feed
#
sub update_feed
{
	my ($widget, $feed) = @_;
	
	# Set image to red pixmap
	$image->set_from_pixbuf($pixbuf_new);
	
	get_feed($feed); 
	menu_create();	

	# Set image to black pixmap
	$image->set_from_pixbuf($pixbuf);
}

# Draw the menu
#
sub menu_show
{
		$menu->popup(undef, undef, undef, undef, 1, 0);
}

# Create the menu for the tray
#
sub menu_create
{
	# Overwrite any existing menu
	$menu = Gtk2::Menu->new;
	# Create a new menu for each feed
	for my $feed (sort 
		{ lc $feeds{$a}->{'title'} cmp lc $feeds{$b}->{'title'} }
		keys %feeds )
	{
		next if $feeds{$feed}->{'enable'} == FALSE;
		my $favicon = get_favicon($feed);
		my $submenu = Gtk2::Menu->new;
		$submenu->set_title($feed);
		# Create a new menu item for each article in feed
		for my $article (0 .. ($maxfeeds-1))
		{
			next if (not defined 
				$feeds{$feed}->{'order'}[$article]{'title'});
				
			my $submenuitem = Gtk2::ImageMenuItem->new(
				$feeds{$feed}->{'order'}[$article]{'title'});

			if ($feeds{$feed}->{'order'}[$article]{'read'} == FALSE)
			{
				my $article_image = Gtk2::Image->new_from_pixbuf($dot);
				$submenuitem->set_image($article_image);
			}
			else
			{
				my $article_image = Gtk2::Image->new_from_pixbuf($blank);
				$submenuitem->set_image($article_image);
			}

			$submenuitem->signal_connect('activate',\&url_load, 
				[$article,$feed]);
				
			# Attach new menu item to the sub menu
			$submenu->append($submenuitem);
		}
		my $subseparator = Gtk2::SeparatorMenuItem->new;
		$submenu->append($subseparator);
		
		# Update this feed button...
		my $subupdate = Gtk2::ImageMenuItem->new('Update this feed');
		my $refresh_image = Gtk2::Image->new_from_stock('gtk-refresh','menu');
		$subupdate->set_image($refresh_image);
		$subupdate->signal_connect('activate',\&update_feed,$feed);
		$submenu->append($subupdate);
		
		# Attach submenu to a new main menu item
		my $menuitem = Gtk2::ImageMenuItem->new($feeds{$feed}->{'title'});

		# Add an icon if the feed has one
		$menuitem->set_image($$favicon) unless ($$favicon eq 'none');
		$menuitem->set_submenu($submenu);
		$menu->append($menuitem);
	}
	# Quit button...
	my $menuquit = Gtk2::ImageMenuItem->new('Quit');
	$menuquit->signal_connect('activate', sub { write_config(); exit 1; });
	my $quit_image = Gtk2::Image->new_from_stock('gtk-quit','menu');
	$menuquit->set_image($quit_image);
	
	# Preferences button...
	my $menupref = Gtk2::ImageMenuItem->new('Preferences');
	$menupref->signal_connect('activate',\&prefs_show);
	my $prefs_image = Gtk2::Image->new_from_stock('gtk-preferences','menu');
	$menupref->set_image($prefs_image);
	
	# Update all feeds button...
	my $menuupdate = Gtk2::ImageMenuItem->new('Update');
	my $refresh_image = Gtk2::Image->new_from_stock('gtk-refresh','menu');
	$menuupdate->signal_connect('activate',\&update_feed_all);
	$menuupdate->set_image($refresh_image);
	
	# Horz. Separator
	my $separator = Gtk2::SeparatorMenuItem->new;
	
	# Attach buttons to menu
	$menu->append($separator);
	$menu->append($menuupdate);
	$menu->append($menupref);
	$menu->append($menuquit);

	# Show menu
	$menu->show_all;
}

# Load a URL in a browser
# 
sub url_load
{
	my ($widget, $feed_info) = @_;
	my ($article, $feed) = @$feed_info;

	$feeds{$feed}->{'order'}[$article]{'read'} = TRUE;

	my $url = $feeds{$feed}->{'order'}[$article]{'url'};

	if ($usegnome == TRUE)
	{
		Gnome2::URL->show($url);
	}
	else
	{
		if (fork == 0)
		{
			my $b = $browser;
			$b .= ' %s' unless $b =~ /\%s/;
			exec(sprintf($b,$url)) or 
				warn "Unable to launch browser!\n";
		}
	}
	Gtk2->main_iteration while Gtk2->events_pending; 
	menu_create();
}

# Preference window
# 
sub prefs_show
{
	my $interval_display = $gld->get_widget('interval_entry');
	my $headings_display = $gld->get_widget('headings_entry');
	my $browser_display = $gld->get_widget('browser_entry');
	my $checkbutton = $gld->get_widget('use_default_browser_checkbox');

	# Convert milliseconds to minutes
	my $display_interval = ($interval / 1000) / 60;

	# Fill in current settings
	$interval_display->set_text($display_interval);
	$headings_display->set_text($maxfeeds);
	$browser_display->set_text($browser);

	$checkbutton->set_active($usegnome);
	$browser_display->set_sensitive(!$usegnome);

	$prefs_window->show_all;
}

sub on_pref_ok_button_clicked
{
	my $widget = shift;
	
	$prefs_window->hide;

	my $interval_temp = $gld->get_widget('interval_entry');
	my $headings_temp = $gld->get_widget('headings_entry');
	my $browser_temp = $gld->get_widget('browser_entry');
	my $usegnome_temp = $gld->get_widget('use_default_browser_checkbox');
	
	$browser = $browser_temp->get_text;

	# Get text from entry boxes
	my $new_interval = $interval_temp->get_text;
	my $new_maxfeeds = $headings_temp->get_text;
	
	# Get gnome default check button
	if ($usegnome_temp->get_active)
	{
		$usegnome = TRUE;
	}
	else
	{
		$usegnome = FALSE;
	}

	# Convert minutes to milliseconds
	$new_interval = ($new_interval * 1000) * 60;
	
	# Update settings and write to config
	update_interval($new_interval);
	update_maxfeeds($new_maxfeeds);
	update_feeds_enabled();
	write_config();
}

sub on_pref_cancel_button_clicked
{
	my $widget = shift;

	# Reset the use gnome checkbutton to old setting
	my $usegnome_temp = $gld->get_widget('use_default_browser_checkbox');
	$usegnome_temp->set_active($usegnome);

	# Hide windows
	$add_dialog->hide;
	$prefs_window->hide;
}

# Prefernce changes
# 
sub update_maxfeeds
{
	# Check if new value is different from current,
	# if so change setting and update the menus
	my $new_maxfeeds = shift;
	if ($new_maxfeeds != $maxfeeds)
	{
		$maxfeeds = $new_maxfeeds;
		menu_create();
	}
}

sub update_interval
{
	# Check if new interval value is different from
	# the current, if so change settings and recreate
	# timer
	my $newinterval = shift;
	if ($newinterval != $interval)
	{
		$interval = $newinterval;
		Glib::Source->remove($timer);
		$timer = Glib::Timeout->add($interval,\&update_feed_all);
	}
}

sub update_feeds_enabled
{
	my $changed = FALSE;
	for my $row (0 .. (scalar(@{$feedlist->{data}})-1))
	{
		next if (not exists($feedlist->{data}[$row]));
		my $url = $feedlist->{data}[$row][2];
		my $enable = $feedlist->{data}[$row][1];

		# Check if this has has been enabled/disabled
		# or new.
		if ($feeds{$url}->{'enable'} != $enable)
		{
			$feeds{$url}->{'enable'} = $enable;
			$image->set_from_pixbuf($pixbuf_new);

			# Redownload feed if it has been turned on
			get_feed($url) if ($enable == TRUE);
			$changed = TRUE;
		}
	}
	$image->set_from_pixbuf($pixbuf);

	menu_create() if $changed;
}

# Add feed window
# 
sub on_add_button_clicked
{
	$add_dialog->show_all;
}

sub add_dialog_clear
{
	my $name = $gld->get_widget('add_name_entry');
	my $address = $gld->get_widget('add_address_entry');

	# Set the entries to blank
	$name->set_text('');
	$address->set_text('');
}

sub on_add_ok_button_clicked
{
	my $name_temp = $gld->get_widget('add_name_entry');
	my $address_temp = $gld->get_widget('add_address_entry');
	
	# Add entry to the info hash
	$feeds{$address_temp->get_text}->{'title'} = $name_temp->get_text;
	$feeds{$address_temp->get_text}->{'enable'} = NEW;
	push @{$feedlist->{data}}, [$name_temp->get_text,NEW,$address_temp->get_text];
	
	# Hide and clear dialog
	$add_dialog->hide;
	add_dialog_clear();
}

sub on_add_cancel_button_clicked
{
	$add_dialog->hide;
	add_dialog_clear();
}

# Get feed failed dialog
#
sub get_feed_failed
{
	my ($url,$error) = @_;

	# Create dialog
	my $dlg = Gtk2::MessageDialog->new (undef, [], 'error', 'none',
		$error);
	
	# Add buttons
	$dlg->add_buttons (
		'gtk-remove'	=> 3,
		'Disable'	=> 2,
		'Retry' 	=> 1
	);
	$dlg->set_default_response ('cancel');
	my $response = $dlg->run;

	if (1 == $response) 
	{
		# Retry
		$dlg->destroy;
		update_feed(undef,$url);
	}
	if (3 == $response)
	{
		# Remove
		remove_feed($url);
		update_feedlist();
	}
	if (2 == $response)
	{
		# Disable
		disable_feed($url);
	}
	$dlg->destroy;
}

sub disable_feed
{
	my $url = shift;
	$feeds{$url}->{'enable'} = FALSE;
	update_feedlist();
	write_config();
}

# Remove feed button
# 
sub on_remove_button_clicked
{
	# Get highlighted rows	
	my @selected = $feedlist->get_selected_indices;

	# Delete rows from feed hash and feed list
	for my $selection (@selected)
	{
		unless ($selection == -1) {
				remove_feed($feedlist->{data}[$selection][2]);
				splice(@{$feedlist->{data}},$selection,1);
		}
	}
}

sub remove_feed
{
	my $url = shift;

	# Delete feed from hash
	delete $feeds{$url};

	write_config();
}	

sub update_feedlist
{
        # Empty feedlist
        @{$feedlist->{data}} = ();
        
        # Fill feedlist with feed info from hash
        for my $feed (keys %feeds)                                                                       { 
                push @{$feedlist->{data}}, [$feeds{$feed}->{'title'},
                        $feeds{$feed}->{'enable'},$feed];
        }               
}    

sub get_favicon
{
	my $url = shift;
	my ($ico, $icofile);

	# Default to none, will get overwritten if there
	# is an icon
	my $image = 'none';

	my $uri = Gnome2::VFS::URI->new($url);
	$ico = 'http://'.$uri->get_host_name.'/favicon.ico';
	$icofile = $configdir.'/icons/'.$feeds{$url}->{'title'}.".ico";

	# Download the icon if we don't have one already
	unless (-e $icofile)
	{
		# Download the icon
		my ($content,$type) = get_file($ico);
		if ($type ne 'text/html' and $content)
		{
			# Write the icon to the config directory
			open(ICO,'>',$icofile) 
				or warn "Could not open icon file: $icofile\n";
			print ICO $$content;
			close(ICO);
		}
	} 
	
	eval
	{
		my $pixbuf = Gtk2::Gdk::Pixbuf->new_from_file($icofile);
	
		# Resize icon if it is too large
		$pixbuf = $pixbuf->scale_simple(16,16,'bilinear')
			if ($pixbuf->get_height != 16);
			
		$image = Gtk2::Image->new_from_pixbuf($pixbuf);
	};

	return \$image;	
}

sub on_use_default_browser_checkbox_toggled
{
	my ($widget, $window) = @_;
	
	my $browser_entry = $gld->get_widget('browser_entry');

	# Check if checkbutton is active
	if ($widget->get_active)
	{
		$browser_entry->set_sensitive(FALSE);
	}
	else
	{
		$browser_entry->set_sensitive(TRUE);
	}
}

sub on_about_button_clicked
{
	my $about = Gnome2::About->new(
		$name,$version,$copyright,$comments,$authors);
	$about->show;
}
__DATA__
<?xml version="1.0" standalone="no"?> <!--*- mode: xml -*-->
<!DOCTYPE glade-interface SYSTEM "http://glade.gnome.org/glade-2.0.dtd">

<glade-interface>

<widget class="GtkWindow" id="window_prefs">
  <property name="border_width">6</property>
  <property name="title" translatable="yes">Preferences - yarssr</property>
  <property name="type">GTK_WINDOW_TOPLEVEL</property>
  <property name="window_position">GTK_WIN_POS_CENTER</property>
  <property name="modal">False</property>
  <property name="default_width">600</property>
  <property name="default_height">550</property>
  <property name="resizable">True</property>
  <property name="destroy_with_parent">False</property>
  <property name="decorated">True</property>
  <property name="skip_taskbar_hint">False</property>
  <property name="skip_pager_hint">False</property>
  <property name="type_hint">GDK_WINDOW_TYPE_HINT_NORMAL</property>
  <property name="gravity">GDK_GRAVITY_NORTH_WEST</property>

  <child>
    <widget class="GtkVBox" id="vbox1">
      <property name="visible">True</property>
      <property name="homogeneous">False</property>
      <property name="spacing">6</property>

      <child>
	<widget class="GtkScrolledWindow" id="scrolledwindow_feeds">
	  <property name="visible">True</property>
	  <property name="can_focus">True</property>
	  <property name="hscrollbar_policy">GTK_POLICY_AUTOMATIC</property>
	  <property name="vscrollbar_policy">GTK_POLICY_AUTOMATIC</property>
	  <property name="shadow_type">GTK_SHADOW_IN</property>
	  <property name="window_placement">GTK_CORNER_TOP_LEFT</property>

	  <child>
	    <placeholder/>
	  </child>
	</widget>
	<packing>
	  <property name="padding">0</property>
	  <property name="expand">True</property>
	  <property name="fill">True</property>
	</packing>
      </child>

      <child>
	<widget class="GtkHButtonBox" id="hbuttonbox2">
	  <property name="visible">True</property>
	  <property name="layout_style">GTK_BUTTONBOX_START</property>
	  <property name="spacing">6</property>

	  <child>
	    <widget class="GtkButton" id="remove_button">
	      <property name="width_request">30</property>
	      <property name="height_request">30</property>
	      <property name="visible">True</property>
	      <property name="can_default">True</property>
	      <property name="can_focus">True</property>
	      <property name="label">gtk-remove</property>
	      <property name="use_stock">True</property>
	      <property name="relief">GTK_RELIEF_NORMAL</property>
	      <property name="focus_on_click">True</property>
	      <signal name="clicked" handler="on_remove_button_clicked" last_modification_time="Wed, 03 Mar 2004 02:04:43 GMT"/>
	    </widget>
	  </child>

	  <child>
	    <widget class="GtkButton" id="add_button">
	      <property name="visible">True</property>
	      <property name="can_default">True</property>
	      <property name="can_focus">True</property>
	      <property name="label">gtk-add</property>
	      <property name="use_stock">True</property>
	      <property name="relief">GTK_RELIEF_NORMAL</property>
	      <property name="focus_on_click">True</property>
	      <signal name="clicked" handler="on_add_button_clicked" last_modification_time="Wed, 03 Mar 2004 02:04:47 GMT"/>
	    </widget>
	  </child>
	</widget>
	<packing>
	  <property name="padding">0</property>
	  <property name="expand">False</property>
	  <property name="fill">True</property>
	</packing>
      </child>

      <child>
	<widget class="GtkHSeparator" id="hseparator2">
	  <property name="visible">True</property>
	</widget>
	<packing>
	  <property name="padding">6</property>
	  <property name="expand">False</property>
	  <property name="fill">True</property>
	</packing>
      </child>

      <child>
	<widget class="GtkTable" id="table2">
	  <property name="visible">True</property>
	  <property name="n_rows">3</property>
	  <property name="n_columns">3</property>
	  <property name="homogeneous">False</property>
	  <property name="row_spacing">6</property>
	  <property name="column_spacing">6</property>

	  <child>
	    <widget class="GtkHBox" id="hbox13">
	      <property name="visible">True</property>
	      <property name="homogeneous">False</property>
	      <property name="spacing">0</property>

	      <child>
		<widget class="GtkLabel" id="label1">
		  <property name="visible">True</property>
		  <property name="label" translatable="yes">Update Interval (min) :</property>
		  <property name="use_underline">False</property>
		  <property name="use_markup">False</property>
		  <property name="justify">GTK_JUSTIFY_LEFT</property>
		  <property name="wrap">False</property>
		  <property name="selectable">False</property>
		  <property name="xalign">0.5</property>
		  <property name="yalign">0.5</property>
		  <property name="xpad">0</property>
		  <property name="ypad">0</property>
		</widget>
		<packing>
		  <property name="padding">0</property>
		  <property name="expand">False</property>
		  <property name="fill">False</property>
		</packing>
	      </child>
	    </widget>
	    <packing>
	      <property name="left_attach">0</property>
	      <property name="right_attach">1</property>
	      <property name="top_attach">0</property>
	      <property name="bottom_attach">1</property>
	      <property name="x_options">fill</property>
	      <property name="y_options">fill</property>
	    </packing>
	  </child>

	  <child>
	    <widget class="GtkHBox" id="hbox14">
	      <property name="visible">True</property>
	      <property name="homogeneous">False</property>
	      <property name="spacing">0</property>

	      <child>
		<widget class="GtkLabel" id="label2">
		  <property name="visible">True</property>
		  <property name="label" translatable="yes">Headings Displayed :</property>
		  <property name="use_underline">False</property>
		  <property name="use_markup">False</property>
		  <property name="justify">GTK_JUSTIFY_LEFT</property>
		  <property name="wrap">False</property>
		  <property name="selectable">False</property>
		  <property name="xalign">0.5</property>
		  <property name="yalign">0.5</property>
		  <property name="xpad">0</property>
		  <property name="ypad">0</property>
		</widget>
		<packing>
		  <property name="padding">0</property>
		  <property name="expand">False</property>
		  <property name="fill">False</property>
		</packing>
	      </child>
	    </widget>
	    <packing>
	      <property name="left_attach">0</property>
	      <property name="right_attach">1</property>
	      <property name="top_attach">1</property>
	      <property name="bottom_attach">2</property>
	      <property name="x_options">fill</property>
	      <property name="y_options">fill</property>
	    </packing>
	  </child>

	  <child>
	    <widget class="GtkHBox" id="hbox15">
	      <property name="visible">True</property>
	      <property name="homogeneous">False</property>
	      <property name="spacing">0</property>

	      <child>
		<widget class="GtkLabel" id="label20">
		  <property name="visible">True</property>
		  <property name="label" translatable="yes">Browser Command :
(%s for URL)</property>
		  <property name="use_underline">False</property>
		  <property name="use_markup">False</property>
		  <property name="justify">GTK_JUSTIFY_LEFT</property>
		  <property name="wrap">False</property>
		  <property name="selectable">False</property>
		  <property name="xalign">0.5</property>
		  <property name="yalign">0.5</property>
		  <property name="xpad">0</property>
		  <property name="ypad">0</property>
		</widget>
		<packing>
		  <property name="padding">0</property>
		  <property name="expand">False</property>
		  <property name="fill">False</property>
		</packing>
	      </child>
	    </widget>
	    <packing>
	      <property name="left_attach">0</property>
	      <property name="right_attach">1</property>
	      <property name="top_attach">2</property>
	      <property name="bottom_attach">3</property>
	      <property name="x_options">fill</property>
	      <property name="y_options">fill</property>
	    </packing>
	  </child>

	  <child>
	    <widget class="GtkHBox" id="hbox16">
	      <property name="visible">True</property>
	      <property name="homogeneous">False</property>
	      <property name="spacing">0</property>

	      <child>
		<widget class="GtkEntry" id="interval_entry">
		  <property name="visible">True</property>
		  <property name="can_focus">True</property>
		  <property name="editable">True</property>
		  <property name="visibility">True</property>
		  <property name="max_length">0</property>
		  <property name="text" translatable="yes"></property>
		  <property name="has_frame">True</property>
		  <property name="invisible_char" translatable="yes">*</property>
		  <property name="activates_default">False</property>
		  <property name="width_chars">6</property>
		</widget>
		<packing>
		  <property name="padding">0</property>
		  <property name="expand">False</property>
		  <property name="fill">False</property>
		</packing>
	      </child>
	    </widget>
	    <packing>
	      <property name="left_attach">1</property>
	      <property name="right_attach">2</property>
	      <property name="top_attach">0</property>
	      <property name="bottom_attach">1</property>
	      <property name="x_options">fill</property>
	      <property name="y_options">fill</property>
	    </packing>
	  </child>

	  <child>
	    <widget class="GtkHBox" id="hbox17">
	      <property name="visible">True</property>
	      <property name="homogeneous">False</property>
	      <property name="spacing">0</property>

	      <child>
		<widget class="GtkEntry" id="headings_entry">
		  <property name="visible">True</property>
		  <property name="can_focus">True</property>
		  <property name="editable">True</property>
		  <property name="visibility">True</property>
		  <property name="max_length">0</property>
		  <property name="text" translatable="yes"></property>
		  <property name="has_frame">True</property>
		  <property name="invisible_char" translatable="yes">*</property>
		  <property name="activates_default">False</property>
		  <property name="width_chars">6</property>
		</widget>
		<packing>
		  <property name="padding">0</property>
		  <property name="expand">False</property>
		  <property name="fill">True</property>
		</packing>
	      </child>
	    </widget>
	    <packing>
	      <property name="left_attach">1</property>
	      <property name="right_attach">2</property>
	      <property name="top_attach">1</property>
	      <property name="bottom_attach">2</property>
	      <property name="x_options">fill</property>
	      <property name="y_options">fill</property>
	    </packing>
	  </child>

	  <child>
	    <widget class="GtkCheckButton" id="use_default_browser_checkbox">
	      <property name="visible">True</property>
	      <property name="can_focus">True</property>
	      <property name="label" translatable="yes">Gnome Default</property>
	      <property name="use_underline">True</property>
	      <property name="relief">GTK_RELIEF_NORMAL</property>
	      <property name="focus_on_click">True</property>
	      <property name="active">False</property>
	      <property name="inconsistent">False</property>
	      <property name="draw_indicator">True</property>
	      <signal name="toggled" handler="on_use_default_browser_checkbox_toggled" last_modification_time="Thu, 11 Mar 2004 00:31:35 GMT"/>
	    </widget>
	    <packing>
	      <property name="left_attach">2</property>
	      <property name="right_attach">3</property>
	      <property name="top_attach">2</property>
	      <property name="bottom_attach">3</property>
	      <property name="x_options"></property>
	      <property name="y_options"></property>
	    </packing>
	  </child>

	  <child>
	    <widget class="GtkEntry" id="browser_entry">
	      <property name="visible">True</property>
	      <property name="can_focus">True</property>
	      <property name="editable">True</property>
	      <property name="visibility">True</property>
	      <property name="max_length">0</property>
	      <property name="text" translatable="yes"></property>
	      <property name="has_frame">True</property>
	      <property name="invisible_char" translatable="yes">*</property>
	      <property name="activates_default">False</property>
	    </widget>
	    <packing>
	      <property name="left_attach">1</property>
	      <property name="right_attach">2</property>
	      <property name="top_attach">2</property>
	      <property name="bottom_attach">3</property>
	      <property name="y_options">fill</property>
	    </packing>
	  </child>
	</widget>
	<packing>
	  <property name="padding">0</property>
	  <property name="expand">False</property>
	  <property name="fill">True</property>
	</packing>
      </child>

      <child>
	<widget class="GtkHSeparator" id="hseparator3">
	  <property name="visible">True</property>
	</widget>
	<packing>
	  <property name="padding">6</property>
	  <property name="expand">False</property>
	  <property name="fill">True</property>
	</packing>
      </child>

      <child>
	<widget class="GtkHBox" id="hbox18">
	  <property name="visible">True</property>
	  <property name="homogeneous">False</property>
	  <property name="spacing">0</property>

	  <child>
	    <widget class="GtkButton" id="about_button">
	      <property name="visible">True</property>
	      <property name="can_focus">True</property>
	      <property name="relief">GTK_RELIEF_NORMAL</property>
	      <property name="focus_on_click">True</property>
	      <signal name="clicked" handler="on_about_button_clicked" last_modification_time="Sat, 19 Jun 2004 04:42:47 GMT"/>

	      <child>
		<widget class="GtkAlignment" id="alignment1">
		  <property name="visible">True</property>
		  <property name="xalign">0.5</property>
		  <property name="yalign">0.5</property>
		  <property name="xscale">0</property>
		  <property name="yscale">0</property>
		  <property name="top_padding">0</property>
		  <property name="bottom_padding">0</property>
		  <property name="left_padding">0</property>
		  <property name="right_padding">0</property>

		  <child>
		    <widget class="GtkHBox" id="hbox19">
		      <property name="visible">True</property>
		      <property name="homogeneous">False</property>
		      <property name="spacing">2</property>

		      <child>
			<widget class="GtkImage" id="image1">
			  <property name="visible">True</property>
			  <property name="stock">gtk-dialog-info</property>
			  <property name="icon_size">4</property>
			  <property name="xalign">0.5</property>
			  <property name="yalign">0.5</property>
			  <property name="xpad">3</property>
			  <property name="ypad">0</property>
			</widget>
			<packing>
			  <property name="padding">0</property>
			  <property name="expand">False</property>
			  <property name="fill">False</property>
			</packing>
		      </child>

		      <child>
			<widget class="GtkLabel" id="label21">
			  <property name="visible">True</property>
			  <property name="label" translatable="yes">_About</property>
			  <property name="use_underline">True</property>
			  <property name="use_markup">False</property>
			  <property name="justify">GTK_JUSTIFY_LEFT</property>
			  <property name="wrap">False</property>
			  <property name="selectable">False</property>
			  <property name="xalign">0.5</property>
			  <property name="yalign">0.5</property>
			  <property name="xpad">3</property>
			  <property name="ypad">0</property>
			</widget>
			<packing>
			  <property name="padding">0</property>
			  <property name="expand">False</property>
			  <property name="fill">False</property>
			</packing>
		      </child>
		    </widget>
		  </child>
		</widget>
	      </child>
	    </widget>
	    <packing>
	      <property name="padding">0</property>
	      <property name="expand">False</property>
	      <property name="fill">False</property>
	    </packing>
	  </child>

	  <child>
	    <widget class="GtkHButtonBox" id="hbuttonbox1">
	      <property name="visible">True</property>
	      <property name="layout_style">GTK_BUTTONBOX_END</property>
	      <property name="spacing">6</property>

	      <child>
		<widget class="GtkButton" id="pref_cancel_button">
		  <property name="visible">True</property>
		  <property name="can_default">True</property>
		  <property name="can_focus">True</property>
		  <property name="label">gtk-cancel</property>
		  <property name="use_stock">True</property>
		  <property name="relief">GTK_RELIEF_NORMAL</property>
		  <property name="focus_on_click">True</property>
		  <signal name="clicked" handler="on_pref_cancel_button_clicked" last_modification_time="Wed, 03 Mar 2004 06:06:03 GMT"/>
		</widget>
	      </child>

	      <child>
		<widget class="GtkButton" id="pref_ok_button">
		  <property name="visible">True</property>
		  <property name="can_default">True</property>
		  <property name="can_focus">True</property>
		  <property name="label">gtk-ok</property>
		  <property name="use_stock">True</property>
		  <property name="relief">GTK_RELIEF_NORMAL</property>
		  <property name="focus_on_click">True</property>
		  <signal name="clicked" handler="on_pref_ok_button_clicked" last_modification_time="Wed, 03 Mar 2004 06:06:27 GMT"/>
		</widget>
	      </child>
	    </widget>
	    <packing>
	      <property name="padding">0</property>
	      <property name="expand">True</property>
	      <property name="fill">True</property>
	    </packing>
	  </child>
	</widget>
	<packing>
	  <property name="padding">0</property>
	  <property name="expand">False</property>
	  <property name="fill">True</property>
	</packing>
      </child>
    </widget>
  </child>
</widget>

<widget class="GtkWindow" id="add_dialog">
  <property name="title" translatable="yes">Add Feed</property>
  <property name="type">GTK_WINDOW_TOPLEVEL</property>
  <property name="window_position">GTK_WIN_POS_NONE</property>
  <property name="modal">False</property>
  <property name="default_width">325</property>
  <property name="default_height">100</property>
  <property name="resizable">False</property>
  <property name="destroy_with_parent">False</property>
  <property name="decorated">True</property>
  <property name="skip_taskbar_hint">False</property>
  <property name="skip_pager_hint">False</property>
  <property name="type_hint">GDK_WINDOW_TYPE_HINT_NORMAL</property>
  <property name="gravity">GDK_GRAVITY_NORTH_WEST</property>

  <child>
    <widget class="GtkVBox" id="vbox2">
      <property name="visible">True</property>
      <property name="homogeneous">False</property>
      <property name="spacing">0</property>

      <child>
	<widget class="GtkTable" id="table1">
	  <property name="visible">True</property>
	  <property name="n_rows">2</property>
	  <property name="n_columns">2</property>
	  <property name="homogeneous">False</property>
	  <property name="row_spacing">0</property>
	  <property name="column_spacing">0</property>

	  <child>
	    <widget class="GtkEntry" id="add_name_entry">
	      <property name="visible">True</property>
	      <property name="can_focus">True</property>
	      <property name="editable">True</property>
	      <property name="visibility">True</property>
	      <property name="max_length">0</property>
	      <property name="text" translatable="yes"></property>
	      <property name="has_frame">True</property>
	      <property name="invisible_char" translatable="yes">*</property>
	      <property name="activates_default">True</property>
	    </widget>
	    <packing>
	      <property name="left_attach">1</property>
	      <property name="right_attach">2</property>
	      <property name="top_attach">0</property>
	      <property name="bottom_attach">1</property>
	      <property name="x_padding">6</property>
	      <property name="y_padding">6</property>
	      <property name="y_options"></property>
	    </packing>
	  </child>

	  <child>
	    <widget class="GtkEntry" id="add_address_entry">
	      <property name="visible">True</property>
	      <property name="can_focus">True</property>
	      <property name="editable">True</property>
	      <property name="visibility">True</property>
	      <property name="max_length">0</property>
	      <property name="text" translatable="yes"></property>
	      <property name="has_frame">True</property>
	      <property name="invisible_char" translatable="yes">*</property>
	      <property name="activates_default">False</property>
	    </widget>
	    <packing>
	      <property name="left_attach">1</property>
	      <property name="right_attach">2</property>
	      <property name="top_attach">1</property>
	      <property name="bottom_attach">2</property>
	      <property name="x_padding">6</property>
	      <property name="y_padding">6</property>
	      <property name="y_options"></property>
	    </packing>
	  </child>

	  <child>
	    <widget class="GtkLabel" id="label_name">
	      <property name="visible">True</property>
	      <property name="label" translatable="yes">Name:</property>
	      <property name="use_underline">False</property>
	      <property name="use_markup">False</property>
	      <property name="justify">GTK_JUSTIFY_LEFT</property>
	      <property name="wrap">False</property>
	      <property name="selectable">False</property>
	      <property name="xalign">0</property>
	      <property name="yalign">0.5</property>
	      <property name="xpad">0</property>
	      <property name="ypad">0</property>
	    </widget>
	    <packing>
	      <property name="left_attach">0</property>
	      <property name="right_attach">1</property>
	      <property name="top_attach">0</property>
	      <property name="bottom_attach">1</property>
	      <property name="x_padding">6</property>
	      <property name="x_options">fill</property>
	      <property name="y_options"></property>
	    </packing>
	  </child>

	  <child>
	    <widget class="GtkLabel" id="label7">
	      <property name="visible">True</property>
	      <property name="label" translatable="yes">Address:</property>
	      <property name="use_underline">False</property>
	      <property name="use_markup">False</property>
	      <property name="justify">GTK_JUSTIFY_LEFT</property>
	      <property name="wrap">False</property>
	      <property name="selectable">False</property>
	      <property name="xalign">0</property>
	      <property name="yalign">0.5</property>
	      <property name="xpad">0</property>
	      <property name="ypad">0</property>
	    </widget>
	    <packing>
	      <property name="left_attach">0</property>
	      <property name="right_attach">1</property>
	      <property name="top_attach">1</property>
	      <property name="bottom_attach">2</property>
	      <property name="x_padding">6</property>
	      <property name="x_options">fill</property>
	      <property name="y_options"></property>
	    </packing>
	  </child>
	</widget>
	<packing>
	  <property name="padding">0</property>
	  <property name="expand">True</property>
	  <property name="fill">True</property>
	</packing>
      </child>

      <child>
	<widget class="GtkHSeparator" id="hseparator1">
	  <property name="visible">True</property>
	</widget>
	<packing>
	  <property name="padding">0</property>
	  <property name="expand">True</property>
	  <property name="fill">True</property>
	</packing>
      </child>

      <child>
	<widget class="GtkHButtonBox" id="hbuttonbox3">
	  <property name="visible">True</property>
	  <property name="layout_style">GTK_BUTTONBOX_END</property>
	  <property name="spacing">0</property>

	  <child>
	    <widget class="GtkButton" id="add_cancel_button">
	      <property name="border_width">6</property>
	      <property name="visible">True</property>
	      <property name="can_default">True</property>
	      <property name="can_focus">True</property>
	      <property name="label">gtk-cancel</property>
	      <property name="use_stock">True</property>
	      <property name="relief">GTK_RELIEF_NORMAL</property>
	      <property name="focus_on_click">True</property>
	      <signal name="clicked" handler="on_add_cancel_button_clicked" last_modification_time="Wed, 03 Mar 2004 03:55:02 GMT"/>
	    </widget>
	  </child>

	  <child>
	    <widget class="GtkButton" id="add_ok_button">
	      <property name="border_width">6</property>
	      <property name="visible">True</property>
	      <property name="can_default">True</property>
	      <property name="has_default">True</property>
	      <property name="can_focus">True</property>
	      <property name="label">gtk-ok</property>
	      <property name="use_stock">True</property>
	      <property name="relief">GTK_RELIEF_NORMAL</property>
	      <property name="focus_on_click">True</property>
	      <signal name="clicked" handler="on_add_ok_button_clicked" last_modification_time="Wed, 03 Mar 2004 03:54:37 GMT"/>
	    </widget>
	  </child>
	</widget>
	<packing>
	  <property name="padding">0</property>
	  <property name="expand">False</property>
	  <property name="fill">True</property>
	</packing>
      </child>
    </widget>
  </child>
</widget>

</glade-interface>
