#!/usr/bin/perl

#Copyright (C) 2006-2008 Alexandru Ionut Munteanu <io_fx AT yahoo.fr>
#
#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.2";
my $program_name = "Network-config";
my $program_author = "Alexandru Ionut Munteanu\nio_fx AT yahoo.fr";
#my $program_date = "- subversion release -";
my $program_date = "- released on 07.04.2008 -";
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_dir."/wpa_supplicant/wpa_psk.conf";
my $wpa_driver="ndiswrapper";
my $dhcp_client="dhclient";
my $window_size_x = 80;
my $window_size_y = 300;
#scan for networks dialog
my $scan_dialog = undef;
my $scan_top_label;
my $scan_list;    
#preferences global variables
my $pref_dhcp_entry;

#save the window size when changing between edit and select
#configuration main view 
my $main_saved_window_x;
my $main_saved_window_y;
my $config_saved_window_x;
my $config_saved_window_y;

my $inside_config = FALSE;
my $run_script_at_the_end = "";

#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 run_script_event
{
  my ($widget) = @_;

  my ($config,$device) = get_selected_config_and_device();

  if (defined($config) && defined($device))
  {
    $all_settings[$config]->{run_script} = $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 => "$program_dir/default-icon.png",
    description => "your description here",
    default_net => $ethernet_cards[0],
    dns_auto => "TRUE",
    dns1 => "",
    dns2 => "",
    dns3 => "",
		run_script => "",
    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(.*)off/)
  {
		$real_command = "iwconfig".$1."key off";
	}
	elsif ($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
    if ($current_config->{dns1} ne '')
    {
        $command = "echo \"nameserver $current_config->{dns1}\" > /etc/resolv.conf";
        execute_command($command);
    }
    if ($current_config->{dns2} ne '')
    {
        $command = "echo \"nameserver $current_config->{dns2}\" >> /etc/resolv.conf";
        execute_command($command);
    }
    if ($current_config->{dns3} ne '')
    {
        $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")
        {
					#fix : managed mode
					execute_command("iwconfig $device->{name} mode managed");
          $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} && ($device->{w_wep} ne ""))
          {
            $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;
						chmod 0600,$wpa_configuration_file;
            close(FILE);
            #we run wpa_supplicant
            $command="pkill wpa_supplicant";
            execute_command($command);
						sleep 1;
            $command="wpa_supplicant -B -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);
  }

	#run script at the end for specific configurations
	if ($current_config->{run_script} && $current_config->{run_script} ne '')
	{
		execute_command($current_config->{run_script});
	}

  if ($run_script_at_the_end ne '')
  {
    execute_command($run_script_at_the_end);
  }

  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_default_size(570, 400);
  #$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_view->set_editable(FALSE);
  $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("$program_dir/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";
		print FILE "run_script=$one_setting->{run_script}\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 "run_script_at_the_end=$run_script_at_the_end\n";
	print FILE "window_size_x=$window_size_x\n";
	print FILE "window_size_y=$window_size_y\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";
    }
		if ($current_config->{run_script})
		{
			print "run script\t$current_config->{run_script}\n";
		}
  }
  print "default_net\t$current_config->{default_net}\n";

  #we print all the devices
  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
  if (defined($net_name))
  {
    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');
    }
		#if the network has a name
		if ($_->{name} ne '')
		{
			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(TRUE);
    $scan_dialog->set_default_size(500,500);

    #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
    my $scan_list_scrolled = Gtk2::ScrolledWindow->new;
    $scan_list_scrolled->set_policy('automatic','automatic');
    $scan_list_scrolled->add($scan_list);
    $scan_hbox_list->pack_start($scan_list_scrolled,TRUE,TRUE,10);
    $scan_vbox->pack_start($scan_hbox_list,TRUE,TRUE,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("$program_dir/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(15);
  $dns2_entry->set_width_chars(15);
  $dns3_entry->set_width_chars(15);
  $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);

	#run script at the end entry			
	my $run_script_end_vbox = Gtk2::VBox->new();
	my $run_script_end_hbox = Gtk2::HBox->new();
	my $run_script_end_label = Gtk2::Label->new("Run script at the end :");
	my $run_script_end_entry = Gtk2::Entry->new();
	$fake_horiz = Gtk2::HBox->new;
	$fake_horiz->pack_start($run_script_end_label,FALSE,FALSE,0);
	$run_script_end_entry->set_width_chars(25);
  $run_script_end_entry->signal_connect("changed" => \&run_script_event);
	$run_script_end_vbox->pack_start($fake_horiz,FALSE,FALSE,0);
	$run_script_end_vbox->pack_start($run_script_end_entry,FALSE,FALSE,0);
	$run_script_end_hbox->pack_start($run_script_end_vbox,FALSE,FALSE,0);
	$general_vbox->pack_start($run_script_end_hbox,FALSE,FALSE,4);

  #############################
  #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});
  $run_script_end_entry->set_text($current_setting->{run_script});

  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(15);
      $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(15);
      $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(15);
      $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(15);
      $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,TRUE,TRUE,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(15);
		$ip_address_gateway->set_alignment(0,0.5);
    $horiz_fake->pack_start($ip_address_gateway,TRUE,TRUE,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(15);
		$netmask->set_alignment(0,0.5);
    $horiz_fake->pack_start($netmask,TRUE,TRUE,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->set_alignment(0,0.5);
    $gateway_entry = Gtk2::Entry->new_with_max_length(15);
    $gateway_entry->signal_connect("changed" => 
      \&gateway_entry_event);
    $gateway_entry->set_width_chars(15);
    $horiz_fake->pack_start($gateway,TRUE,TRUE,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,TRUE,TRUE,3);
      $wifi_notebook->append_page($wifi_notebook_hbox,"Wifi settings");
      $wifi_notebook->set_show_border(FALSE);
    }
    else
    {
      $tab_content->pack_start($settings_vbox,TRUE,TRUE,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,TRUE,TRUE,0);
    $tab_vbox_content->pack_start($tab_fake_vbox_content,TRUE,TRUE,5);
    $tab_hbox_content->pack_start($tab_vbox_content,TRUE,TRUE,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($notebook,"Config");
  $appearance_config_notebook->append_page($appearance_vbox,"Appearance");

  #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,TRUE,TRUE,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
{
  my $first_page_vbox = Gtk2::VBox->new;
  $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);

  #scrolled window for the configuration chooser
  my $first_page_scrolled_window = Gtk2::ScrolledWindow->new;
  $first_page_scrolled_window->set_policy('automatic','automatic');
  $first_page_scrolled_window->add($select_list);

  $first_page_vbox->pack_start($first_page_scrolled_window,TRUE,TRUE,5);
  $first_page_vbox->pack_start($description_hbox,FALSE,FALSE,0);

  $start_vbox->pack_start($first_page_vbox,TRUE,TRUE,0);
}

#properties button from the first page
sub change_config_button_event
{
	$inside_config = TRUE;
  ($main_saved_window_x, $main_saved_window_y) = $main_window->get_size();
  if (defined($config_saved_window_x) &&
      defined($config_saved_window_y))
  {
      $main_window->resize($config_saved_window_x,$config_saved_window_y);
  }
  $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);
}

#go to first page from the configuration page
sub change_select_button_event
{
  ($config_saved_window_x, $config_saved_window_y) = $main_window->get_size();
  if (defined($main_saved_window_x) &&
      defined($main_saved_window_y))
  {
      $main_window->resize($main_saved_window_x,$main_saved_window_y);
  }

  $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);
	$inside_config = FALSE;
}

#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,FALSE,FALSE,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 = "";
		my $run_script_end = "";

    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 (/run_script_at_the_end=(.*)/)
      {
          $run_script_at_the_end = $1;
      }
      if (/wpa_configuration_file=(.*)/)
      {
        $wpa_configuration_file = $1;
      }
      if (/wpa_driver=(.*)/)
      {
        $wpa_driver = $1;
      }
      if (/dhcp_client=(.*)/)
      {
        $dhcp_client = $1;
      }
			if (/window_size_x=(.*)/)
			{
				$window_size_x = $1;
			}
			if (/window_size_y=(.*)/)
			{
				$window_size_y = $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;
				$run_script_end="";
        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 (/run_script=(.*)/)
				{
					$run_script_end = $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,
							run_script => $run_script_end,
              devices =>
              {
                %devices
              }
            };

            push @all_settings,$one_setting;

            %devices = ();
          }
        }
      }
    }
  }

  close(FILE);

  #for all the network cards that exist and that have no 
  #add default configuration
  foreach my $dev (@ethernet_cards)
  {
      #for all the configurations
      foreach my $one_setting (@all_settings)
      {
          #for all the devices
          if (! defined($one_setting->{devices}->{$dev}) ||
              ! defined($one_setting->{devices}->{$dev}{name}))
          {
              $one_setting->{devices}->{$dev} =
              {
                  name => $dev,
                  wifi => is_wifi($dev),
                  w_ssid => "",
                  w_rate => "auto",
                  w_wep => "",
                  w_wpa => "",
                  active => "FALSE",
                  nat => "FALSE",
                  dhcp => "TRUE",
                  ip => "",
                  netmask => "",
                  gateway => "",
              }
          }
      }
  }

  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_default_response("ok");
  $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("2007 (c) ".$program_author);
  my $program_dir = dirname(realpath($0));
  my $pixbuf = Gtk2::Gdk::Pixbuf->new_from_file("$program_dir/default-icon.png");
  $about_dialog->set_logo($pixbuf);
  $about_dialog->set_comments($program_date);
  $about_dialog->run;
  $about_dialog->destroy;
}

