#!/usr/bin/perl -w

############################################################################
#    Copyright (C) 2005 by Fabio Marzocca                             #
#    thesaltydog@gmail.com                                                 #
#                                                                          #
#    This program is free software; you can redistribute it and or modify  #
#    it under the terms of the GNU General Public License as published by  #
#    the Free Software Foundation; either version 2 of the License, or     #
#    (at your option) any later version.                                   #
#                                                                          #
#    This program is distributed in the hope that it will be useful,       #
#    but WITHOUT ANY WARRANTY; without even the implied warranty of        #
#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         #
#    GNU General Public License for more details.                          #
#                                                                          #
#    You should have received a copy of the GNU General Public License     #
#    along with this program; if not, write to the                         #
#    Free Software Foundation, Inc.,                                       #
#    59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             #
############################################################################

# v. 1.0.0 - April 17th 2005
# v. 1.0.1 - April 18th 2005
# v. 1.2.0 - April 26th 2005
# v. 1.2.5 - May 1st 2005
# v. 1.2.6 - May 26th  2005
# v. 1.2.7 - May 27th 2005
# v. 1.3.0 - 15 June 2005
# v. 1.3.1  - 13 July 2005
#v.  1.3.2  - 18 July 2005
# -----------------------------------------------------------------



use Gtk2 '-init';
use Gtk2::SimpleMenu;
use Gtk2::SimpleList;
use Gnome2;
use Locale::gettext;
use POSIX qw(setlocale);
use Encode qw(decode);
use lib "/usr/share/bum/";
use bumlib;
use bum_init;

use constant TRUE  => 1;
use constant FALSE => 0;
use constant PACKAGE => 'bum';
use constant ICONPATH =>"/usr/share/pixmaps/bum/";
use constant ICONFILE =>ICONPATH."bum.png";
my $VERSION = "1.3.2";

my $scripts="";
my $rcS="";
my $summary="";
my $md5rcS="";


# gui
my $window;   		#main window
my $wNB;			#the notebook window
my $menu;			#main menu
my $info_buffer;		#text buffer for descriptions
my $info_buffer_rcS;		#text buffer for descriptions
my $page=0;			#current active page in notebook
my $p_Summary= 0;
my $p_DefaultRL = 1;
my $p_rcSd =2;
my $apply_button;
my $pxbf_boh = Gtk2::Gdk::Pixbuf->new_from_file(ICONPATH.'serv_boh.png');
my $pxbf_on=Gtk2::Gdk::Pixbuf->new_from_file(ICONPATH.'serv_on.png');
my $pxbf_off=Gtk2::Gdk::Pixbuf->new_from_file(ICONPATH.'serv_off.png');
my $pxbf_none=Gtk2::Gdk::Pixbuf->new_from_file(ICONPATH.'serv_none.png');
# /gui


	setlocale(LC_MESSAGES, "");
	textdomain(PACKAGE);    
	bind_textdomain_codeset(PACKAGE,"UTF-8");

#global variables to be translated
my $rcSwarning = _("You have asked to modify one or more services in the System Runlevel (rcSd). This operation could compromise the general stability of your system and, in some cases, cause possible damage to your hardware.\nAre you <b>100%</b> sure?");	

my @MENUIT =(
	_("Services"),
	_('Change start\/stop priority'),
	_('Activate service & apply now'),
	_('Deactivate service & apply now'),
	_('Start service now'),
	_('Stop service now')  
	);

#####################################################
sub _ {return decode("utf-8",dgettext( PACKAGE,$_[0]));}


##########################################################################################???
####################################################################
####################################################################

sub create_window
{
     
    my $win;
    
    $win = Gtk2::Window->new;
    $win->set_title ('Boot-Up Manager');
    $win->signal_connect (destroy => sub { bumlib::remove_lock();Gtk2->main_quit; });
    $win->set_border_width(4);
    $win->set_default_icon_from_file(ICONFILE);
    $win->set_position('center');
    return $win;
    
}


