#!/usr/bin/env perl

#Copyright (C) 2006 Munteanu Alexandru Ionut
#
#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., 51 Franklin Street, Fifth Floor, Boston, MA
#02110-1301, USA.

#includes
use strict;
use warnings;
use Glib qw/TRUE FALSE/;
use Gtk2;
use Gtk2::SimpleList;
use Data::Dumper;
use Cwd qw(realpath);
use File::Basename;
use threads;

#constants
my $program_version = "0.1";
my $program_name = "Network-config";
my $program_author = "Munteanu Alexandru Ionut\nio_alex_2002 AT yahoo.fr";
my $program_date = "- released on 05.08.2006 -";
my $graphic_mode = TRUE;
my $etc_dir="/etc";

#internal global variables
#main window
my $main_window;
#select tab
my $description_label;
my $start_vbox;
my $start_hbox;
my $select_list;
my $internet_site_hbox;
#final dialog
my $dialog;
#right vertical box with all the options
my $main_hbox;
my $main_vbox;
my $main_notebook;
#ethernet cards
my @ethernet_cards;
my @wifi_cards;
my @virtual_cards;
#virtual+wifi+non wifi cards
my @all_cards;
#ethernet notebooks
my @all_eth_notebooks;
#right preferences notebook
my $hidden_notebook;
#left configuration list
my $left_simple_list;
my $old_selected_number = 0;
#all the settings
my @all_settings;
#if expanded or not
my $expanded_description = FALSE;
#console text
my $console_text_buffer;
my $console_text_view;
#change config-select buttons
my $remove_config_button;
#we keep in mind the top labels with the name of the configurations,
#to update them if the name changes
my @top_config_names;
#apply or test dialog close button
my $dialog_close_button;
#preferences variables
my $test_for_internet=FALSE;
my $internet_site_for_ping="";
my $wpa_configuration_file="/etc/wpa_supplicant/wpa_psk.conf";
my $wpa_driver="ndiswrapper";
my $dhcp_client="dhclient";
#scan for networks dialog
my $scan_dialog = undef;
my $scan_top_label;
my $scan_list;    
#preferences global variables
my $pref_dhcp_entry;

#creates a custom button with ($name,$icon_from_stock)
sub get_custom_button
{
    my ($name,$icon_from_stock,$tooltip) = @_;
    
    #the button
    my $button = Gtk2::Button->new;
    my $b_tooltip = Gtk2::Tooltips->new;
    $b_tooltip->set_tip($button,$tooltip);
    #the hbox inside the button
    my $box = Gtk2::HBox->new(FALSE, 0);
    $box->set_border_width(2);
    my $image = Gtk2::Image->new_from_stock($icon_from_stock,"small-toolbar");
    #button label
    my $label = Gtk2::Label->new_with_mnemonic($name);
    # pack the image and label into the box
    $box->pack_start($image, FALSE, FALSE, 3);
    $box->pack_start($label, FALSE, FALSE, 3);
    
    $button->add($box);
    
    return $button;
}

#the config selection number
sub get_config_selection_number
{
    my $selection = $left_simple_list->get_selection;
    my ($model,$iter) = $selection->get_selected;
    my $tree_path =  $model->get_path($iter);
    my $selected_number = $tree_path->get_indices;
    
    return $selected_number;
}

#the select selection number
sub get_select_selection_number
{
    my $selection = $select_list->get_selection;
    my ($model,$iter) = $selection->get_selected;
    my $tree_path;
    my $selected_number;
    if ($model)
    {
        $tree_path =  $model->get_path($iter);
        $selected_number = $tree_path->get_indices;
    }
    else
    {
        $selected_number = 0;
    }
    
    return $selected_number;
}

#get the selected config and the selected device inside the config
sub get_selected_config_and_device
{
    #we get the selection
    my $selection = $left_simple_list->get_selection;
    my ($model,$iter) = $selection->get_selected;
    if ($iter)
    {
	my $tree_path =  $model->get_path($iter);
	my $selected_number = $tree_path->get_indices;
	
	my $device = 0;
	$device = $all_eth_notebooks[$selected_number]->get_current_page-1;
        
	return $selected_number,$all_cards[$device];
    }
    else
    {
	return undef,undef;
    }
}

#gets the selected scanned wifi
sub get_selected_scanned_wifi
{
    #we get the selection
    my $selection = $scan_list->get_selection;
    my ($model,$iter) = $selection->get_selected;
    if ($iter)
    {
	my $tree_path =  $model->get_path($iter);
	my $selected_number = $tree_path->get_indices;
	
	return @{$scan_list->{data}}[$selected_number]->[0];
    }
    else
    {
	return undef;
    }
}

#changes events, must change the @all_settings
sub default_route_combo_box_event
{
    my ($widget) = @_;
    
    my ($config,$device) = get_selected_config_and_device();
    
    if (defined($config) && defined($device))
    {
	$all_settings[$config]->{default_net} = $widget->get_active_text;
	
	save_settings();
    }
}

sub dns1_event
{
    my ($widget) = @_;
    
    my ($config,$device) = get_selected_config_and_device();
    
    if (defined($config) && defined($device))
    {
	$all_settings[$config]->{dns1} = $widget->get_text;
	
	save_settings();
    }
}

sub dns2_event
{
    my ($widget) = @_;
    
    my ($config,$device) = get_selected_config_and_device();
    
    if (defined($config) && defined($device))
    {
	$all_settings[$config]->{dns2} = $widget->get_text;
	
	save_settings();
    }
}

sub dns3_event
{
    my ($widget) = @_;
    
    my ($config,$device) = get_selected_config_and_device();
    
    if (defined($config) && defined($device))
    {
	$all_settings[$config]->{dns3} = $widget->get_text;
	
	save_settings();
    }
}

sub activate_event
{
    my ($widget,$bottom_box) = @_;
    
    #check button state
    if ($widget->get_active)
    {
        $bottom_box->set_sensitive(TRUE);
        $expanded_description = TRUE;
    }
    else
    {
        $bottom_box->set_sensitive(FALSE);
        $expanded_description = FALSE;
    }
    
    #we save the settings
    my ($config,$device) = get_selected_config_and_device();
    
    if (defined($config) && defined($device))
    {
	if ($widget->get_active)
	{
	    $all_settings[$config]->{devices}->{$device}->{active} = "TRUE";
	}
	else
	{
	    $all_settings[$config]->{devices}->{$device}->{active} = "FALSE";
	}
	
	save_settings();
    }
}

sub activate_network_forwarding_event
{
    my ($widget,$check_data) = @_;
    
    #check button state
    if ($widget->get_active)
    {
        $check_data->[0]->set_sensitive(TRUE);
    }
    else
    {
        $check_data->[0]->set_sensitive(FALSE);
    }
    
    #we save the settings
    my ($config,$device) = get_selected_config_and_device();
    
    if (defined($config) && defined($device))
    {
	if ($widget->get_active)
	{
	    $all_settings[$config]->{devices}->{$device}->{nat} = "TRUE";
	}
	else
	{
	    $all_settings[$config]->{devices}->{$device}->{nat} = "FALSE";
	}
	
	save_settings();
    }
}

sub wifi_ESSID_entry_event
{
    my ($widget) = @_;
    
    my ($config,$device) = get_selected_config_and_device();
    
    if (defined($config) && defined($device))
    {
	$all_settings[$config]->{devices}->{$device}->{w_ssid} = $widget->get_text;
	
	save_settings();
    }
}

sub wifi_rate_entry_event
{
    my ($widget) = @_;
    
    my ($config,$device) = get_selected_config_and_device();
    
    if (defined($config) && defined($device))
    {
	$all_settings[$config]->{devices}->{$device}->{w_rate} = $widget->get_text;
	
	save_settings();
    }
}

sub wifi_key_entry_event
{
    my ($widget) = @_;
    
    my ($config,$device) = get_selected_config_and_device();
    
    if (defined($config) && defined($device))
    {
	$all_settings[$config]->{devices}->{$device}->{w_wep} = $widget->get_text;
	
	save_settings();
    }
}

sub wifi_wpa_pass_key_entry_event
{
    my ($widget) = @_;
    
    my ($config,$device) = get_selected_config_and_device();
    
    if (defined($config) && defined($device))
    {
	$all_settings[$config]->{devices}->{$device}->{w_wpa} = $widget->get_text;
	
	save_settings();
    }
}

sub ip_entry_event
{
    my ($widget) = @_;
    
    my ($config,$device) = get_selected_config_and_device();
    
    if (defined($config) && defined($device))
    {
	$all_settings[$config]->{devices}->{$device}->{ip} = $widget->get_text;
	
	save_settings();
    }
}

sub netmask_entry_event
{
    my ($widget) = @_;
    
    my ($config,$device) = get_selected_config_and_device();
    
    if (defined($config) && defined($device))
    {
	$all_settings[$config]->{devices}->{$device}->{netmask} = $widget->get_text;
	
	save_settings();
    }
}

sub gateway_entry_event
{
    my ($widget) = @_;
    
    my ($config,$device) = get_selected_config_and_device();
    
    if (defined($config) && defined($device))
    {
	$all_settings[$config]->{devices}->{$device}->{gateway} = $widget->get_text;
	
	save_settings();
    }
}

#returns a new configuration
sub get_new_config
{
    my %devices = ();
    
    my $is_wifi;
    foreach (@all_cards)
    {
        $is_wifi = "FALSE";
        if (is_wifi($_))
        {
            $is_wifi = "TRUE";
        }
        
        chomp;
        $devices{$_} = 
        {
            name => $_,
            wifi => $is_wifi,
            w_ssid => "",
            w_rate => "auto",
            w_wep => "",
            w_wpa => "",
            active => "FALSE",
            nat => "FALSE",
            dhcp => "TRUE",
            ip => "",
            netmask => "",
            gateway => "",
        }
    }
    
    my $program_dir = dirname(realpath($0));
    my $one_setting = {
	name => "new_config",
	icon => "/usr/share/network-config/default-icon.png",
	description => "your description here",
	default_net => $ethernet_cards[0],
	dns_auto => "TRUE",
	dns1 => "",
	dns2 => "",
	dns3 => "",
	devices =>
	{
            %devices
        }
    };
    
    return $one_setting;
}

#new configuration event
sub left_popup_menu_new_event
{
    push @{$left_simple_list->{data}},"new_config";
    
    my $one_setting = get_new_config();
    
    put_new_config_page($one_setting);
    push @all_settings,$one_setting;
    
    save_settings();
    refresh_select_menu();
    
    #we enable remove button
    if (!$remove_config_button->is_sensitive)
    {
        $remove_config_button->set_sensitive(TRUE);
    }
}

