#!/usr/bin/perl -w

# Tabatha: A GUI for tablet PC settings
# (c) 2004 Austin Acton
# Licensed under the GPL

# Must run as root.
# Generates a list of commands from an xml file formatted as follows:
# <tabatha title="">
# <section title="">
# <button title="">
# <command>command 1</command>
# <command>command 2</command>
# </button>
# </section>
# </tabatha>

# Make a symbolic link to your xml config file, and call it /etc/tabatha.
# Otherwise, /usr/share/tabatha/default.xml will be used.

use XML::Parser;
use Gtk2 '-init';

# die if not running as root
#if ($ENV{USER} ne 'root') {
#	die ("Tabatha must run as root.\n");
#}

# Main exec
if (-e '/etc/tabatha') {
	$config = "/etc/tabatha";
}
elsif (-e '/usr/share/local/tabatha/default.xml') {
	$config = "/usr/share/local/tabatha/default.xml";
}
elsif (-e '/usr/share/tabatha/defualt.xml') {
	$config = "/usr/share/tabatha/default.xml";
}
else {
	die ("No configuration file found.  See README.\n");
}

# parse the config file, creating menu simultaneously
$parser = new XML::Parser (Style => 'Stream');
$parser -> parsefile ("$config");

# XML subroutines
sub StartTag {
	my $handler = shift (@_);
	my $name = shift (@_);
	my %attr = %_;
	if ($name eq 'tabatha') {
		# initialize counters
		$SectionNumber = 0;
		$ButtonNumber = 0;
		# initialize commmand list
		@command = ();
		# initialize window
		$window = Gtk2::Window->new;
		$window->set_title ("Tabatha");
		$window->set_border_width(2);
		$window->signal_connect (destroy => sub {
			Gtk2->main_quit;
		});
		# initialize main widget
		$main = Gtk2::VBox->new(0,0);
		$window->add($main);
		# name config file in main window
		$ConfigTitle = Gtk2::Label->new($attr{'title'});
		$main->pack_start($ConfigTitle, 0, 0, 0);
	}
	elsif ($name eq 'section') {
		# start a new section; frame it
		$section[$SectionNumber] = Gtk2::VBox->new(0,0);
		$frame[$SectionNumber] = Gtk2::Frame->new($attr{'title'});
		$frame[$SectionNumber]->set_border_width(0);
		$frame[$SectionNumber]->add($section[$SectionNumber]);
	}
	elsif ($name eq 'button') {
		# start a new button; wait for commands to assign to it
		$button[$ButtonNumber] = Gtk2::Button->new($attr{'title'});
		$button[$ButtonNumber]->set_border_width(0);
	}
	elsif ($name eq 'command') {
		$CommandOpen = 1;
	}
	else {
		die ("Unknown open tag in config file.\n")
	}
}		

sub EndTag {
	my $handler = shift (@_);
	my $name = shift (@_);
	if ($name eq 'tabatha') {
		# starts the GUI
		$window->show_all;
		Gtk2->main;
	}
	elsif ($name eq 'section') {
		# add section to main widget
		$main->pack_start($frame[$SectionNumber], 0, 0, 0);
		$SectionNumber++;
	}
	elsif ($name eq 'button') {
		# required to isolate button number from button counter
		&AddButton ($ButtonNumber);
		$ButtonNumber++;
	}
	elsif ($name eq 'command') {
		$CommandOpen = 0;
	}
	else {
		die ("Unknown close tag in config file.\n")
	}
}

sub Text {
	$NewCommand = $_;
	if ($CommandOpen) {
			# add command to current list
			push (@{$command[$ButtonNumber]}, $NewCommand);
	}
	else {
		print ("Ignored whitespace.\n");
	}
}

sub AddButton {
	my $number = pop (@_);
	# assign command to button
	$button[$number]->signal_connect (clicked=>sub {
		# convert array into command list; send it to system
		$ToBash = join ("; ", @{$command[$number]});
		system ($ToBash);
		# quit when a button is pushed
		Gtk2->main_quit;
	});
	# add button to current section
	$section[$SectionNumber]->pack_start($button[$number], 0, 0, 0);
}