sub create_menu
{
   
    my $menu_tree = [
		     _File => {
			 item_type => '<Branch>',
			 children => [								
				      _('Apply changes')  => {
					  callback => sub {bum_save(yesnocancel(_("Start or stop services now? \n(If you answer No, changes will be applied at next boot.)"))); },
					  item_type => '<StockItem>',
					  extra_data => 'gtk-save',
					  callback_action => 2,
					  accelerator => '<ctrl>A',
				      },
					Separator => {
						item_type => '<Separator>',
						},
				     _('Exit') => {
					  callback => sub { bumlib::remove_lock();Gtk2->main_quit; },
					  callback_action => 3,
					  item_type => '<StockItem>',
					  extra_data => 'gtk-quit',
					  accelerator => '<ctrl>Q',
				      },
				  ],
		     },
		     
			 "_".$MENUIT[0] => {
			 item_type => '<Branch>',
			 children => [
					$MENUIT[1]  => {
					
					  callback => (\&change_priority),
					  callback_action => 6,
					  accelerator => '<ctrl>P',
				      },
					$MENUIT[2]  => {
					  callback => (\&act_now),
					  callback_action => 6,
					  accelerator => '<ctrl>2',
				      },
					$MENUIT[3] => {
					  callback => (\&deact_now),
					  callback_action => 7,
					  accelerator => '<ctrl>3',
				      },
				        $MENUIT[4] => {
					  callback => (\&start_now),
					  callback_action => 8,
					  accelerator => '<ctrl>S',
				      },
					$MENUIT[5] => {
					  callback => (\&stop_now),
					  callback_action => 9,
					  accelerator => '<ctrl>T',
				      },
					
				  ],
		     },
		     "_"._("Help") => {
			 item_type => '<Branch>',
			 children => [
				      '_'._('About') => {					
					item_type => '<StockItem>',
					callback => 
					      sub {bum_about();},
					  callback_action => 11,
					  accelerator => 'F1',
					extra_data => 'gtk-about',
				      },
					
				  ],
		     },
 
		     ];

    my $menu = Gtk2::SimpleMenu->new(
				     menu_tree        => $menu_tree,
				     default_callback => \&return,
				     );
  $menu->get_widget('/'.$MENUIT[0].'/'.$MENUIT[2])->set_sensitive(FALSE);
      
    return $menu;
}


sub bum_about {

my $translator = _("translator-credits");
my $special_credits=_("Special credits to:");
my $ack = _("Acknowledgments to:");
my $auth1= "Fabio Marzocca <thesaltydog\@gmail.com>\n\n";
my $auth2=("\nBeniamino Caputo, Thomas Hood\n\n");

my $pixbuf = Gtk2::Gdk::Pixbuf->new_from_file(ICONFILE);

if ($translator eq "translator-credits")  { $translator = "Fabio Marzocca <thesaltydog\@gmail.com>"};

	my $ga=Gnome2::About -> new ('Boot-Up Manager', $VERSION, _('Released under GNU General Public License (GPL)'), _('A graphical tool to handle runlevels configuration.')."\nhttp://www.marzocca.net/linux/bum.html", $auth1.$special_credits.$auth2.$ack."\nAndrea Abelli, Mattew East", undef, $translator,$pixbuf );
	
	$ga->set_transient_for($window);
	$ga->show;
}

sub create_V_container
{

    my $win = shift;
    my $vbox;

    $vbox = Gtk2::VBox->new(FALSE, 6);
    $win->add($vbox);

    return $vbox;

}

sub create_frame
{

    my ($parent, $title) = @_;
    my $frame;

    $frame = Gtk2::Frame->new($title);
    $parent->pack_start($frame, TRUE, TRUE, 0);
    $frame->set_border_width(3);

    return $frame;

}

sub create_info_box
{
	my $parent = shift;
	
	my ($entry,$hbox, $buffer);
        
 	$hbox = Gtk2::HBox->new(FALSE, 6);
    	$parent->add($hbox);
	$hbox->set_border_width(3);

	$info = Gtk2::TextView->new();
	$info->set_editable(FALSE);
	$info->set_left_margin(10);
    	
        $buffer = $info->get_buffer();
      
	my $scrolled = Gtk2::ScrolledWindow->new;
	$scrolled->set_policy ('automatic', 'automatic');
	$scrolled->add ($info);
	$hbox->pack_start ($scrolled, TRUE, TRUE, 0);

	return $buffer;
}