#remove configuration event
sub left_popup_menu_remove_event
{
    #we delete if more than one element
    if ($#all_settings > 0)
    {
	my $selected_number =
	    join(", ",$left_simple_list->get_selected_indices);
	splice @{$left_simple_list->{data}},$selected_number,1;
        #remove notebooks references
	splice @all_eth_notebooks,$selected_number,1;
	splice @top_config_names,$selected_number,1;
	
	#we remove settings
	splice @all_settings,$selected_number,1;
        $hidden_notebook->remove_page($selected_number);
	
	#if we have no selection
        my @data = @{$left_simple_list->{data}};
        
        if ($selected_number != 0)
        {
            $left_simple_list->select($selected_number-1);
            refresh_right_part($selected_number-1);
        }
        else
        {
            $left_simple_list->select($selected_number);
            refresh_right_part($selected_number);
        }
	
        refresh_select_menu();
	save_settings();
    }
}

#execute a command
sub execute_command
{
    my ($command) = @_;
    
    my $real_command = $command;
    #we don't print the secret key
    if ($real_command =~ /iwconfig(.*)key(.*)/)
    {
	$real_command = "iwconfig".$1."key XXX...";
    }
    
    #if we are in graphic mode
    if ($graphic_mode)
    {
	Gtk2::Gdk::Threads->enter;
	#we put the text at the end
	my $iter = $console_text_buffer->get_end_iter;
	$console_text_buffer->insert_with_tags_by_name($iter,"\$ ".$real_command."\n","yellow_fg");
	Gtk2::Gdk::Threads->leave;
	
	#we get STDOUT and STDERR
	open(STDOUT, "> .network_config_logfile");
	open(STDERR, "> .network_config_logfile");
	
	system($command);
	
	open(FILE,"< .network_config_logfile");
	my $result = "";
	while (<FILE>)
	{
	    $result .= $_;
	}
	close(FILE);
	
	Gtk2::Gdk::Threads->enter;
	$iter = $console_text_buffer->get_end_iter;
	$console_text_buffer->insert_with_tags_by_name($iter,$result."\n","white_fg");
	
	#remove log file
	unlink ".network_config_logfile";
		  
	#we scroll down
	my $end_mark = $console_text_buffer->create_mark ('end', $console_text_buffer->get_end_iter,
							  FALSE);
	$console_text_view->scroll_to_mark ($end_mark, 0.0, TRUE, 0.0, 1.0);
	
	$dialog->grab_focus;
	Gtk2::Gdk::Threads->leave;
    }
    else
    {
	print "\n".$real_command."\n";
	system($command);
    }
}

#we apply the current settings
sub apply_network_settings
{
    my ($current_config_number) = @_;
    
    my $current_config =
	$all_settings[$current_config_number];
    
    my $command;
    
    #if we dont have auto dns
    if ($current_config->{dns_auto} eq "FALSE")
    {
        #we put the 3 dns servers
        $command = "echo \"nameserver $current_config->{dns1}\" > /etc/resolv.conf";
        execute_command($command);
        $command = "echo \"nameserver $current_config->{dns2}\" >> /etc/resolv.conf";
        execute_command($command);
        $command = "echo \"nameserver $current_config->{dns3}\" >> /etc/resolv.conf";
        execute_command($command);
    }
    
    #default network
    my $default_net = 
        $current_config->{devices}->{$current_config->{default_net}};
    
    #we set all devices
    my @all_devices = keys %{$current_config->{devices}};
    #we save the devices
    foreach my $dev (@all_devices)
    {
	my $device = $current_config->{devices}->{$dev};
	
	#if the device is not virtual (exists)
	if (!is_virtual($device->{name}))
	{
	    #if graphic mode
	    if ($graphic_mode)
	    {
		Gtk2::Gdk::Threads->enter;
		#we put the text at the end
		my $iter = $console_text_buffer->get_end_iter;
		$console_text_buffer->insert_with_tags_by_name($iter,"Configuring device ".$device->{name}." :\n\n","green_fg");
		Gtk2::Gdk::Threads->leave;
            }
	    
	    if ($device->{active} eq "TRUE")
	    {
		#if wifi
		if ($device->{wifi} eq "TRUE")
		{
		    $command = "iwconfig $device->{name} essid \"$device->{w_ssid}\"";
		    execute_command($command);
		    $command = "iwconfig $device->{name} rate $device->{w_rate}";
		    execute_command($command);
		    #WEP key
		    if (($device->{w_wep} ne "") &&
			$device->{w_wep})
		    {
			$command = "iwconfig $device->{name} key $device->{w_wep}";
		    }
		    else
		    {
			$command = "iwconfig $device->{name} key off";
		    }
		    execute_command($command);
		    
		    #WPA PSK
		    if (($device->{w_wpa} ne "") &&
			$device->{w_wpa})
		    {
			#we write wpa_assistant file
			open(FILE,"+> $wpa_configuration_file");
			my $wpa_config = "
network={
         ssid=\"$device->{w_ssid}\"
         scan_ssid=1
         key_mgmt=WPA-PSK
         psk=\"$device->{w_wpa}\"
        }
";
			print FILE $wpa_config;
			close(FILE);
			#we run wpa_supplicant
			$command="pkill -9 wpa_supplicant";
			execute_command($command);
			$command="wpa_supplicant -Bw -D$wpa_driver -i$device->{name} -c$wpa_configuration_file";
			execute_command($command);
		    }
		}
		
		#bring up device
		$command = "ifconfig $device->{name} up";
		execute_command($command);
		
		#if dhcp
		if ($device->{dhcp} eq "TRUE")
		{
		    if ($graphic_mode)
		    {
			Gtk2::Gdk::Threads->enter;
			#we put the text at the end
			my $iter = $console_text_buffer->get_end_iter;
			$console_text_buffer->insert_with_tags_by_name($iter,"DHCP may take a while, please wait...\n",
								       "green_fg");
			Gtk2::Gdk::Threads->leave;
		    }
		    
		    $command = "$dhcp_client $device->{name}";
		    execute_command($command);
		}
		#if static ip
		else
		{
		    #ip and netmask
		    $command = "ifconfig $device->{name} $device->{ip} netmask $device->{netmask}";
		    execute_command($command);
		    
		    #if the gateway is not the default
		    if ($default_net->{name} ne $device->{name})
		    {
			if ($device->{gateway} || 
			    ($device->{gateway} ne ""))
			{
			    $command = "route add $device->{ip} gw $device->{gateway}";
			    execute_command($command);
			}
		    }
		}
		
		#if nat server
		if ($device->{nat} eq "TRUE")
		{
		    $command = "modprobe iptable_nat";
		    execute_command($command);
		    $command = "echo 1 > /proc/sys/net/ipv4/ip_forward";
		    execute_command($command);
		    $command = "iptables -t nat -A POSTROUTING -o $default_net->{name} -j MASQUERADE";
		    execute_command($command);
		    $command = "iptables -A FORWARD -i $device->{name} -j ACCEPT";
		    execute_command($command);
		}
	    }
	    else
	    {
		#bring down device
		$command = "ifconfig $device->{name} down";
		execute_command($command);
	    }
	}
	else
	{
	    #if graphic mode
	    if ($graphic_mode)
	    {
		Gtk2::Gdk::Threads->enter;
		#we put the text at the end
		my $iter = $console_text_buffer->get_end_iter;
		$console_text_buffer->insert_with_tags_by_name($iter,"Warning ! Device ".$device->{name}.
							       " does not exists.\n\n","green_fg");
		Gtk2::Gdk::Threads->leave;
	    }
	}
    }
    
    #if not dhcp
    if ($default_net->{dhcp} eq "FALSE")
    {
	#default ethernet device
	if ($default_net->{active} eq "TRUE")
	{
	    my $default_gw = $default_net->{gateway};
	    if ($default_gw && ($default_gw ne ""))
	    {
		$command = "route del -net default 2>/dev/null";
		execute_command($command);
		$command = "route add default gw $default_gw";
		execute_command($command);
	    }
	}
    }
    
    #if we test for internet
    if ($test_for_internet)
    {
	$command = "ping -c 6 -i 0.2 $internet_site_for_ping";
	execute_command($command);
    }
    
    if ($graphic_mode)
    {
	Gtk2::Gdk::Threads->enter;
	#enable close button
	$dialog_close_button->set_sensitive(TRUE);
	$dialog_close_button->grab_focus;
	Gtk2::Gdk::Threads->leave;
    }
}

#apply button event (confirmation popup)
sub apply_button_event
{
    ####################################
    #the important thing
    
    my $select_tab = TRUE;
    #we find out where we were when we have pushed the apply button
    my $current_page = $main_notebook->get_current_page;
    my $selected_number = 0;
    #if we are on the select tab
    if ($current_page == 0)
    {
	$selected_number = get_select_selection_number();
    }
    else
    {
	#if we are on the Configuration tab
	if ($current_page == 1)
	{
            $selected_number = get_config_selection_number();
            $select_tab = FALSE;
        }
    }
    
    ####################################
    #apply confirmation dialog
    $dialog = Gtk2::Dialog->new ("Applying changes...",
                                 $main_window,
                                 [qw/modal
                                  destroy-with-parent/]);
    $dialog->set_size_request (570, 300);
    #$dialog->set_resizable(FALSE);
    $dialog->signal_connect("delete-event" =>
			    sub {
				return TRUE;
			    });
    
    if ($select_tab)
    {
        #we put the close button to the dialog
        $dialog_close_button = 
            $dialog->add_button("gtk-quit","apply");
        $dialog_close_button->set_sensitive(FALSE);
    }
    else
    {
        #we put the close button to the dialog
        $dialog_close_button =
            $dialog->add_button("gtk-close","apply");
        $dialog_close_button->set_sensitive(FALSE);
    }
    $dialog_close_button->queue_draw;
    
    #if we push close button
    my $close_button_vars =
	[$dialog,$select_tab];
    $dialog_close_button->signal_connect(clicked => sub {
	my ($widget,$close_button_vars) = @_;
	$close_button_vars->[0]->destroy;
	$close_button_vars->[0] = undef;
	if ($close_button_vars->[1])
	{
	    Gtk2->main_quit;
	}
    },$close_button_vars);
    
    #################################
    #console output
    my $console_hbox = Gtk2::HBox->new;
    my $scrolled_window = Gtk2::ScrolledWindow->new;
    $scrolled_window->set_policy('automatic','automatic');
    $console_text_buffer = Gtk2::TextBuffer->new;
    $console_text_view = Gtk2::TextView->new_with_buffer($console_text_buffer);
    $console_text_buffer->create_tag("yellow_fg", foreground => "yellow");
    $console_text_buffer->create_tag("white_fg", foreground => "white");
    $console_text_buffer->create_tag("green_fg", foreground => "green");
    #change TextView colors
    my $bg_color = Gtk2::Gdk::Color->parse('black');
    my $fg_color = Gtk2::Gdk::Color->parse('white');
    $console_text_view->modify_text('normal', $fg_color);
    $console_text_view->modify_base('normal', $bg_color);
    $console_text_view->modify_text('active', $fg_color);
    $console_text_view->modify_base('active', $bg_color);
    $scrolled_window->add($console_text_view);
    $console_hbox->pack_start($scrolled_window,TRUE,TRUE,5);
    
    my $wait_label = Gtk2::Label->new("Terminal output :");
    my $fake_horiz = Gtk2::HBox->new;
    my $console_vbox = Gtk2::VBox->new;
    $fake_horiz->pack_start($wait_label,FALSE,FALSE,5);
    $console_vbox->pack_start($fake_horiz,FALSE,FALSE,0);
    $console_vbox->pack_start($console_hbox,TRUE,TRUE,0);
    $dialog->vbox->pack_start($console_vbox,TRUE,TRUE,10);
    
    $dialog->show_all;
    $dialog->queue_draw;
    
    if ($select_tab)
    {
        $main_window->hide;
    }
    
    #the most important
    my $thread = threads->new(\&apply_network_settings,
			      $selected_number);
    #apply_network_settings($selected_number);
}

#dhcp selector event
sub dhcp_selector_event
{
    my ($widget,$data) = @_;
    my $group = $widget->get_group;
    
    #we take the selected
    my $selected;
    foreach my $r (@$group)
    {
	if ($r->get_active)
	{
	    $selected = $r->get_name();
	}
    }
    
    #get the selected config and the selected device
    my ($config,$device) = get_selected_config_and_device();
    
    #auto dhcp
    if ($selected eq "auto")
    {
	deactivate_ip_netmask_gateway($data);
	
	if (defined($config) && defined($device))
	{
	    $all_settings[$config]->{devices}->{$device}->{dhcp} = "TRUE";
	}
    }
    #static ip
    else
    {
	activate_ip_netmask_gateway($data);
	
	if (defined($config) && defined($device))
	{
	    $all_settings[$config]->{devices}->{$device}->{dhcp} = "FALSE";
	}
    }
    
    save_settings();
}

#dns selector event
sub dns_selector_event
{
    my ($widget,$data) = @_;
    my $group = $widget->get_group;
    
    #we take the selected
    my $selected;
    foreach my $r (@$group)
    {
	if ($r->get_active)
	    {
		$selected = $r->get_name();
	    }
    }
    
    #get the selected config and the selected device
    my ($config,$device) = get_selected_config_and_device();
    
    #auto dhcp
    if ($selected eq "auto")
    {
        #deactivate dns entries
        $data->[0]->set_sensitive(FALSE);
        $data->[1]->set_sensitive(FALSE);
        $data->[2]->set_sensitive(FALSE);
	
	if (defined($config))
	{
	    $all_settings[$config]->{dns_auto} = "TRUE";
	}
    }
    #static ip
    else
    {
        #activate dns entries
        $data->[0]->set_sensitive(TRUE);
        $data->[1]->set_sensitive(TRUE);
        $data->[2]->set_sensitive(TRUE);
	
	if (defined($config))
	{
	    $all_settings[$config]->{dns_auto} = "FALSE";
	}
    }
    
    save_settings();
}

#rename event
sub left_simple_list_name_changed_event
{
    my ($widget) = @_;
    my ($config,$device) = get_selected_config_and_device();
    
    if (defined($config) && defined($device))
    {
	#we get the selection
	my $selection = $left_simple_list->get_selection;
	my ($model,$iter) = $selection->get_selected;
	
	if ($all_settings[$config]->{name} ne $model->get($iter, 0))
	{
	    my $text = $model->get($iter, 0);
            my $test_text = $text;
	    $test_text =~ s/\s+//;
	    #if spaces or nothing
	    if (!$test_text)
	    {
		$text = "name";
		my $tree_path =  $model->get_path($iter);
		my $selected_number = $tree_path->get_indices;
		@{$left_simple_list->{data}}[$selected_number]=$text;
	    }
	    
	    $all_settings[$config]->{name} = $text;
	    
	    save_settings();
	    refresh_select_menu();
	    
	    #we rename the top label
	    my $top_label = $top_config_names[$config];
	    if (length($text) > 25)
	    {
		$text = substr($text,0,25);
		$text .= "...";
	    }
	    $top_label->set_markup("<big><b>$text</b></big>");
	}
    }
    
    #we get the selection
    my $selected_number = get_config_selection_number();
    if ($selected_number != $old_selected_number)
    {
        $old_selected_number = $selected_number;
        refresh_right_part($selected_number);
    }
    
    return TRUE;
}

#change icon button event
sub change_icon_button_event
{
    my ($widget,$current_icon) = @_;
    my $icon_file_chooser = 
	Gtk2::FileChooserDialog->new("Choose icon file",
				     $main_window,'open',
				     'gtk-cancel' => 'cancel',
				     'gtk-ok' => 'ok');
    $icon_file_chooser->set_current_folder("/usr/share/pixmaps");
    $icon_file_chooser->signal_connect(selection_changed => sub {
	my $filename =
	    $icon_file_chooser->get_preview_filename;
	#the icon preview
	my $preview_icon = Gtk2::Image->new_from_file("/");
	$icon_file_chooser->set(preview_widget => $preview_icon,
				preview_widget_active => TRUE);
	my $current = defined $filename && not -d $filename;
	$preview_icon->set_from_file($filename);
    });
    $icon_file_chooser->show;
    
    #we get the file chooser response
    if ('ok' eq $icon_file_chooser->run)
    {
        my $selected_filename = 
	    $icon_file_chooser->get_filename;
	
	my ($config,$device) = get_selected_config_and_device();
	
	if (defined($config) && defined($device))
	{
	    $all_settings[$config]->{icon} = $selected_filename;
	    
	    $current_icon->set_from_file($selected_filename);
	    
	    save_settings();
	    refresh_select_menu();
	}
    }
    
    $icon_file_chooser->destroy;
}

#real time refresh of the select menu
sub refresh_select_menu
{
    #remove all lines
    @{$select_list->{data}} = ();
    
    #we put the icons, configs names and descriptions
    foreach (@all_settings)
    {
	my $icon_name = $_->{icon};
	if ($icon_name)
	{
	    my $icon_pixbuf;
	    my $program_dir = dirname(realpath($0));
	    #if the icon exists
	    if (-e "$icon_name")
	    {
		$icon_pixbuf = Gtk2::Gdk::Pixbuf->new_from_file($icon_name);
	    }
	    else
	    {
		$icon_pixbuf =
		    Gtk2::Gdk::Pixbuf->new_from_file("/usr/share/network-config/default-icon.png");
	    }
	    push @{$select_list->{data}},[$icon_pixbuf,$_->{name}];
	}
	else
	{
	    push @{$select_list->{data}},[undef,$_->{name}];
	}
    }
    
    #refresh description
    my $selected_number = get_select_selection_number();
    if ($selected_number)
    {
        my $new_text = $all_settings[$selected_number]->{description};
        $description_label->set_text($new_text);
    }
}

#save all the settings
sub save_settings
{
    ###########################################
    #SAVE
    #if we don't have the application directory
    if (!opendir(DIR,"$etc_dir/network-config"))
    {
	mkdir "$etc_dir/network-config";
	chmod 0700,"$etc_dir/network-config";
    }
    closedir(DIR);
    
    #we open the settings file
    if (! -e "$etc_dir/network-config/settings.txt")
    {
	open(FILE,"+> $etc_dir/network-config/settings.txt");    
	chmod 0600,"$etc_dir/network-config/settings.txt";
	close(FILE);
    }
    
    open(FILE,"+> $etc_dir/network-config/settings.txt");    
    
    print FILE "---begin user config---\n\n";
    
    #we save the current state
    foreach my $one_setting (@all_settings)
    {
	print FILE "name=$one_setting->{name}\n";
	print FILE "description=<<<$one_setting->{description}>>>\n";
	print FILE "icon=$one_setting->{icon}\n";
	print FILE "default_net=$one_setting->{default_net}\n";
        if ($one_setting->{dns_auto} eq "TRUE")
        {
            print FILE "dns_auto=TRUE\n";
        }
        else
        {
            print FILE "dns_auto=FALSE\n";
        }
	print FILE "dns1=$one_setting->{dns1}\n";
	print FILE "dns2=$one_setting->{dns2}\n";
	print FILE "dns3=$one_setting->{dns3}\n";
	
	my @all_devices = keys %{$one_setting->{devices}};
	#we save the devices
	foreach my $dev (@all_devices)
	{
	    my $device = $one_setting->{devices}->{$dev};
	    
	    print FILE "\ndevice=$device->{name}\n";
            
	    #activate or not
	    if ($device->{active} eq "TRUE")
	    {
		print FILE "active=TRUE\n";
	    }
	    else
	    {
		print FILE "active=FALSE\n";
	    }
            
	    #nat or not
	    if ($device->{nat} eq "TRUE")
	    {
		print FILE "nat=TRUE\n";
	    }
	    else
	    {
		print FILE "nat=FALSE\n";
	    }
            
            #wifi settings
	    if (is_wifi($device->{name}))
	    {
		print FILE "wifi=TRUE\n";
	    }
	    else
	    {
		print FILE "wifi=FALSE\n";
	    }
	    print FILE "w_ssid=$device->{w_ssid}\n";
	    print FILE "w_rate=$device->{w_rate}\n";
	    print FILE "w_wep=$device->{w_wep}\n";
	    print FILE "w_wpa=$device->{w_wpa}\n";
            
	    #dhcp or not
	    if ($device->{dhcp} eq "TRUE")
	    {
		print FILE "dhcp=TRUE\n";
	    }
	    else
	    {
		print FILE "dhcp=FALSE\n";
	    }
	    print FILE "ip=$device->{ip}\n";
	    print FILE "netmask=$device->{netmask}\n";
	    print FILE "gateway=$device->{gateway}\n";
            print FILE "-------------------\n";
	}
	
	print FILE "______________\n\n";
    }
    print FILE "---end user config---\n\n";
    
    #we save internal config
    print FILE "---begin internal config---\n\n";
    #we save here internal config
    if ($test_for_internet)
    {
	print FILE "test_for_internet=TRUE\n";
    }
    else
    {
	print FILE "test_for_internet=FALSE\n";
    }
    #we write web site
    print FILE "internet_site_for_ping=$internet_site_for_ping\n";
    #we print the wpa configuration file
    print FILE "wpa_configuration_file=$wpa_configuration_file\n";
    #we print the wpa driver
    print FILE "wpa_driver=$wpa_driver\n";
    #we print the dhcp client
    print FILE "dhcp_client=$dhcp_client\n";
    print FILE "\n---end internal config---\n\n";
    #we close the settings file
    close(FILE);
}

#prints a configuration
sub print_configuration
{
    my ($counter) = @_;
    
    #we print the current configuration
    my $current_config = $all_settings[$counter];
    print "name\t\t$current_config->{name}\n";
    print "description\t$current_config->{description}\n";
    print "icon\t\t$current_config->{icon}\n";
    #we print dns
    if ($current_config->{dns_auto} eq "TRUE")
    {
	print "dns_auto\tTRUE\n";
    }
    else
    {
	if ($current_config->{dns1})
	{
	    print "dns1\t\t$current_config->{dns1}\n";
	}
	if ($current_config->{dns2})
	{
	    print "dns2\t\t$current_config->{dns2}\n";
	}
	if ($current_config->{dns3})
	{
	    print "dns3\t\t$current_config->{dns3}\n";
	}
    }
    print "default_net\t$current_config->{default_net}\n";
    
    #we print all the devices
    print "\ndevices :\n";
    my @all_devices = keys %{$current_config->{devices}};
    #we save the devices
    foreach my $dev (@all_devices)
    {
	my $device = $current_config->{devices}->{$dev};
	print "\t$device->{name} {\n";
	#if the driver does not exists
	if (is_virtual($device->{name}))
	{
	    print "\t\tInexistent device\n";
	}
	#we print the driver
	my $driver_name = get_device_driver_name($device->{name});
	if ($driver_name)
	{
	    print "\t\tdriver\t$driver_name\n";
	}
	print "\t\tactive\t$device->{active}\n";
	#if active, we print more infos
	if ($device->{active} eq "TRUE")
	{
	    if ($device->{nat} eq "TRUE")
	    {
		print "\t\tnat=TRUE\n";
	    }
	    if ($device->{dhcp} eq "TRUE")
	    {
		print "\t\tdhcp\tTRUE\n";
	    }
	    else
	    {
		if ($device->{ip})
		{
		    print "\t\tip=$device->{ip}\n";
		}
		if ($device->{netmask})
		{
		    print "\t\tnetmask=$device->{netmask}\n";
		}
		if ($device->{gateway})
		{
		    print "\t\tgateway=$device->{gateway}\n";
		}
	    }
	    
	    #wifi settings
	    if ($device->{wifi} eq "TRUE")
	    {
		print "\t\tw_ssid\t$device->{w_ssid}\n";
		print "\t\tw_rate\t$device->{w_rate}\n";
		print "\t\tw_wep\t$device->{w_wep}\n";
		print "\t\tw_wpa\t$device->{w_wpa}\n";
	    }
	}
	print "\t}\n";
    }
}

#activate Ip,netmask,gateway
sub activate_ip_netmask_gateway
{
    my ($data) = @_;
    
    my $gateway = $data->[0];
    my $gateway_entry = $data->[1];
    my $netmask = $data->[2];
    my $netmask_entry = $data->[3];
    my $ip_address_gateway = $data->[4];
    my $ip_entry = $data->[5];
    
    $gateway->set_sensitive(TRUE);
    $gateway->set_sensitive(TRUE);
    $gateway_entry->set_sensitive(TRUE);
    $netmask->set_sensitive(TRUE);
    $netmask_entry->set_sensitive(TRUE);
    $ip_address_gateway->set_sensitive(TRUE);
    $ip_entry->set_sensitive(TRUE);
}

#deactivate Ip,netmask,gateway
sub deactivate_ip_netmask_gateway
{
    my ($data) = @_;
    
    my $gateway = $data->[0];
    my $gateway_entry = $data->[1];
    my $netmask = $data->[2];
    my $netmask_entry = $data->[3];
    my $ip_address_gateway = $data->[4];
    my $ip_entry = $data->[5];
    
    $gateway->set_sensitive(FALSE);
    $gateway->set_sensitive(FALSE);
    $gateway_entry->set_sensitive(FALSE);
    $netmask->set_sensitive(FALSE);
    $netmask_entry->set_sensitive(FALSE);
    $ip_address_gateway->set_sensitive(FALSE);
    $ip_entry->set_sensitive(FALSE);
}

#if it's a wifi card
sub is_wifi
{
    my ($ethernet_name) = @_;
    my $is_wifi = FALSE;
    
    #if the ethernet device is wifi
    foreach my $wifi_name (@wifi_cards)
    {
        chomp $wifi_name;
        if ($ethernet_name eq $wifi_name)
        {
            $is_wifi = TRUE;
            last;
        }
    }
    
    #if the card is not wifi, we check that in the settings we have
    #wifi
    if (!$is_wifi)
    {
	foreach my $setting (@all_settings)
	{
	    if (exists($setting->{devices}->{$ethernet_name}->{wifi}))
	    {
		if ($setting->{devices}->{$ethernet_name}->{wifi}
		    eq "TRUE")
		{
		    $is_wifi = TRUE;
		    last;
		}
	    }
	}
    }
    
    return $is_wifi;
}

#if it's a real ethernet card
sub is_ethernet
{
    my ($ethernet_name) = @_;
    my $is_ethernet = FALSE;
    
    #if the ethernet device is wifi
    foreach my $name (@ethernet_cards)
    {
        if ($ethernet_name eq $name)
        {
            $is_ethernet = TRUE;
            last;
        }
    }
    
    return $is_ethernet;
}

#if it's a virtual card that we only have in the settings
sub is_virtual
{
    my ($ethernet_name) = @_;
    my $is_virtual = FALSE;
    
    #if the ethernet device is wifi
    foreach my $name (@virtual_cards)
    {
        if ($ethernet_name eq $name)
        {
            $is_virtual = TRUE;
            last;
        }
    }
    
    return $is_virtual;
}

#nat auto server button
sub nat_auto_buttons_event
{
    my ($widget,$buttons) = @_;
    
    my ($config,$device) = get_selected_config_and_device();
    
    if (defined($config) && defined($device))
    {
        my ($ip,$netmask,$gateway);
        #if server button or client button
        if ($buttons->[0] eq "server")
        {
            $ip = "192.168.5.1";
            $netmask = "255.255.255.0";
            $gateway = "";
	    $all_settings[$config]->{devices}->{$device}->{nat} = "TRUE";
	    $buttons->[5]->set_active(TRUE);
        }
	#client
        else
        {
            $ip = "192.168.5.2";
            $netmask = "255.255.255.0";
            $gateway = "192.168.5.1";
	    $all_settings[$config]->{devices}->{$device}->{nat} = "FALSE";
	    $buttons->[5]->set_active(FALSE);
	    #we get the number that eq $device
	    my $number = 0;
	    foreach (@all_cards)
	    {
		if ($_ eq $device)
		{
		    last;
		}
		$number++;
	    }
	    #if the device is not virtual
	    #we set it as the default route
	    if (!is_virtual($device))
	    {
		$buttons->[6]->set_active($number);
		$all_settings[$config]->{devices}->{$device}->{default_net} =
		    $device;
	    }
        }
        
        #we put the nat settings
        $all_settings[$config]->{devices}->{$device}->{dhcp} = "FALSE";
        $all_settings[$config]->{devices}->{$device}->{ip} = $ip;
        $all_settings[$config]->{devices}->{$device}->{netmask} = $netmask;
        $all_settings[$config]->{devices}->{$device}->{gateway} = $gateway;
        
        #activate buttons and set entries
        $buttons->[1]->set_active(TRUE);
        $buttons->[2]->set_text($ip);
        $buttons->[3]->set_text($netmask);
        $buttons->[4]->set_text($gateway);
        
	save_settings();
    }
}

#refresh the scanned wifi list
sub refresh_scan_list
{
    my ($buttons) = @_;
    
    Gtk2::Gdk::Threads->enter;
    $scan_top_label->set_markup("<b>Please wait</b>, scanning for wifi networks...");
    $buttons->[0]->set_sensitive(FALSE);
    $buttons->[1]->set_sensitive(FALSE);
    $buttons->[2]->set_sensitive(FALSE);
    Gtk2::Gdk::Threads->leave;
    
    #if we have found wifi networks or notx
    my $have_data = FALSE;
    
    my $wifi_networks = `iwlist $buttons->[3] scanning`;
    my @wifi_networks_lines = split("\n",$wifi_networks);
    #we put here all the networks
    my @networks = ();
    my $net_name = undef;
    my $encryption_key = undef;
    my $signal = undef; my $noise = undef; my $quality = undef;
    foreach (@wifi_networks_lines)
    {
	#we get the network name
	if (/.*ESSID:\"(.*)\"/)
	{
	    $net_name = $1;
	}
	#we get if we have encryption or not
	if (/.*Encryption key:(.*)/)
	{
	    if ($1 eq "on")
	    {
		$encryption_key = "TRUE";
	    }
	    else
	    {
		$encryption_key = "FALSE";
	    }
	}
	#we get the signal statistics
	if (/.*Quality:(.*) Signal level:(.*) Noise level:(.*)/)
	{
	    $quality = $1;
	    $signal = $2;
	    $noise = $3;
	}
	#we write the detected network if we have all we need
	if (/.*Cell.*Address:.*/)
	{
	    if (defined($net_name)&&
		defined($encryption_key))
	    {
		my $network =
		{
		    name => $net_name,
		    encryption => $encryption_key,
		    quality => $quality,
		    signal => $signal,
		    noise => $noise,
		};
		
		push @networks,$network;	    
		
		$net_name = undef;$encryption_key = undef;
		$quality=undef;$signal=undef;$noise=undef;
	    }
	}
    }
    #we write the detected network at the end
    my $network =
    {
	name => $net_name,
	encryption => $encryption_key,
	quality => $quality,
	signal => $signal,
	noise => $noise,
    };    
    push @networks,$network;	    
    
    Gtk2::Gdk::Threads->enter;
    #for all the networks, we put the data
    #we empty the scan list
    $scan_list->get_selection->unselect_all;
    @{$scan_list->{data}} = ();
    foreach (@networks)
    {
	my $pixbuf = undef;
	if ($_->{encryption} eq "TRUE")
	{
	    $pixbuf = $main_window->render_icon('gtk-execute','menu');
	}
	push @{$scan_list->{data}},
	[$_->{name},$pixbuf,$_->{quality},$_->{signal},$_->{noise}];
	$have_data=TRUE;
    }
    
    if ($have_data)
    {
	$scan_top_label->set_markup("Available networks :");
    }
    else
    {
	$scan_top_label->set_markup("No networks found");
    }
    $buttons->[0]->set_sensitive(TRUE);
    $buttons->[2]->set_sensitive(TRUE);
    Gtk2::Gdk::Threads->leave;
}

#event for the scan for wifi button
sub scan_wifi_clicked_event
{ 
    my ($widget, $essid_entry) = @_;
    
    if (!$scan_dialog)
    {
	$scan_dialog = Gtk2::Dialog->new ("Available wifi networks",
					  $main_window,
					  [qw/modal
					   destroy-with-parent/]);
	$scan_dialog->set_resizable(FALSE);
	
	#we can't close it normally
	$scan_dialog->signal_connect("delete-event" =>
				     sub {
					 return TRUE;
				     });
	
	#main dialog vbox
	my $scan_vbox = Gtk2::VBox->new(FALSE,0);
	
	#top label
	$scan_top_label = Gtk2::Label->new;
	$scan_top_label->set_markup("<b>Please wait</b>, scanning for wifi networks...");
	$scan_top_label->set_alignment(0,0.5);
	my $scan_label_hbox =
	    Gtk2::HBox->new(FALSE,0);
	$scan_label_hbox->pack_start($scan_top_label,FALSE,FALSE,10);
	$scan_vbox->pack_start($scan_label_hbox,FALSE,FALSE,0);
	
	#main scan list
	my $scan_hbox_list = Gtk2::HBox->new(FALSE,0);
	$scan_list =
	    Gtk2::SimpleList->new('Network name' => 'text',
				  'Secured' => 'pixbuf',
				  'Quality' => 'text',
				  'Signal' => 'text',
				  'Noise' => 'text');
	
	#we get the first column
	my $network_column = $scan_list->get_column(0);
	$network_column->set_expand(TRUE);
	my $quality_column = $scan_list->get_column(1);
	$quality_column->set_expand(FALSE);
	my $signal_column = $scan_list->get_column(2);
	$signal_column->set_expand(FALSE);
	my $noise_column = $scan_list->get_column(3);
	$noise_column->set_expand(FALSE);
	#list settings
	$scan_list->set_rules_hint(TRUE);
	$scan_list->set_enable_search(FALSE);
	$scan_list->set_headers_visible(TRUE);

	#we pack the scan list
	$scan_hbox_list->pack_start($scan_list,TRUE,TRUE,10);
	$scan_vbox->pack_start($scan_hbox_list,FALSE,FALSE,10);
	
	#refresh scan button
	my $scan_refresh_button;
	$scan_refresh_button = 
	    $scan_dialog->add_button("gtk-refresh","apply");
	$scan_refresh_button->set_sensitive(FALSE);
	
	#select scan button
	my $scan_select_button;
	$scan_select_button =
	    $scan_dialog->add_button("gtk-ok","ok");
	$scan_select_button->set_sensitive(FALSE);
	$scan_select_button->signal_connect(clicked => sub {
	    my ($widget, $essid_entry) = @_;
	    #select the network
	    my $network_name = get_selected_scanned_wifi();
	    #we put the network name to the entry and to the settings
	    $essid_entry->set_text($network_name);
	    my ($config,$device) = get_selected_config_and_device();
	    if (defined($config) && defined($device))
	    {
		$all_settings[$config]->{w_ssid} = $network_name;
		save_settings();
	    }
	    
	    $scan_dialog->destroy;
	    $scan_dialog=undef;
	},$essid_entry);
	
	my ($config,$device) =
	    get_selected_config_and_device();
	
	#scan close button
	my $scan_close_button;	
	$scan_close_button = 
	    $scan_dialog->add_button("gtk-close","close");
	$scan_close_button->set_sensitive(FALSE);
	$scan_close_button->signal_connect(clicked => sub {
	    $scan_dialog->destroy;
	    $scan_dialog=undef;
	});
	
	#we keep all buttons to pass as argument
	my $all_buttons =
	    [$scan_refresh_button,
	     $scan_select_button,$scan_close_button,
	     $device];
	#signal for the refresh button
	$scan_refresh_button->signal_connect(clicked => sub {
	    my ($widget,$args) = @_;
	    my $thread = threads->new(\&refresh_scan_list,
				      $args);
	    #refresh_scan_list($args);
	},$all_buttons);
	#if we select a row, enable ok button
	$scan_list->signal_connect("button_press_event"=>
				   sub {
				       my ($widget,$event,$args) = @_;
				       
				       if ($args->[0]->is_sensitive)
				       {
					   $args->[1]->set_sensitive(TRUE);
				       }
				   }, $all_buttons);

	#we put the main vbox to the dialog
	$scan_dialog->vbox->pack_start($scan_vbox,TRUE,TRUE,10);
	
	$scan_dialog->set_default_response("close");
	$scan_dialog->show_all;
	$scan_dialog->queue_draw;
	
	my $thread = threads->new(\&refresh_scan_list,
				  $all_buttons);
	#refresh_scan_list($all_buttons);
    }
}

#gets the name of the driver for this device
sub get_device_driver_name
{
    my ($ethernet_name) = @_;
    
    my $driver_name = undef;
    my $link_driver = "/sys/class/net/$ethernet_name/device/driver";
    #if the link exists
    if (-l $link_driver)
    {
	my $eth_driver = readlink $link_driver;
	$eth_driver =~ s|^.*/([^/]*)$|$1|;
	$driver_name =
	    `modinfo -F description $eth_driver 2>/dev/null`;
	#if we get a name
	if ($driver_name)
	{
	    chomp $driver_name;
	    #maximum 25 chars
	    if (length($driver_name) > 40)
	    {
		$driver_name = substr($driver_name,0,37);
		$driver_name .= "...";
	    }
	}
    }
    
    return $driver_name;
}

#puts a new config page according to the first argument
sub put_new_config_page
{
    #if we put a new config page, dont update description
    my $global_init = TRUE;
    
    my ($current_setting) = @_;
    
    #labels and entry boxes for static ip
    my $netmask;
    my $netmask_entry;
    my $gateway;
    my $gateway_entry;
    my $ip_address_gateway;
    my $ip_entry;
    
    #prepare the entire vbox
    my $right_vbox;
    $right_vbox = Gtk2::VBox->new(FALSE, 0);
    
    #description main vbox
    my $description_frame = Gtk2::Frame->new("Description");
    my $appearance_vbox = Gtk2::VBox->new(FALSE,0);
    $appearance_vbox->set_border_width(7);
    my $text_buffer = Gtk2::TextBuffer->new;
    my $text_view = Gtk2::TextView->new_with_buffer($text_buffer);
    #if change the description text
    $text_buffer->signal_connect("changed",
                                 sub {
				     my ($text_buffer) = @_;
				     
				     if (!$global_init)
				     {
					 my $real_text = 
					     $text_buffer->get_text($text_buffer->get_start_iter,
								    $text_buffer->get_end_iter,TRUE);
					 my ($config,$device) = get_selected_config_and_device();
					 if (defined($config) && defined($device))
					 {
					     $all_settings[$config]->{description} = $real_text;
					     
					     refresh_select_menu();
					     save_settings();
					 }
				     };
				 });
    $text_view->set_wrap_mode('word');
    #scrolled window for the description entry
    my $scrolled_window = Gtk2::ScrolledWindow->new;
    $scrolled_window->add($text_view);
    $scrolled_window->set_size_request (-1, 50);
    $scrolled_window->set_policy ('automatic', 'automatic');
    $scrolled_window->set_border_width(5);
    $description_frame->add($scrolled_window);
    $appearance_vbox->pack_start($description_frame,FALSE,FALSE,0);
    
    #configuration icon
    my $icon_frame = Gtk2::Frame->new("Icon");
    my $icon_hbox = Gtk2::HBox->new;
    my $icon_vbox = Gtk2::VBox->new;
    $icon_vbox->set_border_width(5);
    $icon_vbox->pack_start($icon_hbox,FALSE,FALSE,0);
    #icon
    my $current_icon;
    #the current icon
    if (-e $current_setting->{icon})
    {
	$current_icon = Gtk2::Image->new_from_file($current_setting->{icon});
    }
    else
    {
	my $program_dir = dirname(realpath($0));
	$current_icon = Gtk2::Image->new_from_file("/usr/share/network-config/default-icon.png");
    }
    $icon_hbox->pack_start($current_icon,TRUE,FALSE,10);
    #change icon button
    my $change_icon_button = 
	get_custom_button("_Change icon","gtk-open","Change the icon");
    my $fake_vbox = Gtk2::VBox->new;
    
    $fake_vbox->pack_start($change_icon_button,TRUE,FALSE,5);
    $icon_hbox->pack_start($fake_vbox,TRUE,FALSE,5);
    $change_icon_button->signal_connect("clicked",
                                        \&change_icon_button_event,
                                        $current_icon);
    $icon_frame->add($icon_vbox);
    $appearance_vbox->pack_start($icon_frame,FALSE,FALSE,9);
    
    #appearance_config notebook
    my $appearance_config_notebook = Gtk2::Notebook->new;
    $appearance_config_notebook->set_show_border(FALSE);
    #it's the "General" tab
    my $general_vbox = Gtk2::VBox->new(FALSE, 0);
    
    #############################
    #default route hbox
    my $default_route_hbox = Gtk2::HBox->new;
    #default route combobox
    my $default_route_combo_box;
    $default_route_combo_box = Gtk2::ComboBox->new_text;
    my $default_route_label = Gtk2::Label->new("Default gateway device :");
    #add all networks to the combobox
    foreach (@all_cards)
    {
        chomp;
        $default_route_combo_box->append_text($_);
    }
    #by default, select the first ethernet card
    $default_route_combo_box->set_active(0);
    $default_route_combo_box->signal_connect("changed",
                                             \&default_route_combo_box_event);
    $default_route_hbox->pack_start($default_route_label,FALSE,FALSE,0);
    $default_route_hbox->pack_start($default_route_combo_box,FALSE,FALSE,0);
    $general_vbox->pack_start($default_route_hbox,FALSE,FALSE,5);
    
    #dns_selector
    my $dns_vbox = Gtk2::VBox->new;
    my $dns_selector =
        Gtk2::RadioButton->new(undef, 'Auto DNS (DHCP)');
    $dns_selector->set_name("auto");
    my $dns_selector2 =
        Gtk2::RadioButton->new_from_widget($dns_selector,'Custom DNS servers');
    $general_vbox->pack_start($dns_selector,FALSE,FALSE,0);
    $general_vbox->pack_start($dns_selector2,FALSE,FALSE,0);
    
    #############################
    #dns entries
    my $dns_hbox = Gtk2::HBox->new;
    my $dnsvbox = Gtk2::VBox->new;
    my $fake_horiz = Gtk2::HBox->new;
    #dns entries
    my $dns1_entry;
    my $dns2_entry;
    my $dns3_entry;
    $dns1_entry = Gtk2::Entry->new_with_max_length(15);
    $dns2_entry = Gtk2::Entry->new_with_max_length(15);
    $dns3_entry = Gtk2::Entry->new_with_max_length(15);
    $dns1_entry->set_width_chars(13);
    $dns2_entry->set_width_chars(13);
    $dns3_entry->set_width_chars(13);
    $dns1_entry->signal_connect("changed" =>
				\&dns1_event);
    $dns2_entry->signal_connect("changed" =>
                                \&dns2_event);
    $dns3_entry->signal_connect("changed" =>
                                \&dns3_event);
    $fake_horiz->pack_start($dns1_entry,FALSE,FALSE,0);
    $dnsvbox->pack_start($fake_horiz,FALSE,FALSE,0);
    $fake_horiz = Gtk2::HBox->new;
    $fake_horiz->pack_start($dns2_entry,FALSE,FALSE,0);
    $dnsvbox->pack_start($fake_horiz,FALSE,FALSE,0);
    $fake_horiz = Gtk2::HBox->new;
    $fake_horiz->pack_start($dns3_entry,FALSE,FALSE,0);
    $dnsvbox->pack_start($fake_horiz,FALSE,FALSE,0);
    $dns_hbox->pack_start($dnsvbox,FALSE,FALSE,20);
    
    #signal for the dns selector
    my $dns_selector_data = [$dns1_entry,$dns2_entry,$dns3_entry];
    $dns_selector->signal_connect("clicked" => 
                                  \&dns_selector_event,
                                  $dns_selector_data);
    
    #we add dns to 
    $general_vbox->pack_start($dns_hbox,FALSE,FALSE,10);
    
    #############################
    #the notebook
    my $notebook;
    $notebook = Gtk2::Notebook->new;
    $notebook->set_tab_pos("left");
    push @all_eth_notebooks,$notebook;
    #ugly hacks to look pretty
    my $general_hbox = Gtk2::HBox->new;
    $general_hbox->pack_start($general_vbox,FALSE,FALSE,10);
    my $general_fake_vbox = Gtk2::VBox->new(FALSE,0);
    $general_fake_vbox->pack_start($general_hbox,FALSE,FALSE,5);
    #we put the general_vbox inside the tab
    $notebook->append_page($general_fake_vbox,"General");
    $notebook->set_show_border(FALSE);
    
    ##########################
    #top data
    $dns1_entry->set_text($current_setting->{dns1});
    $dns2_entry->set_text($current_setting->{dns2});
    $dns3_entry->set_text($current_setting->{dns3});
    
    if ($current_setting->{description})
    {
        $text_buffer->set_text($current_setting->{description});
    }
    
    #we select the default net
    my $index = 0;
    foreach (@all_cards)
    {
        if ($_ eq $current_setting->{default_net})
        {
            last;
        }
        $index++;
    }
    $default_route_combo_box->set_active($index);
    
    ##############################
    #we put all the ethernet cards (even inexistant ones
    foreach my $ethernet_name (@all_cards)
    {
        chomp $ethernet_name;
	
        #if the card is wifi or not
        my $is_wifi = FALSE;
        $is_wifi = is_wifi($ethernet_name);
	#if the device is virtual
	my $is_virtual = is_virtual($ethernet_name);
	
        my $tab_content = Gtk2::VBox->new;
        my $tab_hbox_content = Gtk2::HBox->new;
        my $tab_vbox_content = Gtk2::VBox->new;
        
        my $tab_fake_vbox_content = Gtk2::VBox->new;
	#if the card is not virtual
	#we try to take its name
	if (!$is_virtual)
	{
	    my $driver_name = get_device_driver_name($ethernet_name);
	    if ($driver_name)
	    {
		my $eth_label_name = Gtk2::Label->new($driver_name);
		$eth_label_name->set_alignment(0,0.5);
		$tab_fake_vbox_content->pack_start($eth_label_name,FALSE,FALSE,2);
	    }
	}
        #activate button
        my $activate_check_button;
        #activate button
        $activate_check_button = Gtk2::CheckButton->new("Active");
        $tab_fake_vbox_content->pack_start($activate_check_button,FALSE,FALSE,2);
        
        my $wifi_ESSID;
        my $wifi_rate;        
        my $wifi_key;
	my $wifi_wpa_pass_key;
	my $wifi_notebook = Gtk2::Notebook->new;
	my $wifi_notebook_vbox = Gtk2::VBox->new;
	my $wifi_notebook_hbox = Gtk2::HBox->new;
        #if the card is wifi
        if ($is_wifi)
        {
	    $wifi_notebook_vbox->set_border_width(3);
	    
	    #we put the scan networks button
            my $horiz_fake = Gtk2::HBox->new(FALSE,0);
	    my $scan_wifi_button =
		get_custom_button("Scan wifi networks","gtk-network",
				  "Scan for wifi networks...");
            $horiz_fake->pack_start($scan_wifi_button,FALSE,FALSE,5);
	    $wifi_notebook_vbox->pack_start($horiz_fake,FALSE,FALSE,6);
	    
            #ESSID
	    $horiz_fake = Gtk2::HBox->new(FALSE,0);
            my $wifi_ESSID_label = Gtk2::Label->new("ESSID (name) :");;
	    $wifi_ESSID_label->set_alignment(0,0.5);
            $wifi_ESSID = Gtk2::Entry->new;
	    #scan wifi button event needs the wifi_ESSID
	    $scan_wifi_button->signal_connect("clicked" =>
					      \&scan_wifi_clicked_event,
					      $wifi_ESSID);
	    $wifi_ESSID->signal_connect("changed" =>
					\&wifi_ESSID_entry_event);
            $wifi_ESSID->set_width_chars(14);
            $horiz_fake->pack_start($wifi_ESSID_label,TRUE,TRUE,5);
            $horiz_fake->pack_start($wifi_ESSID,FALSE,FALSE,5);
	    $wifi_notebook_vbox->pack_start($horiz_fake,FALSE,FALSE,0);
	    
            #wifi rate
            $horiz_fake = Gtk2::HBox->new(FALSE,0);
            my $wifi_rate_label = Gtk2::Label->new("Wifi rate :");
	    $wifi_rate_label->set_alignment(0,0.5);
            $wifi_rate = Gtk2::Entry->new;
            $wifi_rate->set_width_chars(14);
            $wifi_rate->signal_connect("changed" =>
                                       \&wifi_rate_entry_event);
            $horiz_fake->pack_start($wifi_rate_label,TRUE,TRUE,5);
            $horiz_fake->pack_start($wifi_rate,FALSE,FALSE,5);
	    $wifi_notebook_vbox->pack_start($horiz_fake,FALSE,FALSE,0);
	    
            #WEP key
            $horiz_fake = Gtk2::HBox->new(FALSE,0);
            my $wifi_key_label = Gtk2::Label->new("WEP key :");
	    $wifi_key_label->set_alignment(0,0.5);
            $wifi_key = Gtk2::Entry->new;
            $wifi_key->set_width_chars(14);
            $wifi_key->signal_connect("changed" =>
                                      \&wifi_key_entry_event);
            $horiz_fake->pack_start($wifi_key_label,TRUE,TRUE,5);
            $horiz_fake->pack_start($wifi_key,FALSE,FALSE,5);
            $wifi_key->set_visibility(FALSE);
	    $wifi_notebook_vbox->pack_start($horiz_fake,FALSE,FALSE,0);
	    
            #WPA-PSK key
            $horiz_fake = Gtk2::HBox->new(FALSE,0);
            my $wifi_wpa_pass_label = Gtk2::Label->new("WPA-PSK key :");
	    $wifi_wpa_pass_label->set_alignment(0,0.5);
            $wifi_wpa_pass_key = Gtk2::Entry->new;
            $wifi_wpa_pass_key->set_width_chars(14);
            $wifi_wpa_pass_key->signal_connect("changed" =>
					       \&wifi_wpa_pass_key_entry_event);
            $horiz_fake->pack_start($wifi_wpa_pass_label,TRUE,TRUE,5);
            $horiz_fake->pack_start($wifi_wpa_pass_key,FALSE,FALSE,5);
            $wifi_wpa_pass_key->set_visibility(FALSE);
	    $wifi_notebook_vbox->pack_start($horiz_fake,FALSE,FALSE,0);
	    
	    $tab_content->pack_start($wifi_notebook,FALSE,FALSE,0);
        }
	
	#settings tab if wifi
	my $settings_vbox = Gtk2::VBox->new;
        #dhcp_selector
        my $dhcp_selector =
            Gtk2::RadioButton->new(undef, 'Auto (DHCP)');
        $dhcp_selector->set_name("auto");
        my $dhcp_selector2 =
            Gtk2::RadioButton->new_from_widget($dhcp_selector,'Static IP');
        $dhcp_selector2->set_name("static");
        $settings_vbox->pack_start($dhcp_selector,FALSE,FALSE,0);
        $settings_vbox->pack_start($dhcp_selector2,FALSE,FALSE,0);
        my $horiz_fake = Gtk2::HBox->new(FALSE,0);
        #ip address
        $ip_address_gateway = Gtk2::Label->new("Ip address :");
        $ip_entry = Gtk2::Entry->new_with_max_length(15);
        $ip_entry->signal_connect("changed" =>
                                  \&ip_entry_event);
        $ip_entry->set_width_chars(13);
        $horiz_fake->pack_start($ip_address_gateway,TRUE,FALSE,20);
        $horiz_fake->pack_start($ip_entry,FALSE,FALSE,5);
        $settings_vbox->pack_start($horiz_fake,FALSE,FALSE,0);
        #netmask
        $horiz_fake = Gtk2::HBox->new;
        $netmask = Gtk2::Label->new("Netmask :");
        $netmask_entry = Gtk2::Entry->new_with_max_length(15);
        $netmask_entry->signal_connect("changed" => 
                                       \&netmask_entry_event);
        $netmask_entry->set_width_chars(13);
        $horiz_fake->pack_start($netmask,TRUE,FALSE,20);
        $horiz_fake->pack_start($netmask_entry,FALSE,FALSE,5);
        $settings_vbox->pack_start($horiz_fake,FALSE,FALSE,0);
        #gateway
        $horiz_fake = Gtk2::HBox->new;
        $gateway = Gtk2::Label->new("Gateway :");
        $gateway_entry = Gtk2::Entry->new_with_max_length(15);
        $gateway_entry->signal_connect("changed" => 
                                       \&gateway_entry_event);
        $gateway_entry->set_width_chars(13);
        $horiz_fake->pack_start($gateway,TRUE,FALSE,20);
        $horiz_fake->pack_start($gateway_entry,FALSE,FALSE,5);
        $settings_vbox->pack_start($horiz_fake,FALSE,FALSE,0);
        
        #we build a ref with the 6 entries : gateway, gateway_entry,
        #netmask, netmask_entry, ip_address_gateway, ip_entry
        my $dhcp_selector_data;
        $dhcp_selector_data = 
            [$gateway, $gateway_entry,$netmask,$netmask_entry,
             $ip_address_gateway,$ip_entry];
        
        #dhcp selector event
        $dhcp_selector->signal_connect("clicked" => 
                                       \&dhcp_selector_event,
                                       $dhcp_selector_data);
        
        #nat check and nat buttons
        my $nat_check_button =
            Gtk2::CheckButton->new("NAT (for internet sharing)");
        $settings_vbox->pack_start($nat_check_button,FALSE,FALSE,0);
        #nat buttons
        my $nat_check_hbox = Gtk2::HBox->new;
        my $nat_put_server_button =
            get_custom_button("NAT _server","gtk-network","Shares internet");
        my $nat_put_client_button =
            get_custom_button("NAT _client","gtk-network","To receive the shared internet");
        #server nat data buttons
        my $nat_buttons_data_server = 
            ["server",$dhcp_selector2,
             $ip_entry,$netmask_entry,$gateway_entry,
	     $nat_check_button];
        $nat_put_server_button->signal_connect("clicked" =>
                                               \&nat_auto_buttons_event,
                                               $nat_buttons_data_server);
        #client nat data buttons
        my $nat_buttons_data_client =
            ["client",$dhcp_selector2,
             $ip_entry,$netmask_entry,$gateway_entry,
	     $nat_check_button,$default_route_combo_box];
        $nat_put_client_button->signal_connect("clicked" =>
                                               \&nat_auto_buttons_event,
                                               $nat_buttons_data_client);
        #nat check button + dns label
        my $nat_dns_label = Gtk2::Label->new("To share internet, copy "
                                             ."DNS\nfrom the server"
					     ." to the client");
        my $check_data = [$nat_dns_label];
        $nat_check_button->signal_connect("clicked" =>
                                          \&activate_network_forwarding_event,
                                          $check_data);
        #nat dns label
        my $nat_dns_hbox = Gtk2::HBox->new;
        $nat_dns_label->set_line_wrap(TRUE);
        $nat_dns_hbox->pack_start($nat_dns_label,FALSE,FALSE,0);
        $settings_vbox->pack_start($nat_dns_hbox,FALSE,FALSE,0);
        
        #we put the server and client buttons
        $nat_check_hbox->pack_start($nat_put_server_button,FALSE,FALSE,0);
        $nat_check_hbox->pack_start($nat_put_client_button,FALSE,FALSE,0);
        $settings_vbox->pack_start($nat_check_hbox,FALSE,FALSE,0);
        
	#if wifi, we put the settings_vbox in the Settings tab
	#else we let them in the main window
	if ($is_wifi)
	{
	    $settings_vbox->set_border_width(8);
	    $wifi_notebook->append_page($settings_vbox,"Settings");
	    #fake vbox to leave spaces on top and bottom
	    $wifi_notebook_hbox->pack_start($wifi_notebook_vbox,FALSE,FALSE,3);
	    $wifi_notebook->append_page($wifi_notebook_hbox,"Wifi settings");
	    $wifi_notebook->set_show_border(FALSE);
	}
	else
	{
	    $tab_content->pack_start($settings_vbox,FALSE,FALSE,0);
	}
	
        ###################
        #devices data
        my $current_device_data = $current_setting->{devices}->{$ethernet_name};
	
        #we put all the devices settings
        if ($is_wifi)
        {
            $wifi_ESSID->set_text($current_device_data->{w_ssid});
            $wifi_rate->set_text($current_device_data->{w_rate});
            $wifi_key->set_text($current_device_data->{w_wep});
            $wifi_wpa_pass_key->set_text($current_device_data->{w_wpa});
        }
        
        $ip_entry->set_text($current_device_data->{ip});
        $netmask_entry->set_text($current_device_data->{netmask});
        $gateway_entry->set_text($current_device_data->{gateway});
        
        #if we have dhcp
        if ($current_device_data->{dhcp} eq "TRUE")
            {
                deactivate_ip_netmask_gateway($dhcp_selector_data);
            }
        else
        {
            #we select static ip;
            $dhcp_selector2->set_active(TRUE);
        }
        
        #if we have auto dns, deactivate dns entries
        if ($current_setting->{dns_auto} eq "TRUE")
            {
                $dns1_entry->set_sensitive(FALSE);
                $dns2_entry->set_sensitive(FALSE);
                $dns3_entry->set_sensitive(FALSE);
            }
        else
        {
            #we select custom dns servers;
            $dns_selector2->set_active(TRUE);
        }
        
        #if we have activate for the device
        if ($current_device_data->{active} eq "TRUE")
        {
            #we check the activate button
            $activate_check_button->set_active(TRUE);
            $tab_content->set_sensitive(TRUE);
        }
        else
        {
            $activate_check_button->set_active(FALSE);
            $tab_content->set_sensitive(FALSE);
        }
        
        #if we have nat for the device
        if ($current_device_data->{nat} eq "TRUE")
        {
            $nat_check_button->set_active(TRUE);
            $nat_dns_label->set_sensitive(TRUE);
        }
        else
        {
            $nat_check_button->set_active(FALSE);
            $nat_dns_label->set_sensitive(FALSE);
        }
        
        $activate_check_button->signal_connect("clicked" =>
                                               \&activate_event,$tab_content);
        $tab_fake_vbox_content->pack_start($tab_content,FALSE,FALSE,0);
        $tab_vbox_content->pack_start($tab_fake_vbox_content,FALSE,FALSE,5);
        $tab_hbox_content->pack_start($tab_vbox_content,FALSE,FALSE,5);
	#we build a icon with a label
	my $notebook_top_hbox = Gtk2::HBox->new(FALSE,0);
	my $notebook_image;
	if ($is_wifi)
	{
	    $notebook_image =
		Gtk2::Image->new_from_stock("gtk-disconnect","small-toolbar");
	}
	else
	{
	    $notebook_image =
		Gtk2::Image->new_from_stock("gtk-connect","small-toolbar");
	}
        #page label
        my $notebook_label = Gtk2::Label->new(" ".$ethernet_name." ");
	
	#if the device is virtual or not
	if ($is_virtual)
	{
	    $notebook_label->set_sensitive(FALSE);
	    $notebook_image->set_sensitive(FALSE);
	}
	
	$notebook_image->show;$notebook_label->show;
        $notebook_top_hbox->pack_start($notebook_image,FALSE,FALSE,0);
        $notebook_top_hbox->pack_start($notebook_label,FALSE,FALSE,0);
        $notebook->append_page($tab_hbox_content,$notebook_top_hbox);
    }
    #add the notebook to the vbox
    $appearance_config_notebook->append_page($appearance_vbox,"Appearance");
    $appearance_config_notebook->append_page($notebook,"Config");
    
    #we put the top config name label
    my $top_config_name_label = Gtk2::Label->new(undef);
    my $new_name = $current_setting->{name};
    if (length($new_name) > 25)
    {
	$new_name = substr($new_name,0,25);
	$new_name .= "...";
    }
    $top_config_name_label->set_markup("<big><b>$new_name</b></big>");
    $top_config_name_label->set_alignment(0.5,0.5);
    my $top_config_vbox = Gtk2::VBox->new(FALSE,0);
    $top_config_vbox->pack_start($top_config_name_label,FALSE,FALSE,3);
    push @top_config_names,$top_config_name_label;
    
    #top frame
    my $top_frame = Gtk2::Frame->new;
    $top_frame->add($top_config_vbox);
    $top_frame->set_shadow_type("etched-in");
    $right_vbox->pack_start($top_frame,FALSE,FALSE,0);
    $right_vbox->pack_start($appearance_config_notebook,FALSE,FALSE,0);
    
    $right_vbox->show_all;
    $hidden_notebook->append_page($right_vbox,$current_setting->{name});
    $global_init = FALSE;
}

#draw the right part
sub draw_tabs
{
    $hidden_notebook = Gtk2::Notebook->new;
    $hidden_notebook->set_show_tabs(FALSE);
    $hidden_notebook->set_show_border(FALSE);
    
    foreach my $current_setting (@all_settings)
    {
        put_new_config_page($current_setting);
    }
    
    $hidden_notebook->show;
    $main_hbox->pack_start($hidden_notebook,TRUE,TRUE,5);
}

#puts the select tab configurations
sub load_select_tab_configurations
{
    $select_list = Gtk2::SimpleList->new('Icon' => 'pixbuf',
					 'Configuration' => 'text');
    
    $select_list->set_rules_hint(TRUE);
    $select_list->set_enable_search(FALSE);
    $select_list->set_headers_visible(FALSE);
    
    #select list row activated event
    #perl-gtk bug ?
    #$select_list->signal_connect("row-activated" => 
    #\&apply_button_event);
    
    #if selection has changed
    $select_list->get_selection->
        signal_connect("changed"=>
                       sub {
                           my $selected = 
                               get_select_selection_number();
                           my $new_text = $all_settings[$selected]->{description};
                           $description_label->set_text($new_text);
                       });
    
    #icon column
    my $icon_column = $select_list->get_column(0);
    $icon_column->set_alignment(0.5);
    my $text_column = $select_list->get_column(1);
    $text_column->set_max_width(200);
    $text_column->set_alignment(0.5);
    
    refresh_select_menu();
    
    #description label
    $description_label = Gtk2::TextBuffer->new;
    my $description_label_view =
        Gtk2::TextView->new_with_buffer($description_label);
    $description_label_view->set_wrap_mode('word');
    $description_label_view->set_editable(FALSE);
    #scrollable window for the description
    my $scrollable_window = Gtk2::ScrolledWindow->new;
    $scrollable_window->add($description_label_view);
    $scrollable_window->set_policy('automatic', 'automatic');
    $scrollable_window->set_size_request (70, 40);
    #hbox
    my $description_hbox = Gtk2::HBox->new;
    $description_hbox->pack_start($scrollable_window,TRUE,TRUE,0);
    
    $start_vbox->pack_start($select_list,TRUE,TRUE,5);
    $start_vbox->pack_start($description_hbox,FALSE,FALSE,0);
}

#properties button from the first page
sub change_config_button_event
{
    $main_notebook->append_page($main_vbox,"Configuration");
    $start_hbox->hide;
    #we get the selection
    my $selected_number = get_select_selection_number();
    #we go to the selected number
    $left_simple_list->select($selected_number);
    refresh_right_part($selected_number);
}

#properties button from the first page
sub change_select_button_event
{
    $start_hbox->show_all;
    $main_notebook->remove_page(1);
    #we get the selection
    my $selected_number = get_config_selection_number();
    $select_list->select($selected_number);
}

#check if internet
sub check_internet_event
{
    my ($widget) = @_;
    
    $test_for_internet = $widget->get_active;
    
    if ($test_for_internet)
    {
	$internet_site_hbox->set_sensitive(TRUE);
    }
    else
    {
	$internet_site_hbox->set_sensitive(FALSE);
    }
    
    save_settings();
}

#put the apply, preferences and quit buttons
sub load_apply_preferences_quit_buttons_select
{
    #apply button
    my $horiz_fake = Gtk2::HBox->new;
    my $apply_button = Gtk2::Button->new_from_stock("gtk-apply");
    my $b_tooltip = Gtk2::Tooltips->new;
    $b_tooltip->set_tip($apply_button,"Apply selected configuration");
    $apply_button->signal_connect("clicked" =>
				  \&apply_button_event);
    $horiz_fake->pack_start($apply_button,TRUE,FALSE,5);
    
    #properties button
    my $change_config_button;
    $change_config_button =
        Gtk2::Button->new_from_stock('gtk-edit');
    $b_tooltip = Gtk2::Tooltips->new;
    $b_tooltip->set_tip($change_config_button,"Edit selected configuration");
    $change_config_button->signal_connect("clicked",
                                          \&change_config_button_event);
    $horiz_fake->pack_start($change_config_button,TRUE,FALSE,5);
    #quit button
    my $quit_button = Gtk2::Button->new_from_stock("gtk-quit");
    $quit_button->signal_connect("clicked" => 
				 sub {Gtk2::main_quit});
    $b_tooltip = Gtk2::Tooltips->new;
    $b_tooltip->set_tip($quit_button,"Quit the program");
    $horiz_fake->pack_start($quit_button,TRUE,FALSE,5);
    #separator
    my $separator = Gtk2::HSeparator->new;
    $start_vbox->pack_start($separator,FALSE,FALSE,0);
    
    #we put the buttons
    $start_vbox->pack_start($horiz_fake,TRUE,TRUE,5);
}

#put the apply, preferences and quit buttons
sub load_apply_preferences_quit_buttons_config
{
    #apply button
    my $horiz_fake = Gtk2::HBox->new;
    my $apply_button =
	get_custom_button("_Test","gtk-yes","Test selected configuration");
    $apply_button->signal_connect("clicked" => 
				  \&apply_button_event);
    $horiz_fake->pack_start($apply_button,TRUE,FALSE,5);
    
    #properties button
    my $change_select_button;
    $change_select_button = 
        Gtk2::Button->new_from_stock('gtk-go-back');
    my $b_tooltip = Gtk2::Tooltips->new;
    $b_tooltip->set_tip($change_select_button,"Back to the main list");
    $change_select_button->signal_connect("clicked",
                                          \&change_select_button_event);
    $horiz_fake->pack_start($change_select_button,TRUE,FALSE,5);
    #quit button
    my $quit_button = Gtk2::Button->new_from_stock("gtk-quit");
    $b_tooltip = Gtk2::Tooltips->new;
    $b_tooltip->set_tip($quit_button,"Quit the program");
    $quit_button->signal_connect("clicked" => 
				 sub {Gtk2::main_quit});
    $horiz_fake->pack_start($quit_button,TRUE,FALSE,5);
    #separator
    my $separator = Gtk2::HSeparator->new;
    $main_vbox->pack_start($separator,FALSE,FALSE,0);
    $main_vbox->pack_start($horiz_fake,FALSE,FALSE,5);
    $main_vbox->show_all;
}

#refresh the right part
sub refresh_right_part
{
    my ($selected_number) = @_;
    
    $hidden_notebook->set_current_page($selected_number);
    $old_selected_number = $selected_number;
    $left_simple_list->grab_focus;
}

#left list row activate
sub left_simple_list_button_press_event
{
    my ($left_simple_list,$event) = @_;
    
    #if left button
    if ($event->button == 1)
    {
	#we get the selection
        my $selected_number = get_config_selection_number();
                    
        if ($selected_number != $old_selected_number)
        {
            refresh_right_part($selected_number);
        }	
	return TRUE;
    }
    else
    {
	#right button
	if ($event->button == 3)
	{
	    #popup menu
	    my $popup_menu = Gtk2::Menu->new;
	    my $accel = undef;
	    my $popup_menu_item_new =
		Gtk2::ImageMenuItem->new_from_stock("gtk-new",$accel);
	    my $b_tooltip = Gtk2::Tooltips->new;
	    $b_tooltip->set_tip($popup_menu_item_new,"New configuration");
	    $popup_menu->append($popup_menu_item_new);
	    $popup_menu_item_new->signal_connect("activate" =>
						 \&left_popup_menu_new_event);
	    $popup_menu_item_new->show;
	    
	    #if we have more than 1 config, show remove button
	    if ($#all_settings > 0)
	    {
		my $popup_menu_item_remove = 
		    Gtk2::ImageMenuItem->new_from_stock("gtk-delete",$accel);
		$b_tooltip = Gtk2::Tooltips->new;
		$b_tooltip->set_tip($popup_menu_item_remove,"Delete selected configuration");
		$popup_menu->append($popup_menu_item_remove);
		$popup_menu_item_remove->signal_connect("activate" =>
							\&left_popup_menu_remove_event);
		$popup_menu_item_remove->show;
	    }
	    $popup_menu->popup(undef,undef,undef,undef,$event->button,$event->time);
	}
    }
    
    return FALSE;
}

#load the settings from the file
sub load_settings
{
    @all_settings = ();
    
    #if we don't have the application directory
    if (!opendir(DIR,"$etc_dir/network-config"))
    {
	mkdir "$etc_dir/network-config";
	chmod 0700,"$etc_dir/network-config";
    }
    closedir(DIR);
    
    #we open the settings file
    if (! -e "$etc_dir/network-config/settings.txt")
    {
	open(FILE,"+< $etc_dir/network-config/settings.txt");
	chmod 0600,"$etc_dir/network-config/settings.txt";
	close(FILE);
    }
    
    #we read the settings from the file
    if (open(FILE,"+< $etc_dir/network-config/settings.txt"))
    {
	my $config_name = undef;
	my $default_net = undef;
	my $dns1 = undef;
	my $dns2 = undef;
	my $dns3 = undef;
	my $device_name = undef;
	my $active = undef;
	my $dhcp = undef;
	my $ip = undef;
	my $netmask = undef;
	my $gateway = undef;
	my $description = "";
	my $found_description = FALSE;
	my $icon = "";
        my $wifi = undef;
        my $w_ssid = "";
        my $w_rate = "";
        my $w_wep = "";
	my %devices = ();
	my $dns_auto;
        my $nat = undef;
	my $w_wpa = "";
        
	while (<FILE>)
	{
	    #internal settings
	    if (/test_for_internet=(.*)/)
	    {
		if ($1 eq "TRUE")
		{
		    $test_for_internet = TRUE;
		}
		else
		{
		    $test_for_internet = FALSE;
		}
	    }
	    if (/internet_site_for_ping=(.*)/)
	    {
		$internet_site_for_ping = $1;
	    }
	    if (/wpa_configuration_file=(.*)/)
	    {
		$wpa_configuration_file = $1;
	    }
	    if (/wpa_driver=(.*)/)
	    {
		$wpa_driver = $1;
	    }
	    if (/dhcp_client=(.*)/)
	    {
		$dhcp_client = $1;
	    }
	    
	    #user config
	    if (/name=(.*)/)
	    {
		$config_name = $1;
		$default_net = undef;
		$dns1 = undef;
		$dns2 = undef;
		$dns3 = undef;
		$device_name = undef;
		$active = undef;
		$dhcp = undef;
		$ip = undef;
		$netmask = undef;
		$gateway = undef;
		$description = "";
		$icon = "";
                $wifi = undef;
                $w_ssid = "";
                $w_rate = "";
                $w_wep = "";
                $w_wpa = "";
                $dns_auto = "";
                $nat=undef;
		next;
	    }
	    
	    if ($config_name)
	    {
		if ($found_description)
		{
		    if (/(.*)>>>/)
		    {
			$description .= $1;
			$found_description = FALSE;
		    }
		    else
		    {
			$description .= $_;
		    }
		    next;
		}
		if (/description=(.*)/)
		{
		    $description .= $1;
		    $description =~ s/<<<//;
		    if (!/>>>/)
		    {
			$found_description = TRUE;
		    }
		    else
		    {
			$description =~ s/>>>//;
		    }
		    next;
		}
		if (/icon=(.*)/)
		{
		    $icon = $1;
		    next;
		}
		if (/default_net=(.*)/)
		{
		    $default_net = $1;
		    next;
		}
		if (/dns_auto=(.*)/)
		{
		    $dns_auto = $1;
		    next;
		}
		if (/dns1=(.*)/)
		{
		    $dns1 = $1;
		    next;
		}
		if (/dns2=(.*)/)
		{
		    $dns2 = $1;
		    next;
		}
		if (/dns3=(.*)/)
		{
		    $dns3 = $1;
		    next;
		}
		if (/device=(.*)/)
		{
		    $device_name = $1;
		    next;
		}
		if ($device_name)
		{
		    if (/active=(.*)/)
		    {
			$active = $1;
			next;
		    }
		    if (/dhcp=(.*)/)
		    {
			$dhcp = $1;
			next;
		    }
		    if (/ip=(.*)/)
		    {
			$ip = $1;
			next;
		    }
		    if (/netmask=(.*)/)
		    {
			$netmask = $1;
			next;
		    }
		    if (/gateway=(.*)/)
		    {
			$gateway = $1;
			next;
		    }
		    if (/wifi=(.*)/)
		    {
			$wifi = $1;
			next;
		    }
		    if (/w_ssid=(.*)/)
		    {
			$w_ssid = $1;
			next;
		    }
		    if (/w_rate=(.*)/)
		    {
			$w_rate = $1;
			next;
		    }
		    if (/w_wep=(.*)/)
		    {
			$w_wep = $1;
			next;
		    }
		    if (/nat=(.*)/)
		    {
			$nat = $1;
			next;
		    }
		    if (/w_wpa=(.*)/)
		    {
			$w_wpa = $1;
			next;
		    }
		    if (/----------(.*)/)
		    {
                        $devices{$device_name} = 
                        {
                            name => $device_name,
                            wifi => $wifi,
                            w_ssid => $w_ssid,
                            w_rate => $w_rate,
                            w_wep => $w_wep,
                            w_wpa => $w_wpa,
                            active => $active,
                            dhcp => $dhcp,
                            ip => $ip,
                            netmask => $netmask,
                            gateway => $gateway,
                            nat => $nat,
                        }
    		    }
                    if (/__________(.*)/)
                    {
			#write one setting
			my $one_setting = {
			    name => $config_name,
			    icon => $icon,
			    description => $description,
			    default_net => $default_net,
                            dns_auto => $dns_auto,
			    dns1 => $dns1,
			    dns2 => $dns2,
			    dns3 => $dns3,
			    devices =>
			    {
                                %devices
			    }
			};
			
			push @all_settings,$one_setting;
                        
                        %devices = ();
                    }
		}
	    }
	}
    }
    
    close(FILE);
    
    my $have_config = FALSE;
    #we put the configs on the left
    foreach (@all_settings)
    {
	push @{$left_simple_list->{data}},$_->{name};
	$have_config = TRUE;
    }
    
    #if we have in the settings cards 
    #that don't exists, we show them also
    @all_cards = @ethernet_cards;
    
    #we get the devices that we have in the settings but that dont
    #exists
    foreach my $current_setting (@all_settings)
    {
	my @all_devices = keys %{$current_setting->{devices}};
	foreach my $dev (@all_devices)
	{
	    my $device = $current_setting->{devices}->{$dev};
	    
	    #if not an ethernet but virtual device
	    if (!is_ethernet($device->{name}))
	    {
		#if we don't have it on the virtual cards
		#we put it
		if (!is_virtual($device->{name}))
		{
		    push @all_cards,$device->{name}."\n";
		    push @virtual_cards,$device->{name};
		}
	    }
	}
    }
    
    #if we have no config, create new configuration
    if (!$have_config)
    {
	push @{$left_simple_list->{data}},"new_config";
	
	my $one_setting = get_new_config();
	
	push @all_settings,$one_setting;
	
	$expanded_description = TRUE;
	
	save_settings();
    }    
}

#about menu item event
sub about_menu_event
{
    #the about dialog
    my $about_dialog = Gtk2::AboutDialog->new;
    $about_dialog->set_name($program_name);
    $about_dialog->set_version($program_version);
    $about_dialog->set_license("\
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.,\
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.");
    $about_dialog->set_copyright("2006 (c) ".$program_author);
    my $program_dir = dirname(realpath($0));
    my $pixbuf = Gtk2::Gdk::Pixbuf->new_from_file("/usr/share/network-config/default-icon.png");
    $about_dialog->set_logo($pixbuf);
    $about_dialog->set_comments($program_date);
    $about_dialog->show;
}

#the preferences of the program
sub preferences_menu_event
{
    #initiate preferences window dialog
    my $pref_dialog = 
	Gtk2::Dialog->new ($program_name." preferences",
			   $main_window,
			   [qw/modal
			    destroy-with-parent/]);
    $pref_dialog->set_resizable(FALSE);
    $pref_dialog->set_default_response("close");
    
    #we put the close button to the dialog
    my $pref_close_button = 
	$pref_dialog->add_button("gtk-close","close");
    $pref_close_button->signal_connect(clicked => sub {
	my ($widget,$dialog) = @_;
	$dialog->destroy;
	$dialog = undef;
    },$pref_dialog);
    
    #the main preferences vbox
    my $pref_vbox = Gtk2::VBox->new;
    $pref_vbox->set_border_width(7);
    
    #the main preferences top icon+label
    my $pref_top_hbox = Gtk2::HBox->new;
    my $pref_top_image = 
	Gtk2::Image->new_from_stock("gtk-preferences","button");
    my $pref_top_label = Gtk2::Label->new;
    $pref_top_label->set_markup("<b>Preferences</b>");
    $pref_top_label->set_alignment(0,0.5);
    $pref_top_hbox->pack_start($pref_top_image,FALSE,FALSE,0);
    $pref_top_hbox->pack_start($pref_top_label,FALSE,FALSE,0);
    my $fake_hbox = Gtk2::HBox->new(FALSE,0);
    $fake_hbox->pack_start($pref_top_hbox,FALSE,FALSE,5);
    $pref_vbox->pack_start($fake_hbox,FALSE,FALSE,0);
    
    #the main preferences notebook
    my $pref_notebook = Gtk2::Notebook->new;
    $pref_vbox->pack_start($pref_notebook,FALSE,FALSE,0);
    
    #Wifi settings tab
    my $wifi_pref_vbox = Gtk2::VBox->new(FALSE,0);
    $wifi_pref_vbox->set_border_width(4);
    #the wpa frame
    my $pref_wpa_frame = Gtk2::Frame->new("Wpa_supplicant");
    $wifi_pref_vbox->pack_start($pref_wpa_frame,FALSE,FALSE,4);
    my $pref_wpa_frame_vbox = Gtk2::VBox->new(FALSE,0);
    $pref_wpa_frame->add($pref_wpa_frame_vbox);
    
    #the wpa config file
    my $pref_wpa_conf_hbox = Gtk2::HBox->new(FALSE,0);
    my $pref_wpa_conf_label = Gtk2::Label->new("Configuration file :");
    $pref_wpa_conf_label->set_alignment(0,0.5);
    my $pref_wpa_conf_entry = Gtk2::Entry->new;
    $pref_wpa_conf_entry->set_text($wpa_configuration_file);
    $pref_wpa_conf_entry->signal_connect("changed" =>
					 sub {
					     my ($widget) = @_;
					     $wpa_configuration_file = $widget->get_text;
					     save_settings();
					 });
    $pref_wpa_conf_hbox->pack_start($pref_wpa_conf_label,TRUE,FALSE,5);
    $pref_wpa_conf_hbox->pack_start($pref_wpa_conf_entry,FALSE,FALSE,5);
    $pref_wpa_frame_vbox->pack_start($pref_wpa_conf_hbox,FALSE,FALSE,4);
    
    #the wpa driver
    my $pref_wpa_driver_hbox = Gtk2::HBox->new(FALSE,0);
    my $pref_wpa_driver_label = Gtk2::Label->new("Wifi driver :");
    $pref_wpa_driver_label->set_alignment(0,0.5);
    my $pref_wpa_driver_entry = Gtk2::Entry->new;
    $pref_wpa_driver_entry->set_text($wpa_driver);
    $pref_wpa_driver_entry->signal_connect("changed" =>
					   sub {
					       my ($widget) = @_;
					       $wpa_driver = $widget->get_text;
					       save_settings();
					   });
    $pref_wpa_driver_hbox->pack_start($pref_wpa_driver_label,TRUE,TRUE,5);
    $pref_wpa_driver_hbox->pack_start($pref_wpa_driver_entry,FALSE,FALSE,5);
    $pref_wpa_frame_vbox->pack_start($pref_wpa_driver_hbox,FALSE,FALSE,4);
    
    #general tab
    my $general_pref_vbox = Gtk2::VBox->new(FALSE,0);
    $general_pref_vbox->set_border_width(4);
    
    #the dhcp frame
    my $pref_dhcp_frame = Gtk2::Frame->new("DHCP");
    $general_pref_vbox->pack_start($pref_dhcp_frame,FALSE,FALSE,4);
    my $pref_dhcp_frame_vbox = Gtk2::VBox->new(FALSE,0);
    $pref_dhcp_frame->add($pref_dhcp_frame_vbox);
    
    #the dhcp label + entry
    my $pref_dhcp_hbox = Gtk2::HBox->new(FALSE,0);
    my $pref_dhcp_label = Gtk2::Label->new("DHCP client :");
    $pref_dhcp_label->set_alignment(0,0.5);
    $pref_dhcp_entry = Gtk2::Entry->new;
    $pref_dhcp_entry->set_text($dhcp_client);
    $pref_dhcp_entry->signal_connect("changed" =>
				     sub {
					 my ($widget) = @_;
					 $dhcp_client = $widget->get_text;
					 save_settings();
				     });
    $pref_dhcp_hbox->pack_start($pref_dhcp_label,TRUE,TRUE,5);
    $pref_dhcp_hbox->pack_start($pref_dhcp_entry,FALSE,FALSE,5);
    $pref_dhcp_frame_vbox->pack_start($pref_dhcp_hbox,FALSE,FALSE,4);
    
    #internet frame
    my $pref_internet_frame = Gtk2::Frame->new("Internet");
    $general_pref_vbox->pack_start($pref_internet_frame,FALSE,FALSE,4);
    my $pref_internet_frame_vbox = Gtk2::VBox->new(FALSE,0);
    $pref_internet_frame->add($pref_internet_frame_vbox);
    
    #check if internet connection
    my $fake_horiz = Gtk2::HBox->new(FALSE,0);
    my $check_internet;
    $check_internet = 
	Gtk2::CheckButton->new("Check internet connection at the end");
    $check_internet->set_active($test_for_internet);    
    $fake_horiz->pack_start($check_internet,FALSE,FALSE,5);
    $pref_internet_frame_vbox->pack_start($fake_horiz,FALSE,FALSE,4);
    $check_internet->signal_connect("clicked" =>
				    \&check_internet_event);
    
    #internet website
    $internet_site_hbox = Gtk2::HBox->new;
    my $internet_site_label = Gtk2::Label->new("Web site or IP :");
    my $internet_site_entry = Gtk2::Entry->new;
    $internet_site_label->set_alignment(0,0.5);
    #we put the site text
    $internet_site_entry->set_text($internet_site_for_ping);
    $internet_site_hbox->pack_start($internet_site_label,TRUE,TRUE,5);
    $internet_site_hbox->pack_start($internet_site_entry,FALSE,FALSE,5);
    if (!$check_internet->get_active)
    {
	$internet_site_hbox->set_sensitive(FALSE);
    }
    $pref_internet_frame_vbox->pack_start($internet_site_hbox,FALSE,FALSE,4);
    
    #we change the internet site ping
    $internet_site_entry->signal_connect("changed" =>
					 sub {
					     my ($widget) = @_;
					     $internet_site_for_ping = $widget->get_text;
					     save_settings();
					 });
    
    #we append the pages to the notebook
    $pref_notebook->append_page($general_pref_vbox,"General");
    $pref_notebook->append_page($wifi_pref_vbox,"Wifi");
    
    #we put the main vbox
    $pref_dialog->vbox->pack_start($pref_vbox,TRUE,TRUE,0);
    $pref_dialog->show_all;
    $pref_dialog->run;
}

#create the main window
sub main_window_create
{
    #create the main window
    $main_window = Gtk2::Window->new('toplevel');
    my $program_dir = dirname(realpath($0));
    my $pixbuf = Gtk2::Gdk::Pixbuf->new_from_file("/usr/share/network-config/default-icon.png");
    $main_window->set_default_icon($pixbuf);
    #title of the main window
    $main_window->set_title($program_name." ".$program_version);
    #center of the screen
    $main_window->set_position("center");
    #disable main window resize
    $main_window->set_resizable(FALSE);
    #the main window close event
    $main_window->signal_connect("destroy" => sub { Gtk2->main_quit; });
    #destroy the main window signal
    $main_window->signal_connect("destroy" => sub { Gtk2->main_quit; });
    #border of the window
    #$main_window->set_border_width(5);
    
    #main horizontal box
    $main_hbox = Gtk2::HBox->new(FALSE, 0);
    
    #window menu
    my @menu_items = (
                      [ "/_Main",       undef, undef, 0, "<Branch>" ],
                      [ "/Main/_Preferences", undef, \&preferences_menu_event, 0, "<StockItem>", 'gtk-preferences' ],
                      [ "/Main/_Quit", undef, sub {Gtk2->main_quit;}, 0, "<StockItem>", 'gtk-quit' ],
                      [ "/_Help",       undef, undef, 0, "<Branch>" ],
                      [ "/Help/_About", undef, \&about_menu_event, 0, "<StockItem>", 'gtk-about' ]);
    my $accel_group = Gtk2::AccelGroup->new;
    $main_window->add_accel_group ($accel_group);
    my $item_factory = Gtk2::ItemFactory->new ("Gtk2::MenuBar", "<main>", 
                                               $accel_group);
    $main_window->{'<main>'} = $item_factory;
    $item_factory->create_items ($main_window, @menu_items);
    
    ########################
    #left list
    $left_simple_list =
	Gtk2::SimpleList->new ('Configurations :' => 'text');
    my $column = $left_simple_list->get_column(0);
    $column->set_min_width(60);
    $column->set_max_width(120);
    #left list options
    $left_simple_list->set_headers_visible(FALSE);
    $left_simple_list->set_column_editable('Configuration',TRUE);
    #simple click event
    $left_simple_list->signal_connect("button_release_event" =>
				      \&left_simple_list_button_press_event);
    $left_simple_list->set_enable_search(FALSE);
    
    #we unsensitive the remove button if necessary
    $left_simple_list->get_selection->
        signal_connect("changed"=>
                       sub { 
                           if ($#all_settings == 0)
                           {
                               $remove_config_button->set_sensitive(FALSE);
                           }
                           else
                           {
                               $remove_config_button->set_sensitive(TRUE);
                           }
                           #fix of the BUG below?
                           save_settings();
                       });
    
    $left_simple_list->signal_connect("row_activated"=>
                                      \&left_simple_list_name_changed_event);
    
    #rename event
    #TODO - bug: does not save if modified with the mouse
    $left_simple_list->signal_connect("key_release_event" =>
                                      \&left_simple_list_name_changed_event);
    
    #put the data to the list
    load_settings();
    
    #we put the 2 buttons, add and remove
    my $add_config_button =
        Gtk2::Button->new_from_stock("gtk-new");
    my $b_tooltip = Gtk2::Tooltips->new;
    $b_tooltip->set_tip($add_config_button,"New configuration");
    $remove_config_button =
        Gtk2::Button->new_from_stock("gtk-delete");
    $add_config_button->signal_connect("clicked" =>
                                       \&left_popup_menu_new_event);
    $remove_config_button->signal_connect("clicked" =>
                                          \&left_popup_menu_remove_event);
    $b_tooltip = Gtk2::Tooltips->new;
    $b_tooltip->set_tip($remove_config_button,"Delete selected configuration");
    my $buttons_hbox = Gtk2::HBox->new;
    $buttons_hbox->pack_start($add_config_button,TRUE,TRUE,0);
    $buttons_hbox->pack_start($remove_config_button,TRUE,TRUE,0);
    
    #vertical box for the left list and the new and remove buttons
    my $left_list_buttons_vbox = Gtk2::VBox->new;
    #scroll window where we put the left simple list
    my $scrolled_window = Gtk2::ScrolledWindow->new;
    $scrolled_window->set_policy('automatic','automatic');
    $scrolled_window->add($left_simple_list);
    $left_list_buttons_vbox->pack_start($scrolled_window,TRUE,TRUE,0);
    $left_list_buttons_vbox->pack_start($buttons_hbox,FALSE,FALSE,0);
    
    #we put the list_buttons_vbox to the main hbox
    $main_hbox->pack_start($left_list_buttons_vbox,FALSE,FALSE,5);
    $main_vbox = Gtk2::VBox->new;
    $main_vbox->pack_start($main_hbox,FALSE,FALSE,5);
    $main_vbox->show_all;
    
    ########################
    #right vertical box with all the options
    draw_tabs();
    
    #select tab
    $start_vbox = Gtk2::VBox->new;
    $start_hbox = Gtk2::HBox->new;
    load_select_tab_configurations();
    
    $start_hbox->pack_start($start_vbox,TRUE,TRUE,5);
    
    #############################
    #the main notebook
    $main_notebook = Gtk2::Notebook->new;
    $main_notebook->append_page($start_hbox,"Select");
    $main_notebook->set_show_tabs(FALSE);
    
    #really main vbox
    my $on_top_all_vbox;
    $on_top_all_vbox = Gtk2::VBox->new(FALSE,0);
    $on_top_all_vbox->pack_start($item_factory->get_widget ("<main>"),
				 FALSE,FALSE,0);
    $on_top_all_vbox->pack_start($main_notebook,FALSE,FALSE,0);
    
    #add the notebook to the main window
    $main_window->add($on_top_all_vbox);
    
    load_apply_preferences_quit_buttons_select();
    load_apply_preferences_quit_buttons_config();
    
    #display the main window
    $main_window->show_all;
    
    $main_notebook->prev_page;
    
    #main loop
    Gtk2->main;
}

#applies the text mode configuration
sub apply_text_mode_configuration
{
    my $initialised = FALSE;
    
    #if we have an argument
    if ($ARGV[1])
    {
	#put the data to the list
	load_settings();
	
	my $counter = 0;
	#we find out the number that matches our config
	foreach (@all_settings)
	{
	    if ($_->{name} eq $ARGV[1])
	    {
		$initialised = TRUE;
		last;
	    }
	    $counter++;
	}
	
	#if we have found a network like this
	if ($initialised)
	{
	    print "Configuring network for ".$ARGV[1]."...\n";
	    apply_network_settings($counter);
	}
	else
	{
	    print STDERR "Error, unknown config \"".$ARGV[1]."\"\n";
	    show_configurations();
	    exit(1);
	}
    }
    else
    {
	print STDERR "Error, option -ta needs an argument\n";
	show_configurations();
	exit(1);
    }
}

#shows the configuration of the config ARGV[1]
sub show_text_mode_configuration
{
    my $initialised = FALSE;
    
    #if we have an argument
    if ($ARGV[1])
    {
	#put the data to the list
	load_settings();
	
	my $counter = 0;
	#we find out the number that matches our config
	foreach (@all_settings)
	{
	    if ($_->{name} eq $ARGV[1])
	    {
		$initialised = TRUE;
		last;
	    }
	    $counter++;
	}
	
	#if we have found a network like this
	if ($initialised)
	{
	    print "Network settings for ".$ARGV[1]." :\n\n";
	    print_configuration($counter);
	}
	else
	{
	    print STDERR "Error, unknown config \"".$ARGV[1]."\"\n";
	    show_configurations();
	    exit(1);
	}
    }
    else
    {
	print STDERR "Error, option -ts needs an argument\n";
	show_configurations();
	exit(1);
    }
}

#change the network settings of $setting
#with values of $format :
#FORMAT example : name=test,eth0[dhcp=TRUE ip=192.168 netmask=255.255.255.0]
sub change_text_network_settings
{
    my ($setting,$format) = @_;
    
    #we take the changes
    my @changes = split(",",$format);
    my $device_name_change = FALSE;
    my $new_device_name = "";
    
    foreach (@changes)
    {
	if (/(eth|wlan|ppp|rausb)(\d+)\[(.*)\]/)
	{
	    my $device_name = $1.$2;
	    my $device_config = $3;
	    my @device_values = split(" ",$device_config);
	    
	    #we change all the settings for the current device
	    foreach (@device_values)
	    {
		if (/(.*)=(.*)/)
		{
		    my $config_name = $1;
		    my $config_value = $2;
		    
		    #if the device name exists
		    if (exists($all_settings[$setting]->{devices}->{$device_name}))
		    {
			#we must not change the wifi variable
			if ($config_name ne "wifi")
			{
			    #if the device value exists
			    if (exists($all_settings[$setting]->{devices}->{$device_name}->{$config_name}))
			    {
				$all_settings[$setting]->{devices}->{$device_name}->{$config_name} = $config_value;
			    }
			    else
			    {
				print "Warning, unknown device format \"".$_."\"\n";
			    }
			}
			else
			{
			    print "Warning, unknown device format \"".$_."\"\n";
			}
		    }
		    else
		    {
			print "Warning, unknown device name \"".$device_name."\"\n";
		    }
		}
		else
		{
		    print "Error, parse error\n";
		    exit(1);
		}
	    }
	}
	else
	{
	    if (/(.*)=(.*)/)
	    {
		my $config_name = $1;
		my $config_value = $2;
		
		#if it's the name, do it only at the end
		if ($config_name eq "name")
		{
		    $device_name_change = TRUE;
		    $new_device_name = $config_value;
		}
		#we check that the key exists
		if (exists($all_settings[$setting]->{$config_name}))
		{
		    $all_settings[$setting]->{$config_name}=$config_value;
		}
		else
		{
		    print "Warning, unknown format \"".$config_name."\"\n";
		}
	    }
	    else
	    {
		print "Error, parse error\n";
		exit(1);
	    }
	}
    }
    
    #we change the device name if necessary
    if ($device_name_change)
    {
	$all_settings[$setting]->{name}=$new_device_name;
    }
}

#change the configuration of the config ARGV[1]
sub change_text_mode_configuration
{
    my $initialised = FALSE;
    
    #if we have an argument
    if ($ARGV[1] && $ARGV[2])
    {
	#put the data to the list
	load_settings();
	
	my $counter = 0;
	#we find out the number that matches our config
	foreach (@all_settings)
	{
	    if ($_->{name} eq $ARGV[1])
	    {
		$initialised = TRUE;
		last;
	    }
	    $counter++;
	}
	
	#if we have found a network like this
	if ($initialised)
	{
	    #we change the network settings
	    print "Changing network settings for ".$ARGV[1]."...\n";
	    change_text_network_settings($counter,$ARGV[2]);
	    #save settings
	    save_settings();
	    #print the new settings
	    print "\nNew network settings for ".$ARGV[1]." : \n\n";
	    print_configuration($counter);
	}
	else
	{
	    print STDERR "Error, unknown config \"".$ARGV[1]."\"\n";
	    show_configurations();
	    exit(1);
	}
    }
    else
    {
	print STDERR "Error, option -tc needs two arguments\n";
	show_configurations();
	exit(1);
    }
}

#shows the help of the program and exits the program
sub show_help
{
    print $program_name." version ".$program_version."\n".
"$program_author\n\n".
"USAGE:".
"\tnetwork-config [OPTIONS]\n\n".
"OPTIONS:\n".
"  -tl\t\t\tlists all the configurations\n".
"  -ts CONFIG\t\tshows CONFIG configuration\n".
"  -tc CONFIG \"FORMAT\"\tchanges the CONFIG configuration\n".
"      FORMAT example : name=test,eth0[dhcp=TRUE ip=192.168. netmask=255.]\n".
"      formats : name,icon,description,dns_auto,dns1,dns2,dns3,default_net\n".
"      devices formats : active,ip,netmask,gateway,nat,dhcp,w_wep,\n".
"                        w_wpa,w_ssid,w_rate\n".
"  -ta CONFIG\t\tapplies the CONFIG configuration\n\n";
}

#lists all the existing configurations
sub show_configurations
{
    #put the data to the list
    load_settings();
    
    print "Existing configurations :\n";
    #we find out the number that matches our config
    foreach (@all_settings)
    {
	my $description = $_->{description};
	if (!$description || 
	    ($description eq ""))
	{
	    $description = "no description";
	}
	print "\t\"".$_->{name}."\" : ".$description."\n";
    }
}

#gets ethernet and wifi cards
sub get_ethernet_wifi_cards
{
    #ethernet cards (includes wifi cards)
    @ethernet_cards = 
	`ifconfig -a | grep -E "wlan|eth|ppp|rausb" | cut -d " " -f 1 | sort`;
    my $counter = 0;
    foreach (@ethernet_cards)
    {
        #erase cards with weird mac address
        chomp $_;
        my $weird_mac = `ifconfig $_ | grep HW`;
        if ($weird_mac =~ /(.*)-(.*)-(.*)-(.*)/)
        {
            splice @ethernet_cards,$counter,1;
        }
        else
        {
            #erase spaces before eth or wlan
            $_ =~ s/\s+(.)/$1/;
            #erase other thing than eth or wlan
            if (!($_ =~ /(eth|wlan|ppp|rausb)\d+/))
            {
                splice @ethernet_cards,$counter,1;
            }
        }
	$counter++;
    }
    
    #wifi cards
    @wifi_cards =
	`iwconfig 2>/dev/null | grep -E \"wlan|eth|ppp|rausb\" | cut -d " " -f 1`;
}

 MAIN:
    #we get the ethernet and the wifi cards
    get_ethernet_wifi_cards();

#by default, we have the graphic mode
$graphic_mode=TRUE;

if ($ARGV[0])
{
    #if we have help
    if (($ARGV[0] eq "--help")
	||($ARGV[0] eq "-h"))
    {
	show_help();
	exit(0);
    }
    else
    {
	#if we have text mode
	if (($ARGV[0] eq "-ta") ||
	    ($ARGV[0] eq "-tl") ||
	    ($ARGV[0] eq "-ts") ||
	    ($ARGV[0] eq "-tc"))
	{
	    $graphic_mode=FALSE;
	}
	else
	{
	    $graphic_mode=FALSE;
	    print STDERR "Error, unknown option \"".$ARGV[0]."\"\n\n";
	    show_help();
	    exit(1);
	}
    }
}

#we check if we are root
my ($name,$passwd,$uid,$gid,$quota,$comment,$gcos,$dir,$shell,$expire) = getpwuid $>;
#if we are root
if (($uid == 0) && ($gid == 0))
{
    #graphic mode
    if ($graphic_mode)
    {
	Gtk2::Gdk::Threads->init;
	Gtk2->init;
	main_window_create();
    }
    #text mode
    else
    {
	if ($ARGV[0] eq "-tl")
	{
	    show_configurations();
	    exit(0);
	}
	elsif ($ARGV[0] eq "-ta")
	{
	    #we apply the configuration with the text mode
	    apply_text_mode_configuration();
	}
	elsif ($ARGV[0] eq "-ts")
	{
	    show_text_mode_configuration();
	}
	elsif ($ARGV[0] eq "-tc")
	{
	    change_text_mode_configuration();
	}
    }
}
#if we are not root, try to start as root...
else
{
    my $program_dir = dirname(realpath($0));
    #graphic mode
    if ($graphic_mode)
    {
	print "starting gksu $0...\n";
	system("gksu $program_dir/network-config");
    }
    #text mode
    else
    {
	my $command = "su root -c \"$program_dir/network-config.pl @ARGV\"";
	print $command."\n";
	system($command);
    }
}

#if we are here, return no error
0;