#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_width_chars(25);
  $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,TRUE,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_width_chars(25);
  $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_width_chars(25);
  $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_entry->set_width_chars(25);
  $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();
    });

  #Other frame
  my $other_frame = Gtk2::Frame->new("Other");
  $general_pref_vbox->pack_start($other_frame,FALSE,FALSE,4);
  my $other_frame_vbox = Gtk2::VBox->new(FALSE,0);
  $other_frame->add($other_frame_vbox);

  #run script at the end
  my $run_script_end_hbox = Gtk2::HBox->new;
  my $run_script_end_label = Gtk2::Label->new("Run script at the end :");
  my $run_script_end_entry = Gtk2::Entry->new;
  $run_script_end_entry->set_width_chars(25);
  #we put the text
  $run_script_end_entry->set_text($run_script_at_the_end);
  $run_script_end_label->set_alignment(0,0.5);

  #we change the run script at the end
  $run_script_end_entry->signal_connect("changed" =>
    sub {
      my ($widget) = @_;
      $run_script_at_the_end = $widget->get_text;
      save_settings();
    });

  $run_script_end_hbox->pack_start($run_script_end_label,TRUE,TRUE,5);
  $run_script_end_hbox->pack_start($run_script_end_entry,FALSE,FALSE,5);
  $other_frame_vbox->pack_start($run_script_end_hbox,FALSE,FALSE,4);

  #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;
}

sub resize_main_window_event($)
{
	my ($container) = @_;
	if (! $inside_config)
	{
		($window_size_x,$window_size_y) = $container->get_size();
		save_settings();
	}
}

#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("$program_dir/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(TRUE);
  #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();

	#check for main window resize
  $main_window->signal_connect("check_resize" => \&resize_main_window_event);
	$main_window->set_default_size($window_size_x,$window_size_y);

  #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,TRUE,TRUE,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,TRUE,TRUE,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|ath|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,run_script,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 "ath|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|ath|wlan|ppp|rausb)\d+/))
      {
        splice @ethernet_cards,$counter,1;
      }
    }
    $counter++;
  }
  chomp @ethernet_cards;

  #wifi cards
  @wifi_cards =
  `iwconfig 2>/dev/null | grep -E \"ath|wlan|eth|ppp|rausb\" | cut -d " " -f 1`;
  chomp @wifi_cards;
}

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.pl");
  }
  #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;