sub create_listbox
{
	my $parent = shift;
	
	my $hbox = Gtk2::HBox->new(FALSE,2);	
 	$parent->add($hbox);
	

$scripts = Gtk2::SimpleList->new (
                _('Activate')    => 'bool',
                _('Service name')  => 'text',
		'Halt'	=>	'text',
		_('Single user')	=>	'text',
		'Run level 2'	=>	'text',
		'Run level 3'	=>	'markup',
		'Run level 4'	=>	'text',
		'Run level 5'	=>	'text',
		'Reboot'	=>	'text'
           
            );
 
       	my $rl = bumlib::get_current_runlevel();
	my $rl_column =$scripts->get_column($rl+2);
	$rl_column->set_title($rl_column->get_title()."*");
	
	#set rules hint
	$scripts->set_rules_hint(TRUE);

	#center the columns
	for (my $column_index=2; $column_index<=7; $column_index++) {
	        my $cell = ($scripts->get_column($column_index)->get_cell_renderers)[0];
		$cell->set(xalign=>0.5);
		}

	$scripts->signal_connect(button_press_event => sub {
					my ($widget, $event) = @_;					
					my ($path, $column) = $widget->get_path_at_pos ($event->coords);	
					$widget->get_selection->select_path ($path);				
					if ($event->button==1) { #tasto sinistro
						if ($column == $scripts->get_column(0)) { #allinea la variazione su $summary 
							my $ind = ($scripts->get_selected_indices)[0];
							$summary->{data}[$ind][0] = !(get_current_item()->[0]);
							}
						}
					if ($event->button==3) { #tasto destro
						popupmenu_list($event);
						}
					return FALSE;});

       $scripts->signal_connect(cursor_changed=> sub {check_menu_sens(); });

# packed into a scrolled window...
$scrolled = Gtk2::ScrolledWindow->new;
$scrolled->set_policy ('never', 'automatic');
#$scrolled->set_size_request(400,200);
$scrolled->add ($scripts);
$hbox->add ($scrolled);


}
###############################
sub create_rcS_listbox
{
	my $parent = shift;
	
	my $hbox = Gtk2::HBox->new(FALSE,2);	
 	$parent->add($hbox);
	

$rcS = Gtk2::SimpleList->new (
              _('Activate')    => 'bool',
              _('Script name')  => 'text',
		'Halt'	=>	'text',
		'Run level S'	=>	'text',
		'Reboot'	=>	'text'
           
            );

	#make inactive the checkboxes
	my $cellrend=($rcS->get_column(0)->get_cell_renderers)[0];
	$cellrend->set('activatable',FALSE);
	#set rules hint
	$rcS->set_rules_hint(TRUE);

	#center the columns
	for (my $column_index=2; $column_index<=3; $column_index++) {
	        my $cell = ($rcS->get_column($column_index)->get_cell_renderers)[0];
		$cell->set(xalign=>0.5);
		}

	$rcS->signal_connect(button_press_event => sub {
					my ($widget, $event) = @_;
					
					if ( $event->button == 1) {
						my ($path, $column) = $widget->get_path_at_pos ($event->coords);
						message (_("Editing in run level S is not allowed!  Playing with rcS.d symlinks is an administration activity requiring deep knowledge of the runlevel system.")) if ($column == $rcS->get_column(0));
					}	
						
					return FALSE;});

					

       $rcS->signal_connect(cursor_changed=> sub {check_menu_sens(); });

# packed into a scrolled window...
$scrolled = Gtk2::ScrolledWindow->new;
$scrolled->set_policy ('never', 'automatic');
$scrolled->add ($rcS);
$hbox->add ($scrolled);


}

################################
sub create_summary_listbox
{
	my $parent = shift;
	my $hbox = Gtk2::HBox->new(FALSE,2);	
 	$parent->add($hbox);
	
      #  my $tooltip = Gtk2::Tooltips->new();
	#$tooltip->set_tip($pxbf_on,_('Prova!'));		

	$summary = Gtk2::SimpleList->new (
              _('Activate')    => 'bool',
	      _('Service name') => 'text',
              _('Description     ')  => 'markup',
	      _('Running') =>'pixbuf'	      
            );

	$summary->set_rules_hint(TRUE);
	
		$summary->get_column(2)->set_resizable(TRUE);


	$summary->signal_connect(button_press_event => sub {
					my ($widget, $event) = @_;					
					my ($path, $column) = $widget->get_path_at_pos ($event->coords);	
					$widget->get_selection->select_path ($path);				
					if ($event->button==1) { #tasto sinistro
						if ($column == $summary->get_column(0)) { #allinea la variazione su $defaultRL 
							my $ind = ($summary->get_selected_indices)[0];
							$scripts->{data}[$ind][0] = !(get_current_item()->[0]);
							}
						}
					if ($event->button==3) { #tasto destro
						popupmenu_simple_list($event,$summary);
						}
					return FALSE;});
       $summary->signal_connect(cursor_changed=> sub {check_menu_sens(); });

# packed into a scrolled window...
	$scrolled = Gtk2::ScrolledWindow->new;
	$scrolled->set_policy ('never', 'automatic');
	$scrolled->add ($summary);
	$hbox->add ($scrolled);

}
####################################

sub act_now
{
my $item= get_current_item();

	if (!defined $item) {
		message(_("You must select a script before!"));
		return;
		}

	if ($page == $p_Summary)
		{
		#allineare a defaultRL
		my $ind = ($summary->get_selected_indices)[0];
		$scripts->{data}[$ind][0] = 1;
		}

	$item->[0]=1;
	bum_save('yes');
}


sub deact_now
{
	my $item= get_current_item();

	if (!defined $item) {
		message(_("You must select a script before!"));
		return;
		}

	if ($page == $p_Summary)
		{
		#allineare a defaultRL
		my $ind = ($summary->get_selected_indices)[0];
		$scripts->{data}[$ind][0] = 0;
		}

	$item->[0]=0;
	bum_save('yes');

}


