#!/usr/bin/perl

################# LINUX UPDATE #################
# Package up-to-date monitor for linux.
#
# Copyright (c) 2004 Patryk Zawadzki
# patrys@pld-linux.org
#
################################################

############### CONFIGURE THESE ################

my $refreshDelay = 100;
my $listCommand = 'poldek -q --noask --shcmd="ls -n -u"';
my $listDelay = 300;
my $listFile = "$ENV{'TMPDIR'}/LinuxUpdate.lst";
my $updateCommand = 'poldek --up && poldek --upa';
my $updateEveryNth = 3;
my $updateFile = "$ENV{'TMPDIR'}/LinuxUpdate.upd";
my $upgradeCommand = 'xterm -e poldek -U -G -v';
my $pixmapDir = '/usr/share/pixmaps/LinuxUpdate';

################################################

my $pid = fork();
if ($pid eq 0)
{
	my $count = 0;

	while (1)
	{
		$count++;

		if (open(fileIN,"$updateFile"))
		{
			my @updateList = <fileIN>;
			chop(@updateList);
			if (@updateList eq 0)
			{
				unlink("$updateFile");
			}
			else
			{
				close(fileIN);
				print "Upgrading...\n";
				print "Calling $upgradeCommand @updateList...\n";
				system "$upgradeCommand @updateList";
				if ($? eq 0)
				{
					unlink("$updateFile");
				}
			}
		}
		if ($count eq $updateEveryNth)
		{
			$count = 0;
			print "Updating package list...\n";
			system $updateCommand;
		}

		print "Requesting fresh list...\n";
		$list = `$listCommand`;
		if ($? eq 0)
		{
			open(fileOUT, ">$listFile");
			flock(fileOUT, 2);
			print fileOUT $list;
			close(fileOUT);
		}
		print "List refreshed.\n";
		sleep($listDelay);

	}
	exit;
}

use Gtk2::TrayIcon;
use Gtk2::SimpleList;

Gtk2->init;

my @list = ();

my @updateList = ();

my $quitting = 0;

my $trayIcon = Gtk2::TrayIcon->new("pld-update");

my $toolTip = Gtk2::Tooltips->new;

my $eventBox = Gtk2::EventBox->new;

my $trayImage;

my $iconImage;

my $window = Gtk2::Window->new('toplevel');

my $widgetBox = Gtk2::VBox->new(0, 5);

my $packageList = Gtk2::SimpleList->new('Update' => 'bool', 'Package name' => 'text');

sub in_array
{
	my $needle = shift;
	foreach (@_)
	{
		return 1 if $_ eq $needle;
	}
	return 0;
}

sub updateList
{
	@{$packageList->{data}} = ();
	foreach (@list)
	{
		push @{$packageList->{data}}, [in_array($_, @updateList), $_ ];
	}
}

sub setIcon
{
	my $num = @list;
	my $tooltip = "$num updates available.";

	if (!$window->visible)
	{
		updateList();
	}

	$toolTip->set_tip($eventBox, $tooltip);

	if ($num > 0)
	{
		$trayImage->set_from_pixbuf($iconImage[2]);
	}
	else
	{
		$trayImage->set_from_pixbuf($iconImage[1]);
	}
}

sub iconClick
{
	my ($widget, $event, $data) = @_;

	setIcon();
	if ($window->visible)
	{
		$window->hide;
	}
	else
	{
		$window->set_position('center');
		$window->show;
	}
}

sub exitClick
{
	print "Quitting...\n";
	$quitting = 1;
	Gtk2->main_quit;
	kill 1, $pid;
}

sub refreshClick
{
	get();
	updateList();
}

sub upgradeClick
{
	open(fileOUT, ">$updateFile");
	flock(fileOUT, 2);
	@updateList = ();
	for($i = 0; $i < @{$packageList->{data}}; $i++)
	{
		if ($packageList->{data}[$i][0] eq 1)
		{
			push @updateList, $packageList->{data}[$i][1];
		}
	}
	if (@updateList > 0)
	{
		print "Writing package list...\n";
		foreach(@updateList)
		{
			print fileOUT $_,"\n";
		}
	}
	$window->hide;
	close(fileOUT);
}

sub windowClose
{
	$window->hide;
	return 1-$quitting;
}

sub get
{
	print "Refreshing...\n";
	if (open(fileIN,"$listFile"))
	{
		@list = <fileIN>;
		chop(@list);
		close(fileIN);
	}
	if (open(fileIN,"$updateFile"))
	{
		@updateList = <fileIN>;
		chop(@updateList);
		close(fileIN);
	}
	setIcon();
	print "Refreshing done.\n";
}

# Load necessary resources

$iconImage[1] = Gtk2::Gdk::Pixbuf->new_from_file("$pixmapDir/none.xpm");
$iconImage[2] = Gtk2::Gdk::Pixbuf->new_from_file("$pixmapDir/avail.xpm");

# Setup the tray icon

$trayImage = Gtk2::Image->new_from_pixbuf($iconImage[1]);

$eventBox->add($trayImage);

$trayIcon->add($eventBox);
$trayIcon->show_all;

$toolTip->set_tip($eventBox, "Wait for updates...");

$eventBox->signal_connect(button_press_event => \&iconClick);

# Setup the window

$window->set_default_icon($iconImage[2]);
$window->set_position('center');
$window->set_default_size(600, 400);
$window->set_border_width(5);
$packageList->set_rules_hint(TRUE);
$packageList->show;
my $label = Gtk2::Label->new("Select packages to update:");
$label->show;
my $scrollBox = Gtk2::ScrolledWindow->new;
$scrollBox->add_with_viewport($packageList);
$scrollBox->show;
$widgetBox->pack_start($label, 0, 0, 0);
$widgetBox->pack_start($scrollBox, 1, 1, 0);
$widgetBox->show;
my $updateButton = Gtk2::Button->new("Upgrade");
$updateButton->show;
$updateButton->signal_connect(button_press_event => \&upgradeClick);
my $refreshButton = Gtk2::Button->new("Refresh");
$refreshButton->show;
$refreshButton->signal_connect(button_press_event => \&refreshClick);
my $exitButton = Gtk2::Button->new("Quit");
$exitButton->show;
$exitButton->signal_connect(button_press_event => \&exitClick);
my $buttonBox = Gtk2::HBox->new(0, 5);
$buttonBox->pack_start($refreshButton, 1, 1, 0);
$buttonBox->pack_start($updateButton, 1, 1, 0);
$buttonBox->pack_end($exitButton, 1, 1, 0);
$buttonBox->show;
$widgetBox->pack_end($buttonBox, 0, 1, 0);
$window->add($widgetBox);
$window->signal_connect(delete_event => \&windowClose);

# Start doing your job

Glib::Timeout->add((1000 * $refreshDelay) => \&get);

get;

Gtk2->main;

0;