sub popupmenu_list
{
	my $event=shift;
	my @ind= $scripts->get_selected_indices;
	my $pmenu = Gtk2::Menu->new;

       my $deact= Gtk2::MenuItem->new (_("Deactivate & apply now"));
       my $act= Gtk2::MenuItem->new (_("Activate & apply now"));
       my $priority= Gtk2::MenuItem->new (_("Change start/stop priority"));
	my $separator = Gtk2::MenuItem->new ();

	$deact->signal_connect(activate=>sub{deact_now();});
	$act->signal_connect(activate=>sub{act_now();});
	$priority->signal_connect(activate=>sub{change_priority();});

	
	if ($scripts->{data}[$ind[0]][0]) {
		$pmenu->add($priority);
		$priority->show;	
		$pmenu->append ($separator);
		$separator->show;
		$pmenu->add($deact);
		$deact->show;
		}
	else {
		$pmenu->add($act);
		$act->show;
		}

	my $stop = Gtk2::MenuItem->new (_("Stop now"));
	my $start = Gtk2::MenuItem->new (_("Start now"));	
 	$stop->signal_connect(activate=>sub{stop_now();	});
	$start->signal_connect(activate=>sub{start_now();});
	
	my $running= bumlib::check_if_running($scripts->{data}[$ind[0]][1]);
	if (!defined($running))  {
		$pmenu->add($stop);
		$stop->show;
		$pmenu->add($start);
		$start->show;
		}
	elsif ($running==TRUE) {
		$pmenu->add($stop);
		$stop->show;
		}
	elsif ($running==FALSE) {	
		$pmenu->add($start);
		$start->show;
		}
	
			
	$pmenu->popup (undef,undef,undef,undef, $event->button, $event->time);

return TRUE;
}

sub popupmenu_simple_list
{
	my ($event, $slist)= @_; 
	my @ind= $slist->get_selected_indices;
	my $pmenu = Gtk2::Menu->new;

       my $deact= Gtk2::MenuItem->new (_("Deactivate & apply now"));
       my $act= Gtk2::MenuItem->new (_("Activate & apply now"));

	$deact->signal_connect(activate=>sub{deact_now();});
	$act->signal_connect(activate=>sub{act_now();});

	
	if ($slist->{data}[$ind[0]][0]) {
		$pmenu->add($deact);
		$deact->show;
		}
	else {
		$pmenu->add($act);
		$act->show;
		}
		
	my $stop = Gtk2::MenuItem->new (_("Stop now"));
	my $start = Gtk2::MenuItem->new (_("Start now"));	
 	$stop->signal_connect(activate=>sub{stop_now();	});
	$start->signal_connect(activate=>sub{start_now();});
	
	my $running= bumlib::check_if_running($slist->{data}[$ind[0]][1]);
	if (!defined($running)) {
		$pmenu->add($stop);
		$stop->show;
		$pmenu->add($start);
		$start->show;
		}
	elsif ($running==TRUE) {
		$pmenu->add($stop);
		$stop->show;
		}
	elsif($running==FALSE) {	
		$pmenu->add($start);
		$start->show;
		}
$pmenu->popup (undef,undef,undef,undef, $event->button, $event->time);
	

return TRUE;
}


sub get_current_item
{
	my @list;
	if ($page==$p_DefaultRL) { 
		my @ind= $scripts->get_selected_indices;
		return undef unless defined $ind[0];
		return $scripts->{data}[$ind[0]];
		}
	elsif($page==$p_rcSd) {
		my @ind= $rcS->get_selected_indices;
		return undef unless defined $ind[0];
		return $rcS->{data}[$ind[0]];
		}
	elsif($page==$p_Summary) {
		my @ind= $summary->get_selected_indices;
		return undef unless defined $ind[0];
		return $summary->{data}[$ind[0]];
		}
	
	return undef;

}

sub check_menu_sens
{
my $item= get_current_item();


if ($item->[0]) {
		$menu->get_widget('/'.$MENUIT[0].'/'.$MENUIT[2])->set_sensitive(FALSE);  #activate service
		$menu->get_widget('/'.$MENUIT[0].'/'.$MENUIT[3])->set_sensitive(TRUE);   #deactivate service
		if ($page==$p_DefaultRL) {$menu->get_widget('/'.$MENUIT[0].'/'.$MENUIT[1])->set_sensitive(TRUE);}   #change priority
		}
		else {
		$menu->get_widget('/'.$MENUIT[0].'/'.$MENUIT[2])->set_sensitive(TRUE); #activate
		$menu->get_widget('/'.$MENUIT[0].'/'.$MENUIT[3])->set_sensitive(FALSE);  #deactivate	
		$menu->get_widget('/'.$MENUIT[0].'/'.$MENUIT[1])->set_sensitive(FALSE);
		}

my $running = bumlib::check_if_running($item->[1]);
if (!defined($running)) {
		$menu->get_widget('/'.$MENUIT[0].'/'.$MENUIT[4])->set_sensitive(TRUE);  #start service
		$menu->get_widget('/'.$MENUIT[0].'/'.$MENUIT[5])->set_sensitive(TRUE);  #stop service
	}
elsif ($running==TRUE) { 
		$menu->get_widget('/'.$MENUIT[0].'/'.$MENUIT[4])->set_sensitive(FALSE);  #start service
		$menu->get_widget('/'.$MENUIT[0].'/'.$MENUIT[5])->set_sensitive(TRUE);  #stop service
	}
elsif($running==FALSE){
		$menu->get_widget('/'.$MENUIT[0].'/'.$MENUIT[4])->set_sensitive(TRUE);  #start service
		$menu->get_widget('/'.$MENUIT[0].'/'.$MENUIT[5])->set_sensitive(FALSE);  #stop service
	}
elsif($running==-1){
		$menu->get_widget('/'.$MENUIT[0].'/'.$MENUIT[4])->set_sensitive(FALSE);  #start service
		$menu->get_widget('/'.$MENUIT[0].'/'.$MENUIT[5])->set_sensitive(FALSE);  #stop service
	}


set_info_text();
}

sub change_page
{

$page=$wNB->get_current_page();
if ($page != $p_Summary) {set_info_text();}

if  ($page==$p_Summary){		
	$menu->get_widget("/File/"._("Apply changes"))->set_sensitive(TRUE);
	$apply_button->set_sensitive(TRUE);
	$menu->get_widget('/'.$MENUIT[0])->set_sensitive(TRUE);
	$menu->get_widget('/'.$MENUIT[0].'/'.$MENUIT[1])->set_sensitive(FALSE);      #change priority
	}
elsif ($page ==$p_rcSd) {
	$menu->get_widget('/'.$MENUIT[0])->set_sensitive(FALSE);
	$menu->get_widget("/File/"._("Apply changes"))->set_sensitive(FALSE);
	$apply_button->set_sensitive(FALSE);
	}
 else {
	$menu->get_widget("/File/"._("Apply changes"))->set_sensitive(TRUE);
	$apply_button->set_sensitive(TRUE);
	$menu->get_widget('/'.$MENUIT[0])->set_sensitive(TRUE);
	check_menu_sens();
	}


}


sub set_info_text
{
	#set info text
	my $buffer="";
	my $item= get_current_item();
	my $key = $item->[1];

	my ($pkg,$info) = bumlib::new_get_script_info($key);
	if ($page==$p_DefaultRL) {	$buffer = $info_buffer;}
	else {$buffer = $info_buffer_rcS; }

	$buffer->delete($buffer->get_start_iter,$buffer->get_end_iter);
  	$buffer->insert($buffer->get_start_iter,$pkg);
	$buffer->apply_tag_by_name ('title', $buffer->get_start_iter, $buffer->get_end_iter);
  	$buffer->insert($buffer->get_end_iter,$info);
	
}

sub stop_now
{
	my $item= get_current_item();
	if (!defined $item) {
		message(_("You must select a script before!"));
		return;
		}
        if ($page == $p_rcSd) {
		if (!yesno($rcSwarning)) { return;}		
		}
	
	my $msg=bumlib::stop_service($item->[1]); 
	if ($msg==0) {message(_("Service  stopped."));}
	else {message(_("Failed command execution."));}
 
	populate_list(); 
}

sub start_now
{
	my $item= get_current_item();
	if (!defined $item) {
		message(_("You must select a script before!"));
		return;
		}

	my $msg=bumlib::start_service($item->[1]); 
	if ($msg==0) {message(_("Service  started."));}
	else {message(_("Failed command execution."));}
	populate_list(); 
}

sub change_priority
{
	my $item= get_current_item();
	
	if (!defined $item) {
		message(_("You must select a script before!"));
		return;
		}
	my $start = $item->[4];
	$start =~ s/S//g;
	if ($start !~ /^([0-9][0-9])/) {$start=20;}

	my $stop = $item->[3];
	$stop =~ s/K//g;
	if ($stop !~ /^([0-9][0-9])/) {$stop=20;}

       my $dialog = Gtk2::Dialog->new (_('Change start/stop priority'), undef, 'modal',
	'gtk-ok' => 'ok',  # response ids may be one of the built-in enums...
	'gtk-cancel' => 'cancel',     # or any positive integer.
	);

	my $vbox0 = Gtk2::VBox->new (FALSE, 6);
	my $label =Gtk2::Label->new ();
	$label->set_justify('GTK_JUSTIFY_CENTER');
 	$label->set_markup("<b>". _("Changes will be applied as soon as \nyou click on OK button.")."</b>");
	$vbox0->pack_start ($label, TRUE, TRUE, 3);
	my $label2=Gtk2::Label->new ();
	$label2->set_justify('GTK_JUSTIFY_LEFT');
	$label2->set_markup("<span foreground='red'><b>$item->[1]:</b></span>");
	$vbox0->pack_start ($label2, FALSE, FALSE, 3);
	$vbox0->show_all;

	my $hbox = Gtk2::HBox->new (FALSE, 6);
	$hbox->pack_start (Gtk2::Label->new (_('Startup Priority:')), TRUE, TRUE, 0);
	my $adj = Gtk2::Adjustment->new ($start, 1, 99, 1, 5, 0.0);
	my $spinner = Gtk2::SpinButton->new ($adj, 0, 0);
	$spinner->set_width_chars(3);
	$spinner->set_max_length(2);
	$hbox->pack_start ($spinner, FALSE, FALSE, 3);
	$hbox->show_all;

	my $hbox2 = Gtk2::HBox->new (FALSE, 6);
	$hbox2->pack_start (Gtk2::Label->new (_('Shutdown Priority:')), TRUE, TRUE, 0);
	my $adj2 = Gtk2::Adjustment->new ($stop, 1, 99, 1, 5, 0.0);
	my $spinner2 = Gtk2::SpinButton->new ($adj2, 0, 0);
	$spinner2->set_width_chars(3);
	$spinner2->set_max_length(2);
	$hbox2->pack_start ($spinner2, FALSE, FALSE, 3);
	$hbox2->show_all;

	$dialog->vbox->pack_start ($vbox0, TRUE, TRUE, 3);
	$dialog->vbox->pack_start ($hbox, TRUE, TRUE, 3);
	$dialog->vbox->pack_start ($hbox2, TRUE, TRUE, 3);

	$dialog->set_transient_for($window);
	if ('ok' eq $dialog->run) {
				bumlib::service_priority($item->[1],$spinner->get_value,$spinner2->get_value) ;
				populate_list();
				$dialog -> destroy;
				}
    		else {;}
    	$dialog->destroy;   

}


sub populate_list
{
	my $array_element;
	splice(@{$scripts->{data}});
	splice(@{$summary->{data}});
	my $list=bumlib::get_full_list();

	my @list = split(/@/,$list);
	
	foreach $array_element(@list)
	{
         	my @dati =split(/,/,$array_element);
		my ($info) = bumlib::get_summ_info($dati[1]);  #prendi la descrizione $dati[1]=nome script
		push@{$summary->{data}},[$dati[0],$dati[1], "<b>$info</b>",get_status_pxbf($dati[1]) ]; # $dati[0] =startonboot
		push @{$scripts->{data}}, [@dati];  #per aggiungerli all'inizio usa unshift @.. ,...; 
	}
  $scripts->select(0);
  $summary->select(0);
   return $list;
}

sub populate_rcS_list
{
	my $array_element; my $list="";

	splice(@{$rcS->{data}});
	$list=bumlib::get_full_rcS_list();
	my @list = split(/@/,$list);
	
	
	foreach $array_element(@list)
	{
         my @dati =split(/,/,$array_element);
    	#print STDERR "@dati\n"; 
	push @{$rcS->{data}}, [@dati];  #per aggiungerli all'inizio usa unshift @.. ,...; 
	}
	$md5rcS = get_md5rcS();
   $rcS->select(0);
   return $list;
}

sub get_status_pxbf {

	my $key = shift; #script name

 	my $running = bumlib::check_if_running($key);
	if (!defined($running)) {return $pxbf_boh;}
	if ($running==TRUE) {	return $pxbf_on;}
	elsif($running==FALSE) {return $pxbf_off;}
	elsif($running==-1) {return $pxbf_none;}

}

sub get_md5rcS
{
	use Digest::MD5;
	my $md5 = Digest::MD5->new;
	for my $next (@{$rcS->{data}}) {
		$md5->add(@$next);
		}
	#print STDERR $md5->hexdigest."\n";
	return ($md5->hexdigest);
}




sub message
{
    
  my $messaggio= shift; 
  my $dialog = Gtk2::MessageDialog->new ($window,
                               [qw/modal destroy-with-parent/],
			       'GTK_MESSAGE_INFO',
                              'GTK_BUTTONS_OK',
				$messaggio);
   $dialog->set_markup($messaggio);
    if ('ok' eq $dialog->run) {$dialog -> destroy;}
    else {;}
    $dialog->destroy;   

}    

sub yesno
{
	my $messaggio= shift; 

  	my $dialog = Gtk2::MessageDialog->new ($window,
                               [qw/modal destroy-with-parent/],
			       'GTK_MESSAGE_QUESTION',
                              'GTK_BUTTONS_YES_NO',
				$messaggio);
 $dialog->set_markup($messaggio);
	if ('yes' eq $dialog->run) {$dialog -> destroy;return TRUE;}
    	else {;}
    	$dialog->destroy;
	return FALSE;   


}

sub yesnocancel
{
	my $messaggio= shift; 
	my $ret;
  	my $dialog = Gtk2::MessageDialog->new ($window,
                               [qw/modal destroy-with-parent/],
			       'GTK_MESSAGE_QUESTION',
                              'GTK_BUTTONS_YES_NO' ,
				$messaggio);
	$dialog->add_button('gtk-cancel','GTK_RESPONSE_CANCEL');
#$dialog->set_markup($messaggio);
	if ('yes' eq ($ret=$dialog->run)) {$dialog -> destroy;return $ret;}
    	else {;}
    	$dialog->destroy;
	return $ret;   


}

sub stock_label_box {
	my ($stockname, $label_text) = @_;

	# create box for image and label 
	my $box = Gtk2::HBox->new(FALSE, 0);
	$box->set_border_width(2);

	# now on to the image stuff
	my $image = Gtk2::Image->new_from_stock($stockname,GTK_ICON_SIZE_BUTTON);
	
	# Create a label for the button
	my $label = Gtk2::Label->new_with_mnemonic($label_text);
	
	# pack the image and label into the box
	$box->pack_start($image, FALSE, FALSE, 3);
	$box->pack_start($label, FALSE, FALSE, 3);

	$image->show;
	$label->show;

	return $box
}

sub add_buttons
{
    my $parent = shift;
    my $button;
    my $tooltip;

    my $hbox = Gtk2::HBox->new(FALSE,2);
    $parent->pack_start ($hbox,FALSE,FALSE,1);
  
    
    #Button Exit
    $button= Gtk2::Button->new();
    $button->signal_connect( clicked => sub {bumlib::remove_lock();Gtk2->main_quit;} );
    my $box =stock_label_box('gtk-quit',_("Exit"));
    $box->show();
    $button->add($box);
    $tooltip = Gtk2::Tooltips->new();
    $tooltip->set_tip($button, _('Cancel changes and exit'));

    $hbox->pack_end($button, FALSE, FALSE, 1);

    #Button Save & Exit
    $button= Gtk2::Button->new();
    $button->signal_connect( clicked => sub {bum_save(yesnocancel(_("Start or stop services now? \n(If you answer No, changes will be applied at next boot.)")));});
    $box =stock_label_box('gtk-save',_("_Apply changes"));
    $box->show();
    $button->add($box);

    $apply_button=$button;
    $tooltip = Gtk2::Tooltips->new();
    $tooltip->set_tip($button, _('Apply changes '));
   
    $hbox->pack_end($button, FALSE, FALSE, 1);


    return $hbox;
}

sub bum_save
{
	my $ret = shift;
       my $current_md5 = get_md5rcS();
	if ( $md5rcS ne $current_md5) {
			if (!yesno($rcSwarning)) { return;}
			}

	#hour-glass
	$window -> window -> set_cursor(Gtk2::Gdk::Cursor -> new("watch"));
   	Gtk2->main_iteration while (Gtk2->events_pending); 			#clear the event queue!!
 
	
	bumlib::make_changes($scripts->{data},$ret);
	populate_list();
	populate_rcS_list();
	
	#restore pointer
	$window -> window -> set_cursor(Gtk2::Gdk::Cursor -> new("left-ptr"));

}

sub check_if_root
{
my $io = `whoami`;
chomp $io;
if ($io ne "root") {

		message(_("This program must be run with root privileges!"));
		return FALSE;
		}
return TRUE;		
}

sub check_if_lock
{

my ($ret, $lockfile) = bumlib::make_lock();
if ($ret == 0) {

		message(_("Another bum is running, or  the file:")." <i>$lockfile</i> "._("remains locked!"));
		return FALSE;
		}
return TRUE;		
}


############################
sub bum_initialized {
	#create the 'waiting' dialog
	my $popup = Gtk2::Window->new('toplevel');
	$popup -> set_resizable (FALSE);
	$popup->set_position('center');
	$popup->set_title("BUM"); 
	$popup->set_border_width(4);
	$popup->set_default_icon_from_file(ICONFILE);

	my $pbar = Gtk2::ProgressBar->new();
	$pbar->set_pulse_step(.1);

	my $vbox0 = Gtk2::VBox->new (FALSE, 6);
	$vbox0->set_border_width(10);

	my $label=Gtk2::Label->new ();
	$label->set_justify('GTK_JUSTIFY_CENTER');
	$label->set_markup("<b>"._("Please wait... loading data...")."</b>");

	$vbox0->pack_start($label,FALSE, FALSE, 0);
	$vbox0->pack_start($pbar,FALSE, FALSE, 0);

	$pbar->show;
	$vbox0->show_all;
	$popup->add($vbox0);
	$popup->show_all;

	#hour-glass and progress bar
	$window -> window -> set_cursor(Gtk2::Gdk::Cursor -> new("watch"));
		Gtk2->main_iteration while (Gtk2->events_pending); 
	bum_init::init_human_text();
		$pbar->set_fraction(.16);
		Gtk2->main_iteration while (Gtk2->events_pending); 
	bumlib::get_full_list();
		$pbar->set_fraction(.35);
		Gtk2->main_iteration while (Gtk2->events_pending); 
	bumlib::get_full_rcS_list();	
		$pbar->set_fraction(.50);
		Gtk2->main_iteration while (Gtk2->events_pending); 
	bumlib::get_packages();
		$pbar->set_fraction(.65);
		Gtk2->main_iteration while (Gtk2->events_pending); 
	populate_list();
		$pbar->set_fraction(.80);
		Gtk2->main_iteration while (Gtk2->events_pending); 
	populate_rcS_list();
		$pbar->set_fraction(1.0);
		Gtk2->main_iteration while (Gtk2->events_pending); 

	$rcS->select(0);
	$scripts->select(0);
	#$wNB->set_current_page($p_DefaultRL);
	$wNB->set_current_page($p_Summary);
	#restore pointer
	$window -> window -> set_cursor(Gtk2::Gdk::Cursor -> new("left-ptr"));

	$popup->destroy;
}

#########################
sub create_standardRL_page
{

	my $vPane; 
	my $info_box;
# set and create main Paned windows
  $vPane =Gtk2::VPaned->new; 
  my $frame1 = Gtk2::Frame->new(_("Services"));
  my $frame2 = Gtk2::Frame->new(_("Information"));
  $frame1->set_shadow_type(GTK_SHADOW_IN);
  $frame2->set_shadow_type(GTK_SHADOW_IN);
  $vPane->set_size_request(-1,350);
  # frames for panes
  $vPane->pack1($frame1,TRUE,FALSE);
  $frame1->set_size_request(-1,60); 
  $vPane->pack2($frame2,TRUE,FALSE);
  $frame2->set_size_request(-1,40); 
  

  $wNB->insert_page($vPane,_("Services"),$p_DefaultRL);

#
   create_listbox($frame1);

#
   
   $info_buffer = create_info_box($frame2);
}

#############################
sub create_rcS_page
{
	my $vPane; 
	my $info_box;

# set and create main Paned windows
  $vPane =Gtk2::VPaned->new; 
  my $frame1 = Gtk2::Frame->new(_("Scripts"));
  my $frame2 = Gtk2::Frame->new(_("Information"));
  $frame1->set_shadow_type(GTK_SHADOW_IN);
  $frame2->set_shadow_type(GTK_SHADOW_IN);
  #$vPane->set_size_request(680,350);
  # frames for panes
  $vPane->pack1($frame1,TRUE,FALSE);
  $frame1->set_size_request(-1,60); 
  $vPane->pack2($frame2,TRUE,FALSE);
  $frame2->set_size_request(-1,40); 
	
  $info_buffer_rcS = create_info_box($frame2);	
	$wNB->insert_page($vPane,_("Startup and shutdown scripts"),$p_rcSd);

   create_rcS_listbox($frame1);
  $info_buffer_rcS->create_tag ("title", weight => 700);
  
}


###########################################
sub create_first_page {

  my $frame1 = Gtk2::Frame->new(_("Services"));

	$frame1->set_shadow_type(GTK_SHADOW_IN);
	$wNB->insert_page($frame1,_("Summary"),$p_Summary);
	create_summary_listbox($frame1);

}

########################################################################
# GUI principale
########################################################################


sub main_gui
{

    	my $vbox_main_container;
	

    
    $window = create_window();
    $window->signal_connect( show => sub {bum_initialized();}); 
    
    $vbox_main_container = create_V_container($window); 
    $menu = create_menu();
    $window->add_accel_group($menu->{accel_group});

   $vbox_main_container->pack_start($menu->{widget},FALSE,FALSE,1);

    $wNB= Gtk2::Notebook->new;	
    $vbox_main_container->pack_start_defaults ($wNB);
  
  	
   	create_first_page();
   	create_standardRL_page();
   	create_rcS_page();
	$info_buffer->create_tag ("title", weight => 700);
      add_buttons($vbox_main_container);
   

  $wNB->set_current_page(0);
  check_if_root() || die _("Run as root or \'gksudo bum\'\n");
  check_if_lock() || die _("Another bum is running, or  the file \/var\/lock\/bum remains locked!\n");

   $wNB->signal_connect_after ('switch-page' => sub {change_page();}); 

   $window->show_all;
   
 
    Gtk2->main;

}

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

main_gui();


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

__END__

=head1 NAME

B<Boot-Up Manager> - Graphical runlevel configuration tool

=head1 SYNOPSIS

B<bum> 

=head1 DESCRIPTION

B<bum> allows  to configure init services  when the system boots 
up or re_(boots.  It displays a list of every service which could be started at boot.  
User can toggle individual services on and off.

A detailed documentation on the program could be read at:
http://www.marzocca.net/linux/bumdocs.html.


=head1 FILE

=over 2

=item /var/lib/bum/packages

The script<->packages name file.

=item /var/lib/bum/numbers

The service number data file.

=item /var/lock/bum

Lock file.


=back

=head1 SEE ALSO

update-rc.d(8)

rcconf(8)

=head1 AUTHOR

Fabio MARZOCCA <thesaltydog@gmail.org>

=cut

