#! /usr/bin/perl

###################################################
#
#  Copyright (C) 2008, 2009 Mario Kemper <mario.kemper@googlemail.com> and Shutter Team
#
#  This file is part of Shutter.
#
#  Shutter 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 3 of the License, or
#  (at your option) any later version.
#
#  Shutter 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 Shutter; if not, write to the Free Software
#  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
#
###################################################

#modules
#--------------------------------------
use utf8;
use strict;
use warnings;

#Gnome2 libraries
use Gnome2;
use Gnome2::GConf;
use Gnome2::Wnck;
use Gnome2::VFS '-init';

#Use AuthenticationManager to handle user credentials easily
Gnome2::AuthenticationManager->init;

#File operations
use File::Copy qw/ cp mv /;
use File::Path qw/ rmtree /;
use File::Glob qw/ glob /;
use File::Basename qw / fileparse dirname /;
use File::Temp qw/ tempfile tempdir /;
use IO::File();

#Gtk2 and Gtk2::ImageView
use Gtk2 '-init';
use Gtk2::Gdk::Keysyms;
use Gtk2::Pango;
use Gtk2::ImageView;

#Gettext and filename parsing
use POSIX qw/ setlocale strftime /;
use Locale::gettext();

#handle upload responses properly
use HTTP::Status;

#load and save settings
use XML::Simple;

#DBus message system
#~ use Net::DBus qw/ dbus_string /;

#timing issues
use Time::HiRes qw/ time usleep /;

#Locate directory of original perl script
use FindBin '$Bin';

#stringified perl data structures, suitable for both printing and eval
use Data::Dumper;

#--------------------------------------

#define constants
#--------------------------------------
use constant TRUE                	=> 1;
use constant FALSE               	=> 0;
use constant MAX_ERROR 				=> 5;
use constant REV                	=> "Rev.579";
use constant SHUTTER_NAME         	=> "Shutter";
use constant SHUTTER_VERSION      	=> "v0.80.1";

#--------------------------------------

#configure path settings
#--------------------------------------
my $shutter_root = undef;
if($ENV{PAR_TEMP}){
	$shutter_root = $ENV{PAR_TEMP}."/inc";
}else{
	$Bin =~ m/(.*)\//;
	$shutter_root = $1;
}

my $shutter_path = $Bin . "/shutter";
$ENV{'SHUTTER_ROOT'} = $shutter_root;    #used by some plugins

#--------------------------------------

#load modules at custom path at runtime
#--------------------------------------
require lib;
import lib "$shutter_root/share/shutter/resources/modules";

#Sort::Naturally - sort lexically, but sort numeral parts numerically
require Sort::Naturally;

#proc (Thanks to Michael Schilli)
require Proc::Simple;

#File::Which - Portable implementation of the `which' utility
require File::Which;

#Perl extension for recursively copying files and directories (Thanks to Daniel Muey)
require File::Copy::Recursive;

#Find programs to open a file by mimetype
require File::MimeInfo::Applications;

#Find your home and other directories, on any platform
require File::HomeDir::Unix;
require File::HomeDir;
$ENV{ 'HOME' } = File::HomeDir->my_home;

#--------------------------------------

#check optional components
#--------------------------------------
my $gnome_web_photo = TRUE;
my $goocanvas       = TRUE;
&fct_init_depend;

#--------------------------------------

#load shutter's modules
#--------------------------------------

#app classes
require Shutter::App::Common;
require Shutter::App::SimpleDialogs;
require Shutter::App::HelperFunctions;
require Shutter::App::Menu;
require Shutter::App::Toolbar;

#pixbuf operations
require Shutter::Pixbuf::Save;
require Shutter::Pixbuf::Thumbnail;

#drawing classes
if($goocanvas){
	require Shutter::Draw::DrawingTool;
}

#screenshot classes
require Shutter::Screenshot::SelectorAdvanced;
require Shutter::Screenshot::SelectorSimple;
require Shutter::Screenshot::Workspace;
require Shutter::Screenshot::Web;
require Shutter::Screenshot::Window;

#upload classes
require Shutter::Upload::ImageBanana;
require Shutter::Upload::UbuntuPics;
require Shutter::Upload::ImageShack;
require Shutter::Upload::FTP;

#--------------------------------------

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

#create app objects
#--------------------------------------
my $shutter_common 	= Shutter::App::Common->new($shutter_root);
$shutter_common->set_mainwindow($window);
my $shutter_hfunct 	= Shutter::App::HelperFunctions->new($shutter_common);
my $shutter_menu   	= Shutter::App::Menu->new($shutter_common);
my $shutter_tool   	= Shutter::App::Toolbar->new($shutter_common);
my $shutter_dialog 	= Shutter::App::SimpleDialogs->new($window);
my $shutter_pix 	= Shutter::Pixbuf::Save->new($shutter_common);
my $shutter_thumb 	= Shutter::Pixbuf::Thumbnail->new($shutter_common);

#--------------------------------------

#Clipboard
my $clipboard = Gtk2::Clipboard->get( Gtk2::Gdk->SELECTION_CLIPBOARD );

#Gettext
my $d = $shutter_common->get_gettext;

#Page Setup
my $pagesetup = undef;

#Icontheme
my $icontheme = $shutter_common->get_theme;

#Tooltips
my $tooltips = $shutter_common->get_tooltips;

#Gtk2::ImageView and Selector for advanced selection tool
my $view 		= Gtk2::ImageView->new;
my $nav 		= Gtk2::ImageView::Nav::new($view);
my $selector 	= Gtk2::ImageView::Tool::Selector->new($view);
my $dragger 	= Gtk2::ImageView::Tool::Dragger->new($view);
$view->set_interpolation ('tiles');
$view->set_tool($selector);

#Gtk2::ImageView and Selector for drawing tool
my $view_d;
my $selector_d;
my $dragger_d;
if($goocanvas){
	$view_d     = Gtk2::ImageView->new;
	$selector_d = Gtk2::ImageView::Tool::Selector->new($view_d);
	$dragger_d 	= Gtk2::ImageView::Tool::Dragger->new($view_d);
	$view_d->set_interpolation ('tiles');	
	$view_d->set_tool($selector_d);
}

#data structures
#--------------------------------------
my %plugins;        #hash to store plugin infos
my %accounts;       #hash to store account infos
my %settings;       #hash to store settings
&fct_init;
&fct_init_framework_versions;
&fct_load_accounts;

#--------------------------------------

#signal-handler
$SIG{RTMIN}  = sub { &evt_take_screenshot( 'global_keybinding', 'select' ) };
$SIG{USR1}   = sub { &evt_take_screenshot( 'global_keybinding', 'raw' ) };
$SIG{USR2}   = sub { &evt_take_screenshot( 'global_keybinding', 'window' ) };
$SIG{RTMAX}  = sub { &evt_take_screenshot( 'global_keybinding', 'section' ) };

#shutdown Shutter carefully when INT or TERM are detected
# => save settings
$SIG{INT}    = sub { &evt_delete_window( '', 'quit' ) };
$SIG{TERM}   = sub { &evt_delete_window( '', 'quit' ) };

#hash of screenshots during session
my %session_screens;
my %session_start_screen;

#main window gui
#--------------------------------------
$window->set_title(SHUTTER_NAME);
$window->set_default_icon_from_file( "$shutter_root/share/pixmaps/shutter.svg" );
$window->signal_connect( 'delete-event' => \&evt_delete_window );
$window->set_border_width(0);
$window->set_resizable(TRUE);
$window->set_focus_on_map(TRUE);
$window->set_default_size( -1, 500 );

#TRAY ICON
my $icon                 = undef;
my $current_profile_indx = 0;
my $is_hidden            = TRUE;

#SESSION NOTEBOOK
my $notebook = Gtk2::Notebook->new;
$notebook = &fct_create_session_notebook;

#STATUSBAR
my $status1 = Gtk2::Statusbar->new;
$status1->set_size_request( 200, -1 );
my $status2 = Gtk2::Statusbar->new;

#arrange settings in notebook
my $notebook_settings = Gtk2::Notebook->new;
my $settings_dialog   = Gtk2::Dialog->new(
	SHUTTER_NAME . " - " . $d->get("Preferences"),
	$window,
	[qw/modal destroy-with-parent/],
	'gtk-close' => 'close'
);
$settings_dialog->set_has_separator(FALSE);

my $vbox = Gtk2::VBox->new( FALSE, 0 );
$window->add($vbox);

#attach signal handlers to subroutines and pack menu
#--------------------------------------
$vbox->pack_start( $shutter_menu->create_menu, FALSE, TRUE, 0 );

$shutter_menu->{_menuitem_open}->signal_connect( 'activate', \&evt_open, 'menu_open' );

#recent manager and menu entry
my $rmanager = Gtk2::RecentManager->new;
$shutter_menu->{_menu_recent} = Gtk2::RecentChooserMenu->new_for_manager($rmanager); 
$shutter_menu->{_menu_recent}->set_sort_type('mru');
$shutter_menu->{_menu_recent}->set_local_only (TRUE);
my $recentfilter = Gtk2::RecentFilter->new;
$recentfilter->add_pixbuf_formats;
$shutter_menu->{_menu_recent}->add_filter ($recentfilter);
$shutter_menu->{_menu_recent}->signal_connect('item-activated' => \&evt_open);	
$shutter_menu->{_menuitem_recent}->set_submenu($shutter_menu->{_menu_recent});	

$shutter_menu->{_menuitem_selection}->signal_connect( 'activate', \&evt_take_screenshot, 'select' );
$shutter_menu->{_menuitem_full}->signal_connect( 'activate', \&evt_take_screenshot, 'raw' );
$shutter_menu->{_menuitem_window}->signal_connect( 'activate', \&evt_take_screenshot, 'window' );
$shutter_menu->{_menuitem_section}->signal_connect( 'activate', \&evt_take_screenshot, 'section' );

#gnome web photo is optional, don't enable it when gnome-web-photo is not in PATH
if($gnome_web_photo){
	$shutter_menu->{_menuitem_web}->set_sensitive(TRUE);
	$shutter_menu->{_menuitem_web}->signal_connect( 'activate', \&evt_take_screenshot, 'web' );
}else{
	$shutter_menu->{_menuitem_web}->set_sensitive(FALSE);	
}

$shutter_menu->{_menuitem_save_as}->signal_connect( 'activate', \&evt_save_as, 'menu_save_as' );
$shutter_menu->{_menuitem_print}->signal_connect( 'activate', \&fct_print, 'menu_print' );
$shutter_menu->{_menuitem_pagesetup}->signal_connect( 'activate', \&evt_page_setup, 'menu_pagesetup' );
$shutter_menu->{_menuitem_close}->signal_connect( 'activate', sub { &fct_remove(undef); }, 'menu_close' );
$shutter_menu->{_menuitem_close_all}->signal_connect( 'activate', sub { &fct_remove_all(); }, 'menu_close_all' );
$shutter_menu->{_menuitem_quit}->signal_connect( 'activate', \&evt_delete_window, 'quit' );

$shutter_menu->{_menuitem_copy}->signal_connect( 'activate', \&fct_clipboard, 'image' );
$shutter_menu->{_menuitem_copy_filename}->signal_connect( 'activate', \&fct_clipboard, 'text' );
$shutter_menu->{_menuitem_trash}->signal_connect( 'activate', \&fct_delete );
$shutter_menu->{_menuitem_select_all}->signal_connect( 'activate', \&fct_select_all );
$shutter_menu->{_menuitem_settings}->signal_connect( 'activate', \&evt_show_settings, 'exp_settings_menu' );

$shutter_menu->{_menuitem_zoom_in}->signal_connect( 'activate', \&fct_zoom_in );
$shutter_menu->{_menuitem_zoom_out}->signal_connect( 'activate', \&fct_zoom_out );
$shutter_menu->{_menuitem_zoom_100}->signal_connect( 'activate', \&fct_zoom_100 );
$shutter_menu->{_menuitem_zoom_best}->signal_connect( 'activate', \&fct_zoom_best );
$shutter_menu->{_menuitem_fullscreen}->signal_connect( 'toggled', \&fct_fullscreen );

$shutter_menu->{_menu_actions}->signal_connect( 'focus', sub { $shutter_menu->{_menuitem_reopen}->set_submenu(&fct_ret_program_menu); });
$shutter_menu->{_menuitem_rename}->signal_connect( 'activate', \&fct_rename );
$shutter_menu->{_menuitem_upload}->signal_connect( 'activate', \&fct_upload );
$shutter_menu->{_menuitem_draw}->signal_connect( 'activate', \&fct_draw );
$shutter_menu->{_menuitem_plugin}->signal_connect( 'activate', \&fct_plugin );

$shutter_menu->{_menuitem_back}->signal_connect( 'activate' => sub {
		$notebook->prev_page;
	}
);
$shutter_menu->{_menuitem_forward}->signal_connect( 'activate' => sub{
		$notebook->next_page;
	}
);
$shutter_menu->{_menuitem_first}->signal_connect( 'activate' => sub {
		$notebook->set_current_page(0);
	}
);
$shutter_menu->{_menuitem_last}->signal_connect( 'activate' => sub {
		$notebook->set_current_page( $notebook->get_n_pages - 1 );
	}
);
	
$shutter_menu->{_menuitem_question}->signal_connect( 'activate', \&evt_question, $window );
$shutter_menu->{_menuitem_translate}->signal_connect( 'activate', \&evt_translate, $window );
$shutter_menu->{_menuitem_bug}->signal_connect( 'activate', \&evt_bug, $window );
$shutter_menu->{_menuitem_about}->signal_connect( 'activate', \&evt_about, $window );

#--------------------------------------

#trayicon
#--------------------------------------
#command line param set to disable tray icon?
unless ( $shutter_common->get_disable_systray ) {

	#do this when idle
	Glib::Idle->add (
	sub{
		
		if ( Gtk2->CHECK_VERSION( 2, 10, 0 ) ) {
			$icon = Gtk2::StatusIcon->new();
			
			$icon->set_from_file("$shutter_root/share/pixmaps/shutter.svg");
			$icon->set_visible(1);
			$icon->signal_connect(
				'popup-menu' => sub { &evt_show_systray_statusicon; },
				$icon
			);
			$icon->signal_connect(
				'activate' => sub {
					&evt_activate_systray_statusicon;
					$icon;
				},
				$icon
			);
			$icon->set_tooltip( SHUTTER_NAME . " " . SHUTTER_VERSION );
		} else {
			require Gtk2::TrayIcon;
			$icon = Gtk2::Image->new_from_pixbuf( Gtk2::Gdk::Pixbuf->new_from_file_at_size( "$shutter_root/share/pixmaps/shutter.svg", 24, 24 ) );
			
			my $eventbox = Gtk2::EventBox->new;
			$eventbox->add($icon);
			
			my $tray = Gtk2::TrayIcon->new('shutter TrayIcon');
			$tray->add($eventbox);
			$tooltips->set_tip( $tray, SHUTTER_NAME . " " . SHUTTER_VERSION );
			$eventbox->signal_connect( 'button_release_event', \&evt_show_systray );
			$tray->show_all;
		}
		
		return FALSE;
	});
}

#--------------------------------------

#settings
#--------------------------------------

my $vbox_settings       = Gtk2::VBox->new( FALSE, 12 );
my $hbox_settings       = Gtk2::HBox->new( FALSE, 12 );
my $vbox_basic          = Gtk2::VBox->new( FALSE, 12 );
my $vbox_extras         = Gtk2::VBox->new( FALSE, 12 );
my $vbox_behavior       = Gtk2::VBox->new( FALSE, 12 );
my $vbox_accounts       = Gtk2::VBox->new( FALSE, 12 );
my $file_vbox           = Gtk2::VBox->new( FALSE, 0 );
my $save_vbox           = Gtk2::VBox->new( FALSE, 0 );
my $behavior_vbox       = Gtk2::VBox->new( FALSE, 0 );
my $behavior_hbox1      = Gtk2::HBox->new( FALSE, 0 );
my $behavior_hbox2      = Gtk2::HBox->new( FALSE, 0 );
my $behavior_hbox3      = Gtk2::HBox->new( FALSE, 0 );
my $keybinding_vbox     = Gtk2::VBox->new( FALSE, 0 );
my $keybinding_mode_box = Gtk2::HBox->new( TRUE,  0 );
my $actions_vbox        = Gtk2::VBox->new( FALSE, 0 );
my $capture_vbox        = Gtk2::VBox->new( FALSE, 0 );
my $effects_vbox        = Gtk2::VBox->new( FALSE, 0 );
my $accounts_hbox       = Gtk2::HBox->new( FALSE, 0 );
my $accounts_vbox       = Gtk2::VBox->new( FALSE, 0 );
my $ftp_hbox1           = Gtk2::HBox->new( FALSE, 0 );
my $ftp_hbox2           = Gtk2::HBox->new( FALSE, 0 );
my $ftp_hbox3           = Gtk2::HBox->new( FALSE, 0 );
my $ftp_hbox4           = Gtk2::HBox->new( FALSE, 0 );
my $ftp_vbox            = Gtk2::VBox->new( FALSE, 0 );
my $profiles_box        = Gtk2::HBox->new( FALSE, 0 );
my $scale_box           = Gtk2::HBox->new( FALSE, 0 );
my $delay_box           = Gtk2::HBox->new( FALSE, 0 );
my $delay_box2          = Gtk2::HBox->new( FALSE, 0 );
my $thumbnail_box       = Gtk2::HBox->new( FALSE, 0 );
my $thumbnail_box2      = Gtk2::HBox->new( FALSE, 0 );
my $filename_box        = Gtk2::HBox->new( FALSE, 0 );
my $progname_box        = Gtk2::HBox->new( FALSE, 0 );
my $progname_box2       = Gtk2::HBox->new( FALSE, 0 );
my $im_colors_box       = Gtk2::HBox->new( FALSE, 0 );
my $im_colors_box2      = Gtk2::HBox->new( FALSE, 0 );
my $filetype_box        = Gtk2::HBox->new( FALSE, 0 );
my $saveDir_box         = Gtk2::HBox->new( FALSE, 0 );
my $key_box             = Gtk2::HBox->new( FALSE, 0 );
my $key_box2            = Gtk2::HBox->new( FALSE, 0 );
my $key_sel_box         = Gtk2::HBox->new( FALSE, 0 );
my $key_sel_box2        = Gtk2::HBox->new( FALSE, 0 );
my $border_box          = Gtk2::HBox->new( FALSE, 0 );
my $cursor_box          = Gtk2::HBox->new( FALSE, 0 );

my $profiles_label = Gtk2::Label->new( $d->get("Profile") . ":" );

#load settings
#--------------------------------------
my $settings_xml = &fct_load_settings( "start" );

#load last profile
if ( defined $settings_xml->{'general'}->{'last_profile'} ) {
	if ( $settings_xml->{'general'}->{'last_profile'} != -1 ) {
		$settings_xml = &fct_load_settings("start", $settings_xml->{'general'}->{'last_profile_name'} );
	}
}

#--------------------------------------

#check plugins
#--------------------------------------
&fct_check_installed_plugins;

#--------------------------------------

#attach signal handlers to subroutines and pack toolbar
#--------------------------------------
#~ my $handlebox = Gtk2::HandleBox->new;
#~ $handlebox->add( $shutter_tool->create_toolbar );
#~ $vbox->pack_start( $handlebox, FALSE, TRUE, 0 );

$vbox->pack_start( $shutter_tool->create_toolbar, FALSE, TRUE, 0 );

my ( $tool_advanced, $tool_simple ) = undef;
my $zoom_active = undef;
my ( $zoom_size1, $zoom_size2, $zoom_size3 ) = undef;
$shutter_tool->{_select}->set_menu(&fct_ret_sel_menu);
$shutter_tool->{_select}->signal_connect( 'clicked' => \&evt_take_screenshot, 'select' );

my $current_monitor_active = undef;
$shutter_tool->{_full}->signal_connect( 'clicked' => \&evt_take_screenshot, 'raw' );

#do this when idle
Glib::Idle->add (
sub{
	$shutter_tool->{_full}->set_menu( &fct_ret_workspace_menu(TRUE) );	
	return FALSE;
});	

$shutter_tool->{_full}->signal_connect( 'show-menu' => sub { &fct_ret_workspace_menu(FALSE) } );

$shutter_tool->{_window}->signal_connect( 'clicked' => \&evt_take_screenshot, 'window' );

#do this when idle
Glib::Idle->add (
sub{
	$shutter_tool->{_window}->set_menu(&fct_ret_window_menu);	
	return FALSE;
});	

$shutter_tool->{_window}->signal_connect( 'show-menu' => \&fct_ret_window_menu );

$shutter_tool->{_section}->signal_connect( 'clicked' => \&evt_take_screenshot, 'section' );

#gnome web photo is optional, don't enable it when gnome-web-photo is not in PATH
if ( $gnome_web_photo ) {
	$tooltips->set_tip( $shutter_tool->{_web}, $d->get("Take a screenshot of a website") );
	$shutter_tool->{_web}->set_arrow_tooltip( Gtk2::Tooltips->new, $d->get("The timeout in seconds, or 0 to disable timeout"), 'arrow' );
	$shutter_tool->{_web}->set_sensitive(TRUE);
	$shutter_tool->{_web}->signal_connect( 'clicked' => \&evt_take_screenshot, 'web' );
	$shutter_tool->{_web}->set_menu(&fct_ret_web_menu);
	$shutter_tool->{_web}->signal_connect( 'show-menu' => \&fct_ret_web_menu );
} else {
	$tooltips->set_tip( $shutter_tool->{_web}, $d->get("gnome-web-photo needs to be installed for this feature") );
	$shutter_tool->{_web}->set_arrow_tooltip( $tooltips, $d->get("gnome-web-photo needs to be installed for this feature"), 'arrow' );
	$shutter_tool->{_web}->set_sensitive(FALSE);
}

$shutter_tool->{_edit}->signal_connect( 'clicked' => \&fct_draw );
$shutter_tool->{_edit}->set_sensitive(FALSE);
	
$shutter_tool->{_upload}->signal_connect( 'clicked' => \&fct_upload );
$shutter_tool->{_upload}->set_sensitive(FALSE);

#--------------------------------------

#handle profiles
#--------------------------------------
my $combobox_settings_profiles = Gtk2::ComboBox->new_text;
my @current_profiles;
my $current_index = 0;
foreach ( sort glob("$ENV{'HOME'}/.shutter/profiles/*.xml") ) {
	utf8::decode $_;
	next if $_ =~ /\_accounts.xml/;    #accounts file - we are looking for "real" profiles
	$_ =~ /.*\/(.*)\.xml/;            #get profiles name
	my $last_profile_name = $1;
	$combobox_settings_profiles->append_text($last_profile_name);

	#set active profile
	if ( exists $settings_xml->{'general'}->{'last_profile_name'} ) {
		if ( $settings_xml->{'general'}->{'last_profile_name'} eq $last_profile_name ) {
			$combobox_settings_profiles->set_active($current_index);
			$current_profile_indx = $current_index;
		}
	}

	push( @current_profiles, $last_profile_name );
	$current_index++;
}
$tooltips->set_tip( $combobox_settings_profiles, $d->get("Choose a profile") );

#set 0 if nothing is selected yet
if ( !$combobox_settings_profiles->get_active_text ) {
	$combobox_settings_profiles->set_active(0);
	$current_profile_indx = 0;
}

#populate quick selector as well
&fct_update_quick_profile_selector($combobox_settings_profiles, \@current_profiles);

my $button_profile_save = Gtk2::Button->new;
$button_profile_save->signal_connect(
	'clicked' => sub {
		my $widget = shift;
		&evt_save_profile( $widget, $combobox_settings_profiles, \@current_profiles );
	}
);
$button_profile_save->set_image( Gtk2::Image->new_from_stock( 'gtk-save', 'button' ) );
$tooltips->set_tip( $button_profile_save, $d->get("Save configuration as profile") );

my $button_profile_delete = Gtk2::Button->new;
$button_profile_delete->signal_connect(
	'clicked' => sub {
		my $widget = shift;
		&evt_delete_profile( $widget, $combobox_settings_profiles, \@current_profiles );
	}
);
$button_profile_delete->set_image( Gtk2::Image->new_from_stock( 'gtk-delete', 'button' ) );
$tooltips->set_tip( $button_profile_delete, $d->get("Delete profile") );
my $button_profile_apply = Gtk2::Button->new;
$button_profile_apply->signal_connect(
	'clicked' => sub {
		my $widget = shift;
		&evt_apply_profile( $widget, $combobox_settings_profiles, \@current_profiles );
	}
);
$button_profile_apply->set_image( Gtk2::Image->new_from_stock( 'gtk-apply', 'button' ) );
$tooltips->set_tip( $button_profile_apply, $d->get("Set profile for current configuration") );

#--------------------------------------


#frames and label for settings dialog
#--------------------------------------
my $file_frame_label = Gtk2::Label->new;
$file_frame_label->set_markup( "<b>" . $d->get("Image format") . "</b>" );

my $file_frame = Gtk2::Frame->new();
$file_frame->set_label_widget($file_frame_label);
$file_frame->set_shadow_type('none');

my $save_frame_label = Gtk2::Label->new;
$save_frame_label->set_markup( "<b>" . $d->get("Save") . "</b>" );

my $save_frame = Gtk2::Frame->new();
$save_frame->set_label_widget($save_frame_label);
$save_frame->set_shadow_type('none');

my $behavior_frame_label = Gtk2::Label->new;
$behavior_frame_label->set_markup( "<b>" . $d->get("Behavior") . "</b>" );

my $behavior_frame = Gtk2::Frame->new();
$behavior_frame->set_label_widget($behavior_frame_label);
$behavior_frame->set_shadow_type('none');

my $keybinding_frame_label = Gtk2::Label->new;
$keybinding_frame_label->set_markup( "<b>" . $d->get("Gnome-Keybinding") . "</b>" );

my $keybinding_frame = Gtk2::Frame->new();
$keybinding_frame->set_label_widget($keybinding_frame_label);
$keybinding_frame->set_shadow_type('none');

my $actions_frame_label = Gtk2::Label->new;
$actions_frame_label->set_markup( "<b>" . $d->get("Actions") . "</b>" );

my $actions_frame = Gtk2::Frame->new();
$actions_frame->set_label_widget($actions_frame_label);
$actions_frame->set_shadow_type('none');

my $capture_frame_label = Gtk2::Label->new;
$capture_frame_label->set_markup( "<b>" . $d->get("Capture") . "</b>" );

my $capture_frame = Gtk2::Frame->new();
$capture_frame->set_label_widget($capture_frame_label);
$capture_frame->set_shadow_type('none');

my $accounts_frame_label = Gtk2::Label->new;
$accounts_frame_label->set_markup( "<b>" . $d->get("Accounts") . "</b>" );

my $accounts_frame = Gtk2::Frame->new();
$accounts_frame->set_label_widget($accounts_frame_label);
$accounts_frame->set_shadow_type('none');

my $ftp_frame_label = Gtk2::Label->new;
$ftp_frame_label->set_markup( "<b>" . $d->get("File Transfer Protocol (FTP)") . "</b>" );

my $ftp_frame = Gtk2::Frame->new();
$ftp_frame->set_label_widget($ftp_frame_label);
$ftp_frame->set_shadow_type('none');

#delay
#--------------------------------------
my $delay_label = Gtk2::Label->new( $d->get("Delay") . ":" );
my $delay = Gtk2::HScale->new_with_range( 1, 10, 1 );
$delay->signal_connect(
	'value-changed' => \&evt_value_changed,
	'delay_changed'
);
$delay->set_value_pos('right');

if ( defined $settings_xml->{'general'}->{'delay'} ) {
	$delay->set_value( $settings_xml->{'general'}->{'delay'} );
} else {
	$delay->set_value(0);
}
my $delay_active = Gtk2::CheckButton->new;
$delay_active->set_active(TRUE);
$delay_active->signal_connect(
	'toggled' => \&evt_value_changed,
	'delay_toggled'
);

if ( defined $settings_xml->{'general'}->{'delay_active'} ) {
	$delay_active->set_active( $settings_xml->{'general'}->{'delay_active'} );
} else {
	$delay_active->set_active(FALSE);
}
$tooltips->set_tip( $delay,        $d->get("Wait n seconds before taking a screenshot") );
$tooltips->set_tip( $delay_active, $d->get("Wait n seconds before taking a screenshot") );
$tooltips->set_tip( $delay_label,  $d->get("Wait n seconds before taking a screenshot") );
$delay_box->pack_start( $delay_label, FALSE, TRUE, 12 );
$delay_box2->pack_start( $delay_active, FALSE, FALSE, 0 );
$delay_box2->pack_start( $delay,        TRUE,  TRUE,  0 );
$delay_box->pack_start( $delay_box2, TRUE, TRUE, 0 );

#end - delay
#--------------------------------------

#thumbnail
#--------------------------------------
my $thumbnail_label = Gtk2::Label->new( $d->get("Thumbnail") . ":" );
my $thumbnail = Gtk2::HScale->new_with_range( 1, 100, 1 );
$thumbnail->signal_connect(
	'value-changed' => \&evt_value_changed,
	'thumbnail_changed'
);
$thumbnail->set_value_pos('right');

if ( defined $settings_xml->{'general'}->{'thumbnail'} ) {
	$thumbnail->set_value( $settings_xml->{'general'}->{'thumbnail'} );
} else {
	$thumbnail->set_value(50);
}
my $thumbnail_active = Gtk2::CheckButton->new;
$thumbnail_active->set_active(TRUE);
$thumbnail_active->signal_connect(
	'toggled' => \&evt_value_changed,
	'thumbnail_toggled'
);

if ( defined $settings_xml->{'general'}->{'thumbnail_active'} ) {
	$thumbnail_active->set_active( $settings_xml->{'general'}->{'thumbnail_active'} );
} else {
	$thumbnail_active->set_active(FALSE);
}
$tooltips->set_tip( $thumbnail,
	$d->get("Generate thumbnail too.\nselect the percentage of the original size for the thumbnail to be") );
$tooltips->set_tip( $thumbnail_active,
	$d->get("Generate thumbnail too.\nselect the percentage of the original size for the thumbnail to be") );
$tooltips->set_tip( $thumbnail_label,
	$d->get("Generate thumbnail too.\nselect the percentage of the original size for the thumbnail to be") );
$thumbnail_box->pack_start( $thumbnail_label, FALSE, TRUE, 12 );
$thumbnail_box2->pack_start( $thumbnail_active, FALSE, FALSE, 0 );
$thumbnail_box2->pack_start( $thumbnail,        TRUE,  TRUE,  0 );
$thumbnail_box->pack_start( $thumbnail_box2, TRUE, TRUE, 0 );

#end - thumbnail
#--------------------------------------

#filename
#--------------------------------------
my $filename = Gtk2::Entry->new;
if ( defined $settings_xml->{'general'}->{'filename'} ) {
	$filename->set_text( $settings_xml->{'general'}->{'filename'} );
} else {
	$filename->set_text("screenshot_\%NNN");
}

#do some input validation
#here are all invalid char codes
my @invalid_codes = (47,92,63,42,58,124,34,60,62,44,59,35,38);
my $filename_hint = Gtk2::Label->new;
$filename->signal_connect('key-press-event' => sub {
	my $filename 	= shift;
	my $event 		= shift;
	
	my $input = Gtk2::Gdk->keyval_to_unicode ($event->keyval); 
	
	#invalid input
	#~ print $input."\n";
	if(grep($input == $_, @invalid_codes)){
		my $char = chr($input);
		$char = '&amp;' if $char eq '&';
		$filename_hint->set_markup("<span size='small'>" . 
										sprintf($d->get("Reserved character %s is not allowed to be in a filename.") , "'".$char."'") 
										. "</span>");	
		return TRUE;
	}else{
		#clear possible message when valid char is entered
		$filename_hint->set_markup("<span size='small'></span>");						
		return FALSE;
	}
});

my $filename_label = Gtk2::Label->new( $d->get("Filename") . ":" );
$tooltips->set_tip(
	$filename,
	$d->get(
		"There are several wild-cards available, like\n%Y = year\n%m = month\n%d = day\n%T = time\n\$w = width\n\$h = height\n%NN = counter"
	)
);
$tooltips->set_tip(
	$filename_label,
	$d->get(
		"There are several wild-cards available, like\n%Y = year\n%m = month\n%d = day\n%T = time\n\$w = width\n\$h = height\n%NN = counter"
	)
);
$filename_box->pack_start( $filename_label, FALSE, TRUE, 12 );
$filename_box->pack_start( $filename,       TRUE,  TRUE, 0 );

#end - filename
#--------------------------------------


#filetype and scale
#--------------------------------------
my $scale = Gtk2::HScale->new_with_range( 0, 9, 1 );
my $scale_label = Gtk2::Label->new( $d->get("Compression") . ":" );
$scale->set_value_pos('right');
$scale->set_value(1);

#we don't need a default here because it will be set through signal handling (filetype)
if ( defined $settings_xml->{'general'}->{'quality'} ) {
	$scale->set_value( $settings_xml->{'general'}->{'quality'} );
}

$tooltips->set_tip( $scale,
	$d->get("Quality/Compression:\nHigh value means high size / high compression\n(depending on file format chosen)") );
$tooltips->set_tip( $scale_label,
	$d->get("Quality/Compression:\nHigh value means high size / high compression\n(depending on file format chosen)") );
$scale_box->pack_start( $scale_label, FALSE, TRUE, 12 );
$scale_box->pack_start( $scale,       TRUE,  TRUE, 0 );

#add compatile, writeable file types
my $combobox_type = Gtk2::ComboBox->new_text;
my ( $int_png, $int_jpeg, $int_bmp ) = ( 0, 0, 0 );
my $format_counter = 0;

foreach ( Gtk2::Gdk::Pixbuf->get_formats ) {
	if (   $_->{name} eq "jpeg"
		|| $_->{name} eq "png"
		|| $_->{name} eq "bmp" )
	{
		$combobox_type->append_text( $_->{name} . " - " . $_->{description} );
		
		#a little ugly here, maybe the values are in alternative order on several machine...
		#just remember the number when appending, so we can set png as default for example
		if ( $_->{name} eq "jpeg" ) {
			$int_jpeg = $format_counter;
		} elsif ( $_->{name} eq "png" ) {
			$int_png = $format_counter;
		} elsif ( $_->{name} eq "bmp" ) {
			$int_bmp = $format_counter;
		}

		$format_counter++;

	}
}
$combobox_type->signal_connect( 'changed' => \&evt_value_changed, 'type_changed' );

if ( defined $settings_xml->{'general'}->{'filetype'} ) {
	
	#migration from gscrot to shutter
	#maybe we can drop this in future releases
	# 0 := jpeg
	# 1 := png
	unless(defined $settings_xml->{'general'}->{'app_version'}){
		if($settings_xml->{'general'}->{'filetype'} == 0){
			$combobox_type->set_active($int_jpeg);			
		}elsif($settings_xml->{'general'}->{'filetype'} == 1){
			$combobox_type->set_active($int_png);		
		}
	
	#shutter
	}else{
		$combobox_type->set_active($settings_xml->{'general'}->{'filetype'});	
	}
	
	#set saved quality/compression value if there is one
	if(defined $settings_xml->{'general'}->{'quality'}){
		$scale->set_value( $settings_xml->{'general'}->{'quality'} );		
	} 

} else {

	#we will try to set a default value in this order
	foreach ( @{ [ $int_png, $int_jpeg, $int_bmp ] } ) {
		if ( $_ > 0 ) {
			$combobox_type->set_active( $_ );
			last;
		}
	}

}

my $filetype_label = Gtk2::Label->new( $d->get("Image format") . ":" );
$tooltips->set_tip( $combobox_type,  $d->get("Select a file format") );
$tooltips->set_tip( $filetype_label, $d->get("Select a file format") );
$filetype_box->pack_start( $filetype_label, FALSE, TRUE, 12 );
$filetype_box->pack_start( $combobox_type,  TRUE,  TRUE, 0 );

#end - filetype and scale
#--------------------------------------

#saveDir
#--------------------------------------
my $saveDir_label = Gtk2::Label->new( $d->get("Directory") . ":" );
my $saveDir_button = Gtk2::FileChooserButton->new( "Shutter - " . $d->get("Choose folder"), 'select-folder' );
if ( defined $settings_xml->{'general'}->{'folder'} ) {
	$saveDir_button->set_filename( $settings_xml->{'general'}->{'folder'} );
} else {
	$saveDir_button->set_filename( File::HomeDir->my_pictures );
}

$tooltips->set_tip( $saveDir_button, $d->get("Your screenshots will be saved\nto this directory") );
$tooltips->set_tip( $saveDir_label,  $d->get("Your screenshots will be saved\nto this directory") );
$saveDir_box->pack_start( $saveDir_label,  FALSE, TRUE, 12 );
$saveDir_box->pack_start( $saveDir_button, TRUE,  TRUE, 0 );

#end - saveDir
#--------------------------------------

#behavior
#--------------------------------------
my $capture_key = Gtk2::Entry->new;
if ( defined $settings_xml->{'general'}->{'capture_key'} ) {
	$capture_key->set_text( $settings_xml->{'general'}->{'capture_key'} );
} else {
	$capture_key->set_text("Print");
}
my $capture_label = Gtk2::Label->new( $d->get("Capture") . ":" );
$tooltips->set_tip(
	$capture_key,
	$d->get(
		"Configure global keybinding for capture\nThe format looks like \"<Control>a\" or \"<Shift><Alt>F1\". The parser is fairly liberal and allows lower or upper case, and also abbreviations such as \"<Ctl>\" and \"<Ctrl>\". If you set the option to the special string \"disabled\", then there will be no keybinding for this action. "
	)
);
$tooltips->set_tip(
	$capture_label,
	$d->get(
		"Configure global keybinding for capture\nThe format looks like \"<Control>a\" or \"<Shift><Alt>F1\". The parser is fairly liberal and allows lower or upper case, and also abbreviations such as \"<Ctl>\" and \"<Ctrl>\". If you set the option to the special string \"disabled\", then there will be no keybinding for this action. "
	)
);
my $capture_sel_key = Gtk2::Entry->new;
if ( defined $settings_xml->{'general'}->{'capture_sel_key'} ) {
	$capture_sel_key->set_text( $settings_xml->{'general'}->{'capture_sel_key'} );
} else {
	$capture_sel_key->set_text("<Alt>Print");
}

my $capture_sel_label = Gtk2::Label->new( $d->get("Capture with selection") . ":" );
$tooltips->set_tip(
	$capture_sel_key,
	$d->get(
		"Configure global keybinding for capture with selection\nThe format looks like \"<Control>a\" or \"<Shift><Alt>F1\". The parser is fairly liberal and allows lower or upper case, and also abbreviations such as \"<Ctl>\" and \"<Ctrl>\". If you set the option to the special string \"disabled\", then there will be no keybinding for this action. "
	)
);
$tooltips->set_tip(
	$capture_sel_label,
	$d->get(
		"Configure global keybinding for capture with selection\nThe format looks like \"<Control>a\" or \"<Shift><Alt>F1\". The parser is fairly liberal and allows lower or upper case, and also abbreviations such as \"<Ctl>\" and \"<Ctrl>\". If you set the option to the special string \"disabled\", then there will be no keybinding for this action. "
	)
);

#keybinding_mode
my $combobox_keybinding_mode = Gtk2::ComboBox->new_text;
$combobox_keybinding_mode->insert_text( 0, $d->get("Selection") );
$combobox_keybinding_mode->insert_text( 1, $d->get("Window") );
$combobox_keybinding_mode->insert_text( 2, $d->get("Section") );

if ( defined $settings_xml->{'general'}->{'keybinding_mode'} ) {
	$combobox_keybinding_mode->set_active( $settings_xml->{'general'}->{'keybinding_mode'} );
} else {
	$combobox_keybinding_mode->set_active(1);
}
$tooltips->set_tip(
	$combobox_keybinding_mode,
	$d->get(
		"Configure global keybinding for capture with selection\nThe format looks like \"<Control>a\" or \"<Shift><Alt>F1\". The parser is fairly liberal and allows lower or upper case, and also abbreviations such as \"<Ctl>\" and \"<Ctrl>\". If you set the option to the special string \"disabled\", then there will be no keybinding for this action. "
	)
);
#~ $combobox_keybinding_mode->signal_connect(
	#~ 'changed' => \&evt_behavior_handle,
	#~ 'keybinding_sel_toggled'
#~ );

$keybinding_mode_box->pack_start( Gtk2::Label->new,          FALSE, FALSE, 0 );
$keybinding_mode_box->pack_start( $combobox_keybinding_mode, TRUE,  TRUE,  0 );

#keybindings
my $keybinding_active = Gtk2::CheckButton->new;
my $keybinding_sel_active = Gtk2::CheckButton->new;

$key_box->pack_start( $capture_label, FALSE, TRUE, 12 );
$key_box2->pack_start( $keybinding_active, FALSE, FALSE, 0 );
$key_box2->pack_start( $capture_key,       TRUE,  TRUE,  0 );
$key_box->pack_start( $key_box2, TRUE, TRUE, 0 );
$key_sel_box->pack_start( $capture_sel_label, FALSE, TRUE, 12 );
$key_sel_box2->pack_start( $keybinding_sel_active, FALSE, FALSE, 0 );
$key_sel_box2->pack_start( $capture_sel_key,       TRUE,  TRUE,  0 );
$key_sel_box->pack_start( $key_sel_box2, TRUE, TRUE, 0 );
$keybinding_active->set_active(TRUE);

#add signal handlers BEFORE settings are restored
#~ $capture_key->signal_connect(
	#~ 'focus-out-event' => sub { &evt_behavior_handle($capture_key, 'keybinding_toggled'); return FALSE; }
#~ );
#~ 
#~ $capture_sel_key->signal_connect(
	#~ 'focus-out-event' => sub { &evt_behavior_handle($capture_sel_key, 'keybinding_sel_toggled'); return FALSE; }
#~ );
#~ 
$keybinding_active->signal_connect(
	'toggled' => \&evt_behavior_handle,
	'keybinding_toggled'
);

$keybinding_sel_active->signal_connect(
	'toggled' => \&evt_behavior_handle,
	'keybinding_sel_toggled'
);

if ( defined $settings_xml->{'general'}->{'keybinding'} ) {
	$keybinding_active->set_active( $settings_xml->{'general'}->{'keybinding'} );
} else {
	$keybinding_active->set_active(FALSE);
}
$keybinding_sel_active->set_active(TRUE);
if ( defined $settings_xml->{'general'}->{'keybinding_sel'} ) {
	$keybinding_sel_active->set_active( $settings_xml->{'general'}->{'keybinding_sel'} );
} else {
	$keybinding_sel_active->set_active(FALSE);
}

my $hide_active           = Gtk2::CheckButton->new_with_label( $d->get("Autohide Shutter Window when taking a screenshot") );
my $autocopy_active       = Gtk2::CheckButton->new_with_label( $d->get("Automatically copy screenshot to clipboard") );
my $close_at_close_active = Gtk2::CheckButton->new_with_label( $d->get("Minimize to tray when closing main window") );

$behavior_hbox1->pack_start( $hide_active,           FALSE, TRUE, 12 );
$behavior_hbox2->pack_start( $autocopy_active,       FALSE, TRUE, 12 );
$behavior_hbox3->pack_start( $close_at_close_active, FALSE, TRUE, 12 );

if ( defined $settings_xml->{'general'}->{'autohide'} ) {
	$hide_active->set_active( $settings_xml->{'general'}->{'autohide'} );
} else {
	$hide_active->set_active(TRUE);
}

#add signal handlers after setting the saved / default values
#~ $hide_active->signal_connect(
	#~ 'toggled' => \&evt_behavior_handle,
	#~ 'hide_toggled'
#~ );

$tooltips->set_tip( $hide_active, $d->get("Autohide Shutter Window when taking a screenshot") );

if ( defined $settings_xml->{'general'}->{'autocopy'} ) {
	$autocopy_active->set_active( $settings_xml->{'general'}->{'autocopy'} );
} else {
	$autocopy_active->set_active(TRUE);
}

#add signal handlers after setting the saved / default values
#~ $autocopy_active->signal_connect(
	#~ 'toggled' => \&evt_behavior_handle,
	#~ 'autocopy_toggled'
#~ );

$tooltips->set_tip( $autocopy_active, $d->get("Automatically copy screenshot to clipboard") );

if ( defined $settings_xml->{'general'}->{'close_at_close'} ) {
	$close_at_close_active->set_active( $settings_xml->{'general'}->{'close_at_close'} );
} else {
	$close_at_close_active->set_active(TRUE);
}

#add signal handlers after setting the saved / default values
#~ $close_at_close_active->signal_connect(
	#~ 'toggled' => \&evt_behavior_handle,
	#~ 'close_at_close_toggled'
#~ );

$tooltips->set_tip( $close_at_close_active, $d->get("Minimize to tray when closing main window") );

#~ if ( defined $settings_xml->{'general'}->{'save_at_close'} ) {
	#~ $save_at_close_active->set_active( $settings_xml->{'general'}->{'save_at_close'} );
#~ } else {
	#~ $save_at_close_active->set_active(TRUE);
#~ }

#add signal handlers after setting the saved / default values
#~ $save_at_close_active->signal_connect(
	#~ 'toggled' => \&evt_behavior_handle,
	#~ 'save_at_close_toggled'
#~ );

#~ $tooltips->set_tip( $save_at_close_active, $d->get("Save settings automatically when exiting Shutter") );

#end - behavior
#--------------------------------------

#program
#--------------------------------------
my $model		= &fct_get_program_model;
my $progname	= Gtk2::ComboBox->new($model);

#add pixbuf renderer for icon
my $renderer_pix = Gtk2::CellRendererPixbuf->new;
$progname->pack_start( $renderer_pix, FALSE );
$progname->add_attribute( $renderer_pix, pixbuf => 0 );

#add text renderer for app name
my $renderer_text = Gtk2::CellRendererText->new;
$progname->pack_start( $renderer_text, FALSE );
$progname->add_attribute( $renderer_text, text => 1 );

#try to set the saved value
if ( defined $settings_xml->{'general'}->{'prog'} ) {
	$model->foreach( \&fct_iter_programs, $settings_xml->{'general'}->{'prog'} );
} else {
	$progname->set_active(0);
}

#nothing has been set
if ( $progname->get_active == -1 ) {
	$progname->set_active(0);
}

my $progname_active = Gtk2::CheckButton->new;
$progname_active->set_active(TRUE);
$progname_active->signal_connect(
	'toggled' => \&evt_value_changed,
	'progname_toggled'
);
if ( defined $settings_xml->{'general'}->{'prog_active'} ) {
	$progname_active->set_active( $settings_xml->{'general'}->{'prog_active'} );
} else {
	$progname_active->set_active(FALSE);
}
my $progname_label = Gtk2::Label->new( $d->get("Open with") . ":" );
$tooltips->set_tip( $progname,        $d->get("Open your screenshot\nwith this program after capturing") );
$tooltips->set_tip( $progname_active, $d->get("Open your screenshot\nwith this program after capturing") );
$tooltips->set_tip( $progname_label,  $d->get("Open your screenshot\nwith this program after capturing") );
$progname_box->pack_start( $progname_label, FALSE, TRUE, 12 );
$progname_box2->pack_start( $progname_active, FALSE, TRUE, 0 );
$progname_box2->pack_start( $progname, TRUE, TRUE, 0 );
$progname_box->pack_start( $progname_box2, TRUE, TRUE, 0 );

#end - program
#--------------------------------------

#im_colors
#--------------------------------------
my $combobox_im_colors = Gtk2::ComboBox->new_text;
$combobox_im_colors->insert_text( 0, $d->get("16 colors   - (4bit) ") );
$combobox_im_colors->insert_text( 1, $d->get("64 colors   - (6bit) ") );
$combobox_im_colors->insert_text( 2, $d->get("256 colors  - (8bit) ") );
$combobox_im_colors->signal_connect(
	'changed' => \&evt_value_changed,
	'im_colors_changed'
);

if ( defined $settings_xml->{'general'}->{'im_colors'} ) {
	$combobox_im_colors->set_active( $settings_xml->{'general'}->{'im_colors'} );
} else {
	$combobox_im_colors->set_active(2);
}

my $im_colors_active = Gtk2::CheckButton->new;
$im_colors_active->set_active(TRUE);
$im_colors_active->signal_connect(
	'toggled' => \&evt_value_changed,
	'im_colors_toggled'
);

if ( defined $settings_xml->{'general'}->{'im_colors_active'} ) {
	$im_colors_active->set_active( $settings_xml->{'general'}->{'im_colors_active'} );
} else {
	$im_colors_active->set_active(FALSE);
}

my $im_colors_label = Gtk2::Label->new( $d->get("Reduce colors") . ":" );
$tooltips->set_tip( $combobox_im_colors, $d->get("Automatically reduce colors \nafter taking a screenshot") );
$tooltips->set_tip( $im_colors_active,   $d->get("Automatically reduce colors \nafter taking a screenshot") );
$tooltips->set_tip( $im_colors_label,    $d->get("Automatically reduce colors \nafter taking a screenshot") );
$im_colors_box->pack_start( $im_colors_label, FALSE, TRUE, 12 );
$im_colors_box2->pack_start( $im_colors_active,   FALSE, TRUE, 0 );
$im_colors_box2->pack_start( $combobox_im_colors, TRUE,  TRUE, 0 );
$im_colors_box->pack_start( $im_colors_box2, TRUE, TRUE, 0 );

#end - colors
#--------------------------------------

#border
#--------------------------------------
my $combobox_border = Gtk2::ComboBox->new_text;
$combobox_border->insert_text( 1, $d->get("activate") );
$combobox_border->insert_text( 0, $d->get("deactivate") );
$combobox_border->signal_connect(
	'changed' => \&evt_value_changed,
	'border_changed'
);

if ( defined $settings_xml->{'general'}->{'border'} ) {
	$combobox_border->set_active( $settings_xml->{'general'}->{'border'} );
} else {
	$combobox_border->set_active(TRUE);
}

my $border_label = Gtk2::Label->new( $d->get("Window border") . ":" );
$tooltips->set_tip( $combobox_border, $d->get("Include wm border when selecting a window") );
$tooltips->set_tip( $border_label,    $d->get("Include wm border when selecting a window") );
$border_box->pack_start( $border_label,    FALSE, TRUE, 12 );
$border_box->pack_start( $combobox_border, TRUE,  TRUE, 0 );

#end - border
#--------------------------------------

#cursor
#--------------------------------------
my $combobox_cursor = Gtk2::ComboBox->new_text;
$combobox_cursor->insert_text( 1, $d->get("activate") );
$combobox_cursor->insert_text( 0, $d->get("deactivate") );
$combobox_cursor->signal_connect(
	'changed' => \&evt_value_changed,
	'cursor_changed'
);

if ( defined $settings_xml->{'general'}->{'cursor'} ) {
	$combobox_cursor->set_active( $settings_xml->{'general'}->{'cursor'} );
} else {
	$combobox_cursor->set_active(0);
}
my $cursor_label = Gtk2::Label->new( $d->get("Include cursor") . ":" );
$tooltips->set_tip( $combobox_cursor, $d->get("Include cursor when taking a screenshot") );
$tooltips->set_tip( $cursor_label,    $d->get("Include cursor when taking a screenshot") );
$cursor_box->pack_start( $cursor_label,    FALSE, TRUE, 12 );
$cursor_box->pack_start( $combobox_cursor, TRUE,  TRUE, 0 );

#end - cursor
#--------------------------------------

#accounts
#--------------------------------------
my $accounts_model = undef;
&fct_load_accounts_tree;

my $accounts_tree = Gtk2::TreeView->new_with_model($accounts_model);
$tooltips->set_tip(
	$accounts_tree,
	$d->get(
		"Entering your Accounts for specific hosting-sites is optional. If entered it will give you the same benefits as the upload on the website. If you leave these fields empty you will be able to upload to the specific hosting-partner as a guest."
	)
);

$accounts_tree->signal_connect(
	'row-activated' => \&evt_accounts,
	'row_activated'
);

&fct_set_model_accounts($accounts_tree);

#ftp uri
my $ftp_entry_label = Gtk2::Label->new( $d->get("URI") . ":" );

my $ftp_remote_entry = Gtk2::Entry->new;
if ( defined $settings_xml->{'general'}->{'ftp_uri'} ) {
	$ftp_remote_entry->set_text( $settings_xml->{'general'}->{'ftp_uri'} );
} else {
	$ftp_remote_entry->set_text("ftp://host:port/path");
}

$tooltips->set_tip( $ftp_entry_label, $d->get("URI\nExample: ftp://host:port/path") );

$tooltips->set_tip( $ftp_remote_entry, $d->get("URI\nExample: ftp://host:port/path") );

$ftp_hbox1->pack_start( $ftp_entry_label,  FALSE, TRUE, 12 );
$ftp_hbox1->pack_start( $ftp_remote_entry, TRUE,  TRUE, 0 );

#connection mode
my $ftp_mode_label = Gtk2::Label->new( $d->get("Connection mode") . ":" );

my $ftp_mode_combo = Gtk2::ComboBox->new_text;
$ftp_mode_combo->insert_text( 0, $d->get("Active mode") );
$ftp_mode_combo->insert_text( 1, $d->get("Passive mode") );
if ( defined $settings_xml->{'general'}->{'ftp_mode'} ) {
	$ftp_mode_combo->set_active( $settings_xml->{'general'}->{'ftp_mode'} );
} else {
	$ftp_mode_combo->set_active(0);
}

$tooltips->set_tip( $ftp_mode_label, $d->get("Connection mode") );

$tooltips->set_tip( $ftp_mode_combo, $d->get("Connection mode") );

$ftp_hbox2->pack_start( $ftp_mode_label, FALSE, TRUE, 12 );
$ftp_hbox2->pack_start( $ftp_mode_combo, TRUE,  TRUE, 0 );

#username
my $ftp_username_label = Gtk2::Label->new( $d->get("Username") . ":" );

my $ftp_username_entry = Gtk2::Entry->new;
if ( defined $settings_xml->{'general'}->{'ftp_username'} ) {
	$ftp_username_entry->set_text( $settings_xml->{'general'}->{'ftp_username'} );
} else {
	$ftp_username_entry->set_text("");
}

$tooltips->set_tip( $ftp_username_label, $d->get("Username") );

$tooltips->set_tip( $ftp_username_entry, $d->get("Username") );

$ftp_hbox3->pack_start( $ftp_username_label, FALSE, TRUE, 12 );
$ftp_hbox3->pack_start( $ftp_username_entry, TRUE,  TRUE, 0 );

#password
my $ftp_password_label = Gtk2::Label->new( $d->get("Password") . ":" );

my $ftp_password_entry = Gtk2::Entry->new;
$ftp_password_entry->set_invisible_char("*");
$ftp_password_entry->set_visibility(FALSE);
if ( defined $settings_xml->{'general'}->{'ftp_password'} ) {
	$ftp_password_entry->set_text( $settings_xml->{'general'}->{'ftp_password'} );
} else {
	$ftp_password_entry->set_text("");
}

$tooltips->set_tip( $ftp_password_label, $d->get("Password") );

$tooltips->set_tip( $ftp_password_entry, $d->get("Password") );

$ftp_hbox4->pack_start( $ftp_password_label, FALSE, TRUE, 12 );
$ftp_hbox4->pack_start( $ftp_password_entry, TRUE,  TRUE, 0 );

#--------------------------------------

#packing
#--------------------------------------

#settings main tab
my $label_basic = Gtk2::Label->new;
$label_basic->set_markup( $d->get("Main") );

$file_vbox->pack_start( $scale_box,    TRUE,  TRUE, 3 );
$file_vbox->pack_start( $filetype_box, FALSE, TRUE, 3 );
$file_frame->add($file_vbox);

$save_vbox->pack_start( $filename_box, TRUE,  TRUE, 3 );
$save_vbox->pack_start( $saveDir_box,  FALSE, TRUE, 3 );
$save_vbox->pack_start( $filename_hint, TRUE,  TRUE, 3 );
$save_frame->add($save_vbox);

#all labels = one size
$scale_label->set_alignment( 0, 0.5 );
$filetype_label->set_alignment( 0, 0.5 );
$filename_label->set_alignment( 0, 0.5 );
$saveDir_label->set_alignment( 0, 0.5 );

my $sg_main = Gtk2::SizeGroup->new('horizontal');
$sg_main->add_widget($scale_label);
$sg_main->add_widget($filetype_label);
$sg_main->add_widget($filename_label);
$sg_main->add_widget($saveDir_label);

$vbox_basic->pack_start( $file_frame, FALSE, TRUE, 3 );
$vbox_basic->pack_start( $save_frame, FALSE, TRUE, 3 );
$vbox_basic->set_border_width(5);

#settings advanced tab
my $label_extras = Gtk2::Label->new;
$label_extras->set_markup( $d->get("Advanced") );

$actions_vbox->pack_start( $progname_box,  FALSE, TRUE, 3 );
$actions_vbox->pack_start( $im_colors_box, FALSE, TRUE, 3 );
$actions_vbox->pack_start( $thumbnail_box, FALSE, TRUE, 3 );
$actions_frame->add($actions_vbox);

$capture_vbox->pack_start( $delay_box,  FALSE, TRUE, 3 );
$capture_vbox->pack_start( $border_box, FALSE, TRUE, 3 );
$capture_vbox->pack_start( $cursor_box, FALSE, TRUE, 3 );
$capture_frame->add($capture_vbox);

#all labels = one size
$progname_label->set_alignment( 0, 0.5 );
$im_colors_label->set_alignment( 0, 0.5 );
$thumbnail_label->set_alignment( 0, 0.5 );
$delay_label->set_alignment( 0, 0.5 );
$border_label->set_alignment( 0, 0.5 );
$cursor_label->set_alignment( 0, 0.5 );

my $sg_adv = Gtk2::SizeGroup->new('horizontal');
$sg_adv->add_widget($progname_label);
$sg_adv->add_widget($im_colors_label);
$sg_adv->add_widget($thumbnail_label);
$sg_adv->add_widget($delay_label);
$sg_adv->add_widget($border_label);
$sg_adv->add_widget($cursor_label);

$vbox_extras->pack_start( $actions_frame, FALSE, TRUE, 3 );
$vbox_extras->pack_start( $capture_frame, FALSE, TRUE, 3 );
$vbox_extras->set_border_width(5);

#settings behavior tab
my $label_behavior = Gtk2::Label->new;
$label_behavior->set_markup( $d->get("Behavior") );

$behavior_vbox->pack_start( $behavior_hbox1, TRUE, TRUE, 3 );
$behavior_vbox->pack_start( $behavior_hbox2, TRUE, TRUE, 3 );
$behavior_vbox->pack_start( $behavior_hbox3, TRUE, TRUE, 3 );
$behavior_frame->add($behavior_vbox);

$keybinding_vbox->pack_start( $key_box,             FALSE, TRUE, 3 );
$keybinding_vbox->pack_start( $key_sel_box,         FALSE, TRUE, 3 );
$keybinding_vbox->pack_start( $keybinding_mode_box, FALSE, TRUE, 3 );
$keybinding_frame->add($keybinding_vbox);

#all labels = one size
$capture_label->set_alignment( 0, 0.5 );
$capture_sel_label->set_alignment( 0, 0.5 );

my $sg_behav = Gtk2::SizeGroup->new('horizontal');
$sg_behav->add_widget($capture_label);
$sg_behav->add_widget($capture_sel_label);

$vbox_behavior->pack_start( $behavior_frame,   FALSE, TRUE, 3 );
$vbox_behavior->pack_start( $keybinding_frame, FALSE, TRUE, 3 );
$vbox_behavior->set_border_width(5);

#settings upload tab
my $label_accounts = Gtk2::Label->new;
$label_accounts->set_markup( $d->get("Upload") );

my $scrolled_accounts_window = Gtk2::ScrolledWindow->new;
$scrolled_accounts_window->set_policy( 'automatic', 'automatic' );
$scrolled_accounts_window->set_shadow_type('in');
$scrolled_accounts_window->add($accounts_tree);
$accounts_hbox->pack_start( $scrolled_accounts_window, TRUE, TRUE, 3 );
$accounts_vbox->pack_start( $accounts_hbox,            TRUE, TRUE, 3 );
$accounts_frame->add($accounts_vbox);

$ftp_vbox->pack_start( $ftp_hbox1, FALSE, TRUE, 3 );
$ftp_vbox->pack_start( $ftp_hbox2, FALSE, TRUE, 3 );
$ftp_vbox->pack_start( $ftp_hbox3, FALSE, TRUE, 3 );
$ftp_vbox->pack_start( $ftp_hbox4, FALSE, TRUE, 3 );
$ftp_frame->add($ftp_vbox);

#all labels = one size
$ftp_entry_label->set_alignment( 0, 0.5 );
$ftp_mode_label->set_alignment( 0, 0.5 );
$ftp_username_label->set_alignment( 0, 0.5 );
$ftp_password_label->set_alignment( 0, 0.5 );

my $sg_acc = Gtk2::SizeGroup->new('horizontal');
$sg_acc->add_widget($ftp_entry_label);
$sg_acc->add_widget($ftp_mode_label);
$sg_acc->add_widget($ftp_username_label);
$sg_acc->add_widget($ftp_password_label);

$vbox_accounts->pack_start( $accounts_frame, FALSE, TRUE, 3 );
$vbox_accounts->pack_start( $ftp_frame,      FALSE, TRUE, 3 );
$vbox_accounts->set_border_width(5);

#append pages to notebook
$notebook_settings->append_page( $vbox_basic,    $label_basic );
$notebook_settings->append_page( $vbox_extras,   $label_extras );
$notebook_settings->append_page( $vbox_behavior, $label_behavior );
$notebook_settings->append_page( $vbox_accounts, $label_accounts );

#plugins
if ( keys(%plugins) > 0 ) {

	my $effects_tree = Gtk2::TreeView->new_with_model(&fct_load_plugin_tree);
	&fct_set_model_plugins($effects_tree);	
	
	my $scrolled_plugins_window = Gtk2::ScrolledWindow->new;
	$scrolled_plugins_window->set_policy( 'automatic', 'automatic' );
	$scrolled_plugins_window->set_shadow_type('in');
	$scrolled_plugins_window->add($effects_tree);
	
	my $label_plugins = Gtk2::Label->new;
	$label_plugins->set_markup( $d->get("Plugins") );
	
	my $label_treeview = Gtk2::Label->new( $d->get("The following plugins are installed") );
	$label_treeview->set_alignment( 0, 0.5 );
	$effects_vbox->pack_start( $label_treeview,          FALSE, TRUE, 1 );
	$effects_vbox->pack_start( $scrolled_plugins_window, TRUE,  TRUE, 1 );
	
	my $vbox_plugins = Gtk2::VBox->new( FALSE, 12 );
	$vbox_plugins->set_border_width(5);
	$vbox_plugins->pack_start( $effects_vbox,            TRUE,  TRUE, 1 );
	
	$notebook_settings->append_page( $vbox_plugins, $label_plugins );
}

#profiles
$profiles_box->pack_start( $profiles_label,             FALSE, TRUE, 1 );
$profiles_box->pack_start( $combobox_settings_profiles, TRUE,  TRUE, 6 );
$profiles_box->pack_start( $button_profile_save,        FALSE, TRUE, 1 );
$profiles_box->pack_start( $button_profile_delete,      FALSE, TRUE, 1 );
$profiles_box->pack_start( $button_profile_apply,       FALSE, TRUE, 1 );

$vbox_settings->pack_start( $profiles_box,      FALSE, TRUE, 1 );
$vbox_settings->pack_start( $notebook_settings, TRUE,  TRUE, 1 );

#settings
$hbox_settings->pack_start( $vbox_settings, FALSE, TRUE, 6 );
$settings_dialog->vbox->add($hbox_settings);
$settings_dialog->set_default_response('apply');

#main app
$vbox->pack_start( $notebook,  TRUE,  TRUE,  0 );

#pack statusbar
$status1->set_has_resize_grip (FALSE);
$status2->set_has_resize_grip (TRUE);
my $status_hbox = Gtk2::HBox->new( FALSE, 0 );
$status_hbox->pack_start( $status1, TRUE, TRUE, 0 );
$status_hbox->pack_start( $status2, TRUE, TRUE, 0 );
$vbox->pack_start( $status_hbox, FALSE, FALSE, 0 );

#--------------------------------------

#restore session
#--------------------------------------
&fct_load_session;

#start minimized?
#--------------------------------------
unless ( $shutter_common->get_min ) {
	&fct_control_main_window (TRUE, 'show');
} else {
	&fct_control_main_window (TRUE, 'hide');
}

#update the first tab on startup
&fct_update_first_tab();

#load saved settings
#--------------------------------------
my $folder_to_save = $settings_xml->{'general'}->{'folder'}
	|| $ENV{'HOME'};
if ( $shutter_common->get_start_with && $folder_to_save ) {
	if ( $shutter_common->get_start_with eq "raw" ) {
		&evt_take_screenshot( 'global_keybinding', "raw", $folder_to_save );
	} elsif ( $shutter_common->get_start_with eq "select" ) {
		&evt_take_screenshot( 'global_keybinding', "select", $folder_to_save );
	} elsif ( $shutter_common->get_start_with eq "window" ) {
		&evt_take_screenshot( 'global_keybinding', "window", $folder_to_save );
	} elsif ( $shutter_common->get_start_with eq "section" ) {
		&evt_take_screenshot( 'global_keybinding', "section", $folder_to_save );
	}
}

Gtk2->main;

0;

#events
#--------------------------------------
sub evt_value_changed {
	my ( $widget, $data ) = @_;
	print "\n$data was emitted by widget $widget\n"
		if $shutter_common->get_debug;

	return FALSE unless $data;

	#checkbox for "open with" -> entry active/inactive
	if ( $data eq "progname_toggled" ) {
		if ( $progname_active->get_active ) {
			$progname->set_sensitive(TRUE);
		} else {
			$progname->set_sensitive(FALSE);
		}
	}

	#checkbox for "color depth" -> entry active/inactive
	if ( $data eq "im_colors_toggled" ) {
		if ( $im_colors_active->get_active ) {
			$combobox_im_colors->set_sensitive(TRUE);
		} else {
			$combobox_im_colors->set_sensitive(FALSE);
		}
	}

	#checkbox for "delay" -> HScale active/inactive
	if ( $data eq "delay_toggled" ) {
		if ( $delay_active->get_active ) {
			$delay->set_sensitive(TRUE);
		} else {
			$delay->set_sensitive(FALSE);
		}
	}

	#checkbox for "thumbnail" -> HScale active/inactive
	if ( $data eq "thumbnail_toggled" ) {
		if ( $thumbnail_active->get_active ) {
			$thumbnail->set_sensitive(TRUE);
		} else {
			$thumbnail->set_sensitive(FALSE);
		}
	}

	#filetype changed
	if ( $data eq "type_changed" ) {
		if ( $combobox_type->get_active_text =~ /jpeg/ ) {
			$scale->set_sensitive(TRUE);
			$scale_label->set_sensitive(TRUE);
			$scale->set_range( 1, 100 );
			$scale->set_value(90);
			$scale_label->set_text( $d->get("Quality") . ":" );
		} elsif ( $combobox_type->get_active_text =~ /png/ ) {
			$scale->set_sensitive(TRUE);
			$scale_label->set_sensitive(TRUE);
			$scale->set_range( 0, 9 );
			$scale->set_value(9);
			$scale_label->set_text( $d->get("Compression") . ":" );
		} else {
			$scale->set_sensitive(FALSE);
			$scale_label->set_sensitive(FALSE);
		}
	}

	return TRUE;
}

sub evt_take_screenshot {
	my ( $widget, $data, $folder_from_config ) = @_;

	#get xid if any window was selected from the submenu...
	my $selfcapture = FALSE;
	if ( $data =~ /^shutter_window_direct(.*)/ ) {
		my $xid = $1;
		$selfcapture = TRUE if $xid == $window->window->XID;
	}

	#hide mainwindow
	if (   $hide_active->get_active
		&& $data ne "web" 
		&& $data ne "tray_web"
		&& !$is_hidden
		&& !$selfcapture )
	{
		&fct_control_main_window(FALSE, 'hide');
	}else{

		#save current position of main window
		( $window->{x}, $window->{y} ) = $window->get_position;
		
	}

	if ( $data eq "web" || $data eq "tray_web" ){
		&fct_take_screenshot($widget, $data, $folder_from_config);
	}else{
		#A short timeout to give the server a chance to
		#redraw the area that was obscured by our dialog.
		Glib::Timeout->add (400, sub{
			&fct_take_screenshot($widget, $data, $folder_from_config);
			return FALSE;	
		});		
	}
}

sub evt_behavior_handle {
	my ( $widget, $data ) = @_;
	print "\n$data was emitted by widget $widget\n"
		if $shutter_common->get_debug;

	#checkbox for "keybinding" -> entry active/inactive
	if ( $data eq "keybinding_toggled" ) {
		if ( $keybinding_active->get_active ) {
			$capture_key->set_sensitive(TRUE);
		} else {
			$capture_key->set_sensitive(FALSE);
		}
		
	}

	#checkbox for "keybinding_sel" -> entry active/inactive
	if ( $data eq "keybinding_sel_toggled" ) {
		if ( $keybinding_sel_active->get_active ) {
			$capture_sel_key->set_sensitive(TRUE);
			$combobox_keybinding_mode->set_sensitive(TRUE);
		} else {
			$capture_sel_key->set_sensitive(FALSE);
			$combobox_keybinding_mode->set_sensitive(FALSE);
		}
	}
		
	return TRUE;
}

sub evt_notebook_switch {
	my ( $widget, $pointer, $int ) = @_;

	my $key = &fct_get_file_by_index($int);
	if($key){

		#do this when idle
		Glib::Idle->add (
		sub{

			foreach (keys %session_screens){
				if ($_ eq $key){
					if($session_screens{$key}->{'long'}){
						eval{
							$session_screens{$_}->{'image'}->set_pixbuf(Gtk2::Gdk::Pixbuf->new_from_file( $session_screens{$key}->{'long'} ));								
						}
					}
					next;
				}
				eval{
					$session_screens{$_}->{'image'}->set_pixbuf(undef);
				};
				if($@){
					delete $session_screens{$_};
					next;	
				}
			}

			return FALSE;
		});			
		
	}	

	#unselect all items in session tab
	#when we move away
	if($int == 0){
		$session_start_screen{'first_page'}->{'view'}->unselect_all;
	}

	#enable/disable menu entry when we switch tabs		
	&fct_update_actions($int);

	return TRUE;
}

sub evt_delete_window {
	my ( $widget, $data ) = @_;
	print "\n$data was emitted by widget $widget\n"
		if $shutter_common->get_debug;

	if ( $data ne "quit" && $close_at_close_active->get_active ) {
		$window->hide;
		$is_hidden = TRUE;
		return TRUE;
	}

	#hide window and save settings
	$window->hide;
	&fct_save_settings(undef);
	&fct_save_settings( $combobox_settings_profiles->get_active_text ) 
		if $combobox_settings_profiles->get_active != -1;

	Gtk2->main_quit;
	return FALSE;
}

sub evt_bug {
	$shutter_hfunct->xdg_open( undef, "https://bugs.launchpad.net/shutter", undef );
}

sub evt_question {
	$shutter_hfunct->xdg_open( undef, "https://answers.launchpad.net/shutter", undef );
}

sub evt_translate {
	$shutter_hfunct->xdg_open( undef, "https://translations.launchpad.net/shutter", undef );
}

sub evt_about {
	my ( $widget, $data ) = @_;
	if ( $shutter_common->get_debug ) {
		print "\n$data was emitted by widget $widget\n";
	}
	
	#everything is stored in external files, so it is easier to maintain
	my $all_hint = "";
	open( GPL_HINT, "$shutter_root/share/shutter/resources/license/gplv3_hint" )
		or die $!;
	while(my $hint = <GPL_HINT>){
		utf8::decode $hint;
		$all_hint .= $hint;	
	}
	close(GPL_HINT);
	
	my $all_gpl = "";
	open( GPL, "$shutter_root/share/shutter/resources/license/gplv3" )
		or die $!;
	while(my $gpl = <GPL>){
		utf8::decode $gpl;
		$all_gpl .= $gpl;	
	}	
	close(GPL);
	
	my $all_dev = "";
	open( DEVCREDITS, "$shutter_root/share/shutter/resources/credits/dev" )
		or die $!;
	while(my $dev = <DEVCREDITS>){
		utf8::decode $dev;
		$all_dev .= $dev;	
	}
	close(DEVCREDITS);

	my $all_art = "";
	open( ARTCREDITS, "$shutter_root/share/shutter/resources/credits/art" )
		or die $!;
	while(my $art = <ARTCREDITS>){
		utf8::decode $art;
		$all_art .= $art;	
	}
	close(ARTCREDITS);
	
	my $website = "http://shutter-project.org";
	my $about   = Gtk2::AboutDialog->new;
	my $logo    = Gtk2::Gdk::Pixbuf->new_from_file_at_scale( "$shutter_root/share/pixmaps/shutter.svg", 100, 100, TRUE );
	$about->set_logo($logo);
	if (Gtk2->CHECK_VERSION( 2, 12, 0 )){
		$about->set_program_name(SHUTTER_NAME);
	}else{
		$about->set_name(SHUTTER_NAME);
	}
	$about->set_version(SHUTTER_VERSION);
	$about->set_url_hook( sub { $shutter_hfunct->xdg_open(@_) } );
	$about->set_website_label("Shutter-Website");
	$about->set_website($website);
	$about->set_email_hook( sub { $shutter_hfunct->xdg_open_mail(@_) } );
	$about->set_authors( $all_dev );
	$about->set_artists( $all_art );
	$about->set_translator_credits($d->get("translator-credits"));
	$about->set_copyright($all_hint);
	$about->set_license($all_gpl);
	$about->set_comments(REV);
	$about->show_all;
	$about->signal_connect( 'response' => sub { $about->destroy } );
}

sub evt_show_systray {
	my ( $widget, $data ) = @_;
	if ( $shutter_common->get_debug ) {
		print "\n$data was emitted by widget $widget\n";
	}

	#left button (mouse)
	if ( $_[1]->button == 1 ) {
		if ( $window->visible ) {
			&fct_control_main_window (TRUE, 'hide');
		} else {
			&fct_control_main_window (TRUE, 'show');
		}
	}

	#right button (mouse)
	elsif ( $_[1]->button == 3 ) {

		my $tray_menu = &fct_ret_tray_menu;

		$tray_menu->popup(
			undef,    # parent menu shell
			undef,    # parent menu item
			undef,    # menu pos func
			undef,    # data
			$data->button,
			$data->time
		);
	}
	return TRUE;
}

sub evt_show_systray_statusicon {
	my ( $widget, $button, $time, $icon ) = @_;
	if ( $shutter_common->get_debug ) {
		print "\n$button, $time was emitted by widget $widget\n";
	}

	my $tray_menu = &fct_ret_tray_menu;

	$tray_menu->popup(
		undef,    # parent menu shell
		undef,    # parent menu item
		sub {
			return Gtk2::StatusIcon::position_menu( $tray_menu, 0, 0, $icon );
		},        # menu pos func
		undef,    # data
		$time ? $button : 0,
		$time
	);
	return TRUE;
}

sub evt_activate_systray_statusicon {
	my ( $widget, $data, $icon ) = @_;
	if ( $shutter_common->get_debug ) {
		print "\n$data was emitted by widget $widget\n";
	}

	unless ( $is_hidden ) {
		&fct_control_main_window (TRUE, 'hide');
	} else {
		&fct_control_main_window (TRUE, 'show');
	}

	return TRUE;
}

sub evt_accounts {
	my ( $tree, $path, $column ) = @_;

	#open browser if register url is clicked
	if ( $column->get_title eq $d->get("Register") ) {
		my $model         = $tree->get_model();
		my $account_iter  = $model->get_iter($path);
		my $account_value = $model->get_value( $account_iter, 3 );
		$shutter_hfunct->xdg_open( undef, $account_value, undef );
	}
	return TRUE;
}

sub evt_tab_button_press {
	my ($ev_box, $ev, $key) = @_;
	
	#right click
	if($key && $ev->button == 3 && $ev->type eq 'button-press'){

		$shutter_menu->{_menu_actions}->popup(
			undef,    # parent menu shell
			undef,    # parent menu item
			undef,    # menu pos func
			undef,    # data
			$ev->button,
			$ev->time
		);
		
	}
	
	return TRUE;
}

sub evt_iconview_button_press {
	my $ev_box	= shift;
	my $ev 		= shift;
	my $view 	= shift;
	
	my $path = $view->get_path_at_pos ($ev->x, $ev->y);
	
	if($path){
		#select item
		$view->select_path ($path);		

		$shutter_menu->{_menu_actions}->popup(
			undef,    # parent menu shell
			undef,    # parent menu item
			undef,    # menu pos func
			undef,    # data
			$ev->button,
			$ev->time
		);
		
	}
	
	return TRUE;
}

sub evt_iconview_sel_changed {
	my ( $iconview, $data ) = @_;

	#we don't handle selection changes 
	#if we are not in the session tab
	if (&fct_get_current_file){
	
		return FALSE; 		
	}

	my @sel_items = $iconview->get_selected_items;	
	
	#enable/disable menu entry when we are in the session tab and selection changes
	&fct_update_actions( scalar @sel_items );
		
	return TRUE;
}

sub fct_update_actions {
	my $n_items = shift;

	#TOOLBAR
	#--------------------------------------
	$shutter_tool->{_edit}->set_sensitive($n_items);
	$shutter_tool->{_upload}->set_sensitive($n_items);

	#MENU
	#--------------------------------------
	$shutter_menu->{_menuitem_reopen_default}->visible($n_items);
	$shutter_menu->{_menuitem_reopen_default}->set_sensitive($n_items);
	$shutter_menu->{_menuitem_reopen}->set_sensitive($n_items);
	$shutter_menu->{_menuitem_rename}->set_sensitive($n_items);
	$shutter_menu->{_menuitem_upload}->set_sensitive($n_items);
	
	$shutter_menu->{_menuitem_draw}->set_sensitive($n_items);
	
	#maybe lib is not installed
	unless ($goocanvas) {
		$shutter_menu->{_menuitem_draw}->set_sensitive(FALSE);
	}		

	$shutter_menu->{_menuitem_plugin}->set_sensitive($n_items);
	$shutter_menu->{_menuitem_save_as}->set_sensitive($n_items);
	$shutter_menu->{_menuitem_pagesetup}->set_sensitive($n_items);
	$shutter_menu->{_menuitem_print}->set_sensitive($n_items);
	$shutter_menu->{_menuitem_close}->set_sensitive($n_items);
	$shutter_menu->{_menuitem_trash}->set_sensitive($n_items);
	$shutter_menu->{_menuitem_copy}->set_sensitive($n_items);
	$shutter_menu->{_menuitem_copy_filename}->set_sensitive($n_items);
	$shutter_menu->{_menuitem_zoom_in}->set_sensitive($n_items);
	$shutter_menu->{_menuitem_zoom_out}->set_sensitive($n_items);
	$shutter_menu->{_menuitem_zoom_100}->set_sensitive($n_items);
	$shutter_menu->{_menuitem_zoom_best}->set_sensitive($n_items);
		
	return TRUE;
}

sub evt_iconview_item_activated {
	my ( $iconview, $path, $data ) = @_;

	my $iter = $session_start_screen{'first_page'}->{'model'}->get_iter($path);
	my $key = $session_start_screen{'first_page'}->{'model'}->get_value( $iter, 2 );

	$notebook->set_current_page( $notebook->page_num( $session_screens{$key}->{'tab_child'} ) );

	return TRUE;
}

sub evt_show_settings {
	&fct_check_installed_programs;

	$settings_dialog->show_all;
	my $settings_dialog_response = $settings_dialog->run;
	
	&fct_post_settings($settings_dialog);	
	
	if ( $settings_dialog_response eq "close" ) {
		return TRUE;
	} else {
		return FALSE;
	}
}

sub fct_post_settings {
	my $settings_dialog = shift;

	#unset profile combobox when profile was not applied
	if ( $current_profile_indx != $combobox_settings_profiles->get_active ) {
		$combobox_settings_profiles->set_active($current_profile_indx);
	}

	$settings_dialog->hide();
	
	#save directly
	&fct_save_settings(undef);
	&fct_save_settings( $combobox_settings_profiles->get_active_text ) 
		if $combobox_settings_profiles->get_active != -1;
	
	#we need to update the first tab here
	#because the profile might have changed
	&fct_update_first_tab();

	return TRUE;
}

sub evt_open {
	my ( $widget, $data ) = @_;
	print "\n$data was emitted by widget $widget\n"
		if $shutter_common->get_debug;

	#do we need to open a filechooserdialog?
	#maybe we open a recently opened file that is 
	#selected via menu
	my @new_files;	
	unless($widget =~ /Gtk2::RecentChooserMenu/){
		my $fs = Gtk2::FileChooserDialog->new(
			$d->get("Choose file to open"), $window,
			'open',
			'gtk-cancel' => 'reject',
			'gtk-open'   => 'accept'
		);
		$fs->set_select_multiple(TRUE);

		my $filter_all = Gtk2::FileFilter->new;
		$filter_all->set_name( $d->get("All compatible image formats") );
		$fs->add_filter($filter_all);
		
		foreach ( Gtk2::Gdk::Pixbuf->get_formats ) {
			my $filter = Gtk2::FileFilter->new;
			
			#add all known formats to the dialog			
			$filter->set_name( $_->{name} . " - " . $_->{description} );
			
			foreach ( @{ $_->{extensions} } ) {
				$filter->add_pattern( "*." . uc $_ );
				$filter_all->add_pattern( "*." . uc $_ );
				$filter->add_pattern( "*." . $_ );
				$filter_all->add_pattern( "*." . $_ );
			}
			$fs->add_filter($filter);
		}
		
		#set default filter
		$fs->set_filter($filter_all);

		my $key = &fct_get_current_file;
		if ($key) {
			$fs->set_filename( $session_screens{$key}->{'long'} );
		} elsif ( $ENV{'HOME'} ) {
			$fs->set_current_folder( $saveDir_button->get_filename() );
		}
		my $fs_resp = $fs->run;

		if ( $fs_resp eq "accept" ) {
			@new_files = $fs->get_filenames;
			$fs->destroy();
		} else {
			$fs->destroy();
		}

	}else{
		push @new_files, $widget->get_current_uri;
	}

	#call function to open files - with progress bar etc.
	&fct_open_files(@new_files);

	return TRUE;
}

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

	#restore settings if prossible
	my $ssettings = Gtk2::PrintSettings->new;
	if ( $shutter_hfunct->file_exists("$ENV{ HOME }/.shutter/printing.xml") ) {
		eval { $ssettings = Gtk2::PrintSettings->new_from_file("$ENV{ HOME }/.shutter/printing.xml"); };
	}

	$pagesetup = Gtk2::Print->run_page_setup_dialog( $window, $pagesetup, $ssettings );

	return TRUE;
}

sub evt_save_as {
	my ( $widget, $data ) = @_;
	print "\n$data was emitted by widget $widget\n"
		if $shutter_common->get_debug;


	my $key = &fct_get_current_file;

	my @save_as_files;
	#single file
	if ($key) {

		push @save_as_files, $key;

	#session tab
	} else {

		$session_start_screen{'first_page'}->{'view'}->selected_foreach(
			sub {
				my ( $view, $path ) = @_;
				my $iter = $session_start_screen{'first_page'}->{'model'}->get_iter($path);
				if ( defined $iter ) {
					my $key = $session_start_screen{'first_page'}->{'model'}->get_value( $iter, 2 );

					push @save_as_files, $key;

				}
			},
			undef
		);

	}

	&fct_save_as(@save_as_files);

	return TRUE;
	
}

sub evt_save_profile {
	my ( $widget, $combobox_settings_profiles, $current_profiles_ref ) = @_;
	my $curr_profile_name = $combobox_settings_profiles->get_active_text
		|| "";
	my $new_profile_name = &dlg_profile_name( $curr_profile_name, $combobox_settings_profiles );

	if ($new_profile_name) {
		if ( $curr_profile_name ne $new_profile_name ) {
			$combobox_settings_profiles->prepend_text($new_profile_name);
			$combobox_settings_profiles->set_active(0);
			$current_profile_indx = 0;

			#unshift to array as well
			unshift( @{$current_profiles_ref}, $new_profile_name );
		
			&fct_update_quick_profile_selector($combobox_settings_profiles, $current_profiles_ref);

		}
		&fct_save_settings($new_profile_name);
	}
	return TRUE;
}

sub evt_delete_profile {
	my ( $widget, $combobox_settings_profiles, $current_profiles_ref ) = @_;
	if ( $combobox_settings_profiles->get_active_text ) {
		my $active_text  = $combobox_settings_profiles->get_active_text;
		my $active_index = $combobox_settings_profiles->get_active;
		unlink( "$ENV{'HOME'}/.shutter/profiles/" . $active_text . ".xml" );
		unlink( "$ENV{'HOME'}/.shutter/profiles/" . $active_text . "_accounts.xml" );

		unless ( $shutter_hfunct->file_exists( "$ENV{'HOME'}/.shutter/profiles/" . $active_text . ".xml" )
			|| $shutter_hfunct->file_exists( "$ENV{'HOME'}/.shutter/profiles/" . $active_text . "_accounts.xml" ) )
		{
			$combobox_settings_profiles->remove_text($active_index);
			$combobox_settings_profiles->set_active( $combobox_settings_profiles->get_active + 1 );
			$current_profile_indx = $combobox_settings_profiles->get_active;

			#remove from array as well
			splice( @{$current_profiles_ref}, $active_index, 1 );

			&fct_update_quick_profile_selector($combobox_settings_profiles, $current_profiles_ref);
			
			&dlg_status_message( 1, $d->get("Profile deleted") );
		} else {
			$shutter_dialog->dlg_error_message( $d->get("Profile could not be deleted"), $d->get("Failed") );
			&dlg_status_message( 1, $d->get("Profile could not be deleted") );
		}
	}
	return TRUE;
}

sub evt_apply_profile {
	my ( $widget, $combobox_settings_profiles, $current_profiles_ref ) = @_;

	if ( $combobox_settings_profiles->get_active_text ) {
		$settings_xml = &fct_load_settings( 'profile_load', $combobox_settings_profiles->get_active_text );
		$current_profile_indx = $combobox_settings_profiles->get_active;

		&fct_update_quick_profile_selector($combobox_settings_profiles, $current_profiles_ref);	
	}
	
	&fct_update_first_tab();
	
	return TRUE;
}

#--------------------------------------

#functions
#--------------------------------------

sub fct_create_session_notebook {

	$notebook->set( homogeneous  => TRUE );
	$notebook->set( 'scrollable' => TRUE );

	$notebook->set_size_request( 430, 320 );
	my $hbox_first_label = Gtk2::HBox->new( FALSE, 0 );
	my $thumb_first_icon = Gtk2::Image->new_from_stock( 'gtk-index', 'menu' );
	my $tab_first_label = Gtk2::Label->new();
	$tab_first_label->set_markup( "<b>" . $d->get("Session") . "</b>" );
	$hbox_first_label->pack_start( $thumb_first_icon, FALSE, TRUE, 1 );
	$hbox_first_label->pack_start( $tab_first_label,  TRUE,  TRUE, 1 );
	$hbox_first_label->show_all;

	my $new_index = $notebook->append_page( fct_create_tab( "", TRUE ), $hbox_first_label );
	$session_start_screen{'first_page'}->{'tab_child'} = $notebook->get_nth_page($new_index);

	$notebook->signal_connect( 'switch-page' => \&evt_notebook_switch );

	return $notebook;
}

sub fct_integrate_screenshot_in_notebook {
	my ($uri, $pixbuf) = @_;

	#check parameters
	return FALSE unless $uri;
	unless ($uri->exists){
		&dlg_status_message( 1, $uri->to_string . " " . $d->get("not found") );		
		return FALSE;
	}

	#add to recentmanager
	$rmanager->add_item($uri->to_string);

	#append a page to notebook using with label == filename
	my ( $second, $minute, $hour ) = localtime();
	my $theTime = sprintf("%02d:%02d:%02d", $hour, $minute, $second);
	my $key     = "[" . &fct_get_latest_tab_key . "] - $theTime";

	#setup tab label (thumb, preview etc.)
	my $hbox_tab_label = Gtk2::HBox->new( FALSE, 0 );
	my $close_icon = Gtk2::Image->new_from_icon_name( 'gtk-close', 'menu' );

	$session_screens{$key}->{'tab_icon'} = Gtk2::Image->new;

	#setup tab label
	my $tab_close_button = Gtk2::Button->new;
	$tab_close_button->set_relief('none');
	$tab_close_button->set_image($close_icon);
	my $tab_label = Gtk2::Label->new($key);
	$hbox_tab_label->pack_start( $session_screens{$key}->{'tab_icon'}, FALSE, TRUE, 1 );
	$hbox_tab_label->pack_start( $tab_label,                           TRUE,  TRUE, 1 );
	$hbox_tab_label->pack_start( $tab_close_button,                    FALSE, TRUE, 1 );
	$hbox_tab_label->show_all;

	#and append page with label == key
	my $new_index = $notebook->append_page( &fct_create_tab( $key, FALSE ), $hbox_tab_label );
	$session_screens{$key}->{'tab_label'} = $hbox_tab_label;
	$session_screens{$key}->{'tab_child'} = $notebook->get_nth_page($new_index);
	$tab_close_button->signal_connect( clicked => sub { &fct_remove($key); } );

	$notebook->set_current_page($new_index);

	if ( &fct_update_tab( $key, $pixbuf, $uri ) ) {

		#setup a filemonitor, so we get noticed if the file changed
		&fct_add_file_monitor($key);
				
	}

	return $key;
}

sub fct_add_file_monitor {
	my $key = shift;

	$session_screens{$key}->{'changed'} = FALSE;
	$session_screens{$key}->{'deleted'} = FALSE;
	$session_screens{$key}->{'created'} = FALSE;

	my $result;
	( $result, $session_screens{$key}->{'handle'} ) = Gnome2::VFS::Monitor->add(
		$session_screens{$key}->{'uri'}->to_string,
		'file',
		sub {
			my $handle = shift;
			my $file1  = shift;
			my $file2  = shift;
			my $event  = shift;
			my $key    = shift;

			print $event. " - $key\n" if $shutter_common->get_debug;

			if ( $event eq 'deleted' ) {
				
				$handle->cancel;
				$session_screens{$key}->{'deleted'} = TRUE;
				$session_screens{$key}->{'changed'} = TRUE;
				&fct_update_tab($key);

			} elsif ( $event eq 'changed' ) {

				print $session_screens{$key}->{'uri'}->to_string . " - " . $event . "\n" if $shutter_common->get_debug;
				$session_screens{$key}->{'changed'} = TRUE;
				&fct_update_tab($key);
			
			}

		},
		$key
	);
	
	#show error dialog when installing the file
	#monitor failed
	unless ($result eq 'ok'){
		$shutter_dialog->dlg_error_message( Gnome2::VFS->result_to_string($result), $d->get("Failed") );		
		return FALSE;
	}

	return TRUE;
}

sub fct_control_main_window {
	my $set = shift;
	my $mode = shift;
	
	#set all buttons insensitive/sensitive
	if($shutter_tool->{_select}){
		$shutter_tool->{_select}->set_sensitive($set);
		$shutter_tool->{_full}->set_sensitive($set);
		$shutter_tool->{_window}->set_sensitive($set);
		$shutter_tool->{_section}->set_sensitive($set);
		$shutter_tool->{_web}->set_sensitive($set) if ($gnome_web_photo);
	}else{
		return FALSE;	
	}
	
	#hide or show window
	if($mode eq 'show'){

		#move window to saved position
		$window->move( $window->{x}, $window->{y} ) if (defined $window->{x} && defined $window->{y});
		
		#this is an unusual method for raising the window
		#to the top within the stacking order (z-axis)
		#but it works best here
		if($is_hidden){
			$window->show_all;
			$window->window->focus(time) if defined $window->window;
			$window->present;
		}
				
		#set flag
		$is_hidden = FALSE;

		#attach signal-handler again
		$SIG{USR1}  = sub { &evt_take_screenshot( 'global_keybinding', 'raw' ) };
		$SIG{USR2}  = sub { &evt_take_screenshot( 'global_keybinding', 'window' ) };
		$SIG{RTMIN} = sub { &evt_take_screenshot( 'global_keybinding', 'select' ) };
		$SIG{RTMAX} = sub { &evt_take_screenshot( 'global_keybinding', 'section' ) };
		
		#toolbar->set_show_arrow is FALSE at startup
		#to automatically adjust the main window width
		#we change the setting to TRUE if it is still false, 
		#so the window/toolbar is resizable again
		if($shutter_tool->{_toolbar}){
			unless($shutter_tool->{_toolbar}->get_show_arrow){
				$shutter_tool->{_toolbar}->set_show_arrow(TRUE);
			}
		}
	
	}elsif($mode eq 'hide'){

		#save current position of main window
		( $window->{x}, $window->{y} ) = $window->get_position;

		$window->hide;
		
		$is_hidden = TRUE;
		
	}
	
	return TRUE;
}

sub fct_create_tab {
	my ( $key, $is_all ) = @_;

	my $vbox            = Gtk2::VBox->new( FALSE, 0 );
	my $vbox_tab        = Gtk2::VBox->new( FALSE, 0 );
	my $vbox_tab_event  = Gtk2::EventBox->new;
	my $vbox_all        = Gtk2::VBox->new( FALSE, 0 );
	my $hbox_all        = Gtk2::HBox->new( FALSE, 0 );
	my $vbox_all2       = Gtk2::VBox->new( FALSE, 0 );
	my $vbox_fileinfos  = Gtk2::VBox->new( FALSE, 0 );

	unless ($is_all) {
		my $filename_label = Gtk2::Label->new;
		$filename_label->set_markup( "<b>" . $d->get("Filename") . "</b>" );
		$session_screens{$key}->{'filename_label'} = Gtk2::Label->new();
		$session_screens{$key}->{'filename_label'}->set_line_wrap(TRUE);
		$session_screens{$key}->{'filename_label'}->set_line_wrap_mode ('char');
		$session_screens{$key}->{'filename_label'}->set_width_chars (20);
		$session_screens{$key}->{'filename_label'}->set_single_line_mode(FALSE);

		my $folder_label = Gtk2::Label->new;
		$folder_label->set_markup( "<b>" . $d->get("Directory") . "</b>" );
		$session_screens{$key}->{'folder_label'} = Gtk2::Label->new();
		$session_screens{$key}->{'folder_label'}->set_line_wrap(TRUE);
		$session_screens{$key}->{'folder_label'}->set_line_wrap_mode ('char');
		$session_screens{$key}->{'folder_label'}->set_width_chars (20);
		$session_screens{$key}->{'folder_label'}->set_single_line_mode(FALSE);

		my $mime_type_label = Gtk2::Label->new;
		$mime_type_label->set_markup( "<b>" . $d->get("Mime-Type") . "</b>" );
		$session_screens{$key}->{'mime_type_label'} = Gtk2::Label->new();

		my $size_label = Gtk2::Label->new;
		$size_label->set_markup( "<b>" . $d->get("Filesize") . "</b>" );
		$session_screens{$key}->{'size_label'} = Gtk2::Label->new();

		my $geometry_label = Gtk2::Label->new;
		$geometry_label->set_markup( "<b>" . $d->get("Geometry") . "</b>" );
		$session_screens{$key}->{'geometry_label'} = Gtk2::Label->new();

		#Gtk2::ImageView - empty at first
		$session_screens{$key}->{'image'} = Gtk2::ImageView->new();
		$session_screens{$key}->{'image'}->set_interpolation ('tiles');	
		
		#Gtk2::ImageView::ScrollWin
		my $image_sw = Gtk2::ImageView::ScrollWin->new($session_screens{$key}->{'image'});
		$image_sw->set_size_request(50, -1);

		#WORKAROUND
		#upstream bug
		#http://trac.bjourne.webfactional.com/ticket/21						
		#left  => zoom in
		#right => zoom out
		$session_screens{$key}->{'image'}->signal_connect('scroll-event', sub{
			my ($view, $ev) = @_;		
			if($ev->direction eq 'left'){
				$ev->direction('up');
			}elsif($ev->direction eq 'right'){
				$ev->direction('down');
			}
			return FALSE;
		});
		
		$session_screens{$key}->{'image'}->signal_connect('button-press-event', sub{
			my ($view, $ev) = @_;
			if($ev->button == 1 && $ev->type eq '2button-press'){
				&fct_zoom_best;	
				return TRUE;
			}else{
				return FALSE;	
			}					
		});
		
		#packing
		#~ my $tab_infos_sizegroup = Gtk2::SizeGroup->new('vertical');
		#~ $tab_infos_sizegroup->add_widget( $session_screens{$key}->{'filename_label'} );
		#~ $tab_infos_sizegroup->add_widget( $session_screens{$key}->{'folder_label'} );
		#~ $tab_infos_sizegroup->add_widget( $session_screens{$key}->{'size_label'} );
		#~ $tab_infos_sizegroup->add_widget( $session_screens{$key}->{'mime_type_label'} );
		#~ $tab_infos_sizegroup->add_widget( $session_screens{$key}->{'geometry_label'} );

		#~ $session_screens{$key}->{'filename_label'}->set_alignment( 0, 0.5 );
		#~ $session_screens{$key}->{'folder_label'}->set_alignment( 0, 0.5 );
		#~ $session_screens{$key}->{'mime_type_label'}->set_alignment( 0, 0.5 );
		#~ $session_screens{$key}->{'size_label'}->set_alignment( 0, 0.5 );
		#~ $session_screens{$key}->{'geometry_label'}->set_alignment( 0, 0.5 );

		#~ $filename_label->set_alignment( 0, 0.5 );
		#~ $folder_label->set_alignment( 0, 0.5 );
		#~ $mime_type_label->set_alignment( 0, 0.5 );
		#~ $size_label->set_alignment( 0, 0.5 );
		#~ $geometry_label->set_alignment( 0, 0.5 );

		$vbox_fileinfos->pack_start( $filename_label,                             FALSE, TRUE, 5 );
		$vbox_fileinfos->pack_start( $session_screens{$key}->{'filename_label'},  FALSE, TRUE, 2 );
		$vbox_fileinfos->pack_start( $folder_label,                               FALSE, TRUE, 5 );
		$vbox_fileinfos->pack_start( $session_screens{$key}->{'folder_label'},    FALSE, TRUE, 2 );
		$vbox_fileinfos->pack_start( $size_label,                                 FALSE, TRUE, 10 );
		$vbox_fileinfos->pack_start( $session_screens{$key}->{'size_label'},      FALSE, TRUE, 2 );
		$vbox_fileinfos->pack_start( $mime_type_label,                            FALSE, TRUE, 10 );
		$vbox_fileinfos->pack_start( $session_screens{$key}->{'mime_type_label'}, FALSE, TRUE, 2 );
		$vbox_fileinfos->pack_start( $geometry_label,                             FALSE, TRUE, 10 );
		$vbox_fileinfos->pack_start( $session_screens{$key}->{'geometry_label'},  FALSE, TRUE, 2 );

		my $hpaned = Gtk2::HPaned->new;
		$hpaned->add1($vbox_fileinfos);
		$hpaned->pack2($image_sw, TRUE, FALSE);

		$vbox_tab->pack_start( $hpaned, TRUE, TRUE, 0 );

		$vbox->pack_start_defaults($vbox_tab);
		
		#pack vbox into an event box so we can listen
		#to various key and button events
		$vbox_tab_event->add($vbox);
		$vbox_tab_event->show_all;
		$vbox_tab_event->signal_connect('button-press-event', \&evt_tab_button_press, $key);
		
		return $vbox_tab_event;

	} else {
		my $stats_label = Gtk2::Label->new;
		$stats_label->set_markup( "<b>" . $d->get("Statistic") . "</b>" );

		$session_start_screen{'first_page'}->{'statistics_counter'} = Gtk2::Label->new(
			$notebook->get_n_pages . " " . $d->nget( "screenshot during this session", "screenshots during this session", $notebook->get_n_pages ) );

		$session_start_screen{'first_page'}->{'size_counter'}
			= Gtk2::Label->new( $d->get("Total size") . ": " . $shutter_hfunct->utf8_decode( Gnome2::VFS->format_file_size_for_display(0) ) );

		$vbox_all->pack_start( $stats_label,                                                FALSE, TRUE, 1 );
		$vbox_all->pack_start( $session_start_screen{'first_page'}->{'statistics_counter'}, FALSE, TRUE, 1 );
		$vbox_all->pack_start( $session_start_screen{'first_page'}->{'size_counter'},       FALSE, TRUE, 1 );

		$session_start_screen{'first_page'}->{'settings_label'} = Gtk2::Label->new;
		$session_start_screen{'first_page'}->{'settings_label'}->set_markup( "<b>" . $d->get("Current Preferences") . "</b>" );

		$vbox_all2->pack_start_defaults( $session_start_screen{'first_page'}->{'settings_label'} );

		$session_start_screen{'first_page'}->{'filename_label'} = Gtk2::Label->new( $d->get("Filename") . ": " );
		$session_start_screen{'first_page'}->{'folder_label'}   = Gtk2::Label->new( $d->get("Directory") . ": " );

		my $tab_all_sizegroup = Gtk2::SizeGroup->new('vertical');
		$tab_all_sizegroup->add_widget( $session_start_screen{'first_page'}->{'filename_label'} );
		$tab_all_sizegroup->add_widget( $session_start_screen{'first_page'}->{'folder_label'} );

		$vbox_all2->pack_start_defaults( $session_start_screen{'first_page'}->{'filename_label'} );
		$vbox_all2->pack_start_defaults( $session_start_screen{'first_page'}->{'folder_label'} );

		#create iconview for session
		$session_start_screen{'first_page'}->{'model'} = Gtk2::ListStore->new( 'Gtk2::Gdk::Pixbuf', 'Glib::String', 'Glib::String' );
		$session_start_screen{'first_page'}->{'view'} = Gtk2::IconView->new_with_model($session_start_screen{'first_page'}->{'model'});
		$session_start_screen{'first_page'}->{'view'}->set_orientation('horizontal');
		$session_start_screen{'first_page'}->{'view'}->set_pixbuf_column(0);
		$session_start_screen{'first_page'}->{'view'}->set_text_column(1);
		$session_start_screen{'first_page'}->{'view'}->set_selection_mode('multiple');
		$session_start_screen{'first_page'}->{'view'}->set_columns(0);
		$session_start_screen{'first_page'}->{'view'}->signal_connect( 'selection-changed', \&evt_iconview_sel_changed,    'sel_changed' );
		$session_start_screen{'first_page'}->{'view'}->signal_connect( 'item-activated',    \&evt_iconview_item_activated, 'item_activated' );

		$hbox_all->pack_start_defaults($vbox_all);
		$hbox_all->pack_start_defaults($vbox_all2);
		$vbox_tab->pack_start( $hbox_all, FALSE, TRUE, 0 );

		my $scrolled_window_view = Gtk2::ScrolledWindow->new;
		$scrolled_window_view->set_policy( 'automatic', 'automatic' );
		$scrolled_window_view->set_shadow_type('in');
		$scrolled_window_view->add($session_start_screen{'first_page'}->{'view'});

		#add an event box to show a context menu on right-click
		my $view_event = Gtk2::EventBox->new;
		$view_event->add($scrolled_window_view);
		$view_event->signal_connect( 'button-press-event', \&evt_iconview_button_press, $session_start_screen{'first_page'}->{'view'} );

		$vbox_tab->pack_start( $view_event, TRUE, TRUE, 0 );

		$vbox->pack_start_defaults($vbox_tab);
		$vbox->show_all;

		return $vbox;

	}

}

sub fct_save_settings {
	my ($profilename) = @_;

	#settings file
	my $settingsfile = "$ENV{ HOME }/.shutter/settings.xml";
	if ( defined $profilename ) {
		$settingsfile = "$ENV{ HOME }/.shutter/profiles/$profilename.xml"
			if ( $profilename ne "" );
	}

	#session file
	my $sessionfile = "$ENV{ HOME }/.shutter/session.xml";

	#accounts file
	my $accountsfile = "$ENV{ HOME }/.shutter/accounts.xml";
	if ( defined $profilename ) {
		$accountsfile = "$ENV{ HOME }/.shutter/profiles/$profilename\_accounts.xml"
			if ( $profilename ne "" );
	}

	#we store the version info, so we know if there was a new version installed
	#when starting new version we clear the cache on first startup
	$settings{'general'}->{'app_version'} = SHUTTER_VERSION . REV;

	$settings{'general'}->{'last_profile'}      = $combobox_settings_profiles->get_active;
	$settings{'general'}->{'last_profile_name'} = $combobox_settings_profiles->get_active_text || "";

	$settings{'general'}->{'filetype'} = $combobox_type->get_active;
	$settings{'general'}->{'quality'}  = $scale->get_value();
	$settings{'general'}->{'filename'} = $filename->get_text();
	$settings{'general'}->{'folder'} = $saveDir_button->get_filename();

	#wrksp -> submenu
	$settings{'general'}->{'current_monitor_active'} = $current_monitor_active->get_active;

	$settings{'general'}->{'selection_tool'} = 1
		if $tool_advanced->get_active;
	$settings{'general'}->{'selection_tool'} = 2
		if $tool_simple->get_active;

	$settings{'general'}->{'zoom_active'} = $zoom_active->get_active();
	$settings{'general'}->{'zoom_size'}   = 1
		if ( $zoom_size1->get_active );
	$settings{'general'}->{'zoom_size'} = 2
		if ( $zoom_size2->get_active );
	$settings{'general'}->{'zoom_size'} = 3
		if ( $zoom_size3->get_active );

	#determining timeout
	if($gnome_web_photo){
		my $web_menu = $shutter_tool->{_web}->get_menu;
		my @timeouts = $web_menu->get_children;
		my $timeout  = undef;
		foreach (@timeouts) {

			if ( $_->get_active ) {
				$timeout = $_->get_children->get_text;
				$timeout =~ /([0-9]+)/;
				$timeout = $1;
			}
		}
		$settings{'general'}->{'web_timeout'} = $timeout;
	}	

	my $model         = $progname->get_model();
	my $progname_iter = $progname->get_active_iter();

	if ( defined $progname_iter ) {
		my $progname_value = $model->get_value( $progname_iter, 1 );
		$settings{'general'}->{'prog'} = $progname_value;
	}

	$settings{'general'}->{'prog_active'}      = $progname_active->get_active();
	$settings{'general'}->{'im_colors'}        = $combobox_im_colors->get_active();
	$settings{'general'}->{'im_colors_active'} = $im_colors_active->get_active();
	$settings{'general'}->{'delay'}            = $delay->get_value();
	$settings{'general'}->{'delay_active'}     = $delay_active->get_active();
	$settings{'general'}->{'thumbnail'}        = $thumbnail->get_value();
	$settings{'general'}->{'thumbnail_active'} = $thumbnail_active->get_active();
	$settings{'general'}->{'border'}           = $combobox_border->get_active();
	$settings{'general'}->{'cursor'}           = $combobox_cursor->get_active();
	$settings{'general'}->{'autohide'}         = $hide_active->get_active();
	$settings{'general'}->{'autocopy'}         = $autocopy_active->get_active();
	$settings{'general'}->{'close_at_close'}   = $close_at_close_active->get_active();
	#~ $settings{'general'}->{'save_at_close'}    = $save_at_close_active->get_active();
	$settings{'general'}->{'keybinding'}       = $keybinding_active->get_active();
	$settings{'general'}->{'keybinding_sel'}   = $keybinding_sel_active->get_active();
	$settings{'general'}->{'keybinding_mode'}  = $combobox_keybinding_mode->get_active();
	$settings{'general'}->{'capture_key'}      = $capture_key->get_text();
	$settings{'general'}->{'capture_sel_key'}  = $capture_sel_key->get_text();

	#ftp upload
	$settings{'general'}->{'ftp_uri'}      = $ftp_remote_entry->get_text();
	$settings{'general'}->{'ftp_mode'}     = $ftp_mode_combo->get_active();
	$settings{'general'}->{'ftp_username'} = $ftp_username_entry->get_text();
	$settings{'general'}->{'ftp_password'} = $ftp_password_entry->get_text();
	
	#plugins
	foreach my $plugin_key ( sort keys %plugins ) {	
		$settings{'plugins'}->{$plugin_key}->{'name'}        = $plugin_key;
		$settings{'plugins'}->{$plugin_key}->{'binary'}      = $plugins{$plugin_key}->{'binary'};
		$settings{'plugins'}->{$plugin_key}->{'name_plugin'} = $plugins{$plugin_key}->{'name'};
		$settings{'plugins'}->{$plugin_key}->{'category'}    = $plugins{$plugin_key}->{'category'};
		
		#keep newlines => switch them to <![CDATA[<br>]]> tags
		#the load routine does it the other way round
		my $temp_tooltip = $plugins{$plugin_key}->{'tooltip'};
		$temp_tooltip =~ s/\n/\<\!\[CDATA\[\<br\>\]\]\>/g;
		$settings{'plugins'}->{$plugin_key}->{'tooltip'}     = $temp_tooltip;
		$settings{'plugins'}->{$plugin_key}->{'lang'}        = $plugins{$plugin_key}->{'lang'};
		$settings{'plugins'}->{$plugin_key}->{'recent'}      = $plugins{$plugin_key}->{'recent'} if defined $plugins{$plugin_key}->{'recent'};
	}

	#settings
	eval {
		my ( $tmpfh, $tmpfilename ) = tempfile(UNLINK => 1);
		XMLout( \%settings, OutputFile => $tmpfilename);
		#and finally move the file
		mv($tmpfilename, $settingsfile);
	};
	if ($@) {
		$shutter_dialog->dlg_error_message( $@, $d->get("Settings could not be saved!") );
	}else{
		&dlg_status_message( 1, $d->get("Settings saved successfully!") );
	}

	#we need to clean the hashkeys, so they become parseable
	my %clean_files;
	my $counter = 0;
	foreach ( Sort::Naturally::nsort(keys %session_screens) ) {

		next unless exists $session_screens{$_}->{'long'};

		#8 leading zeros to counter
		$counter = sprintf( "%08d", $counter );
		if ( $shutter_hfunct->file_exists( $session_screens{$_}->{'long'} ) ) {
			$clean_files{ "file" . $counter }{'filename'} = $session_screens{$_}->{'long'};
			$counter++;
		}
	}
	
	#session
	eval {
		my ( $tmpfh, $tmpfilename ) = tempfile(UNLINK => 1);	
		XMLout( \%clean_files, OutputFile => $tmpfilename );
		#and finally move the file
		mv($tmpfilename, $sessionfile);
	};
	if ($@) {
		$shutter_dialog->dlg_error_message( $@, $d->get("Session could not be saved!") );
	}

	#accounts
	my %clean_accounts;
	foreach ( keys %accounts ) {
		$clean_accounts{$_}->{'host'} 			= $accounts{$_}->{'host'};
		$clean_accounts{$_}->{'password'} 		= $accounts{$_}->{'password'};
		$clean_accounts{$_}->{'username'} 		= $accounts{$_}->{'username'};
	}

	eval {
		my ( $tmpfh, $tmpfilename ) = tempfile(UNLINK => 1);	
		XMLout( \%clean_accounts, OutputFile => $tmpfilename );
		#and finally move the file
		mv($tmpfilename, $accountsfile);
	};
	if ($@) {
		$shutter_dialog->dlg_error_message( $@, $d->get("Account-settings could not be saved!") );
	}

	#keybindings
	&fct_save_bindings($capture_key->get_text, $capture_sel_key->get_text);	

	return TRUE;
}

sub fct_save_bindings {
	my $key 	= shift;
	my $skey 	= shift;
	
	#~ #COMPIZ VIA DBus	
	#~ my $bus		= undef;
	#~ my $compiz 	= undef;
	#~ my $cs 		= undef;
	#~ my $cs_k  	= undef;
	#~ my $cws     = undef;
	#~ my $cws_k  	= undef;
	
	#~ eval{
		#~ $bus = Net::DBus->find;
		#~ 
		#~ #Get a handle to the compiz service
		#~ $compiz = $bus->get_service("org.freedesktop.compiz");
#~ 
		#~ # Get the relevant objects object
		#~ $cs = $compiz->get_object("/org/freedesktop/compiz/gnomecompat/allscreens/command_screenshot",
									 #~ "org.freedesktop.compiz");
		#~ 
		#~ $cs_k = $compiz->get_object("/org/freedesktop/compiz/gnomecompat/allscreens/run_command_screenshot_key",
									 #~ "org.freedesktop.compiz");
#~ 
		#~ $cws = $compiz->get_object("/org/freedesktop/compiz/gnomecompat/allscreens/command_window_screenshot",
									 #~ "org.freedesktop.compiz");
		#~ 
		#~ $cws_k = $compiz->get_object("/org/freedesktop/compiz/gnomecompat/allscreens/run_command_window_screenshot_key",
									 #~ "org.freedesktop.compiz");
	#~ };
	#~ if($@){
		#~ warn "WARNING: DBus connection to org.freedesktop.compiz failed --> setting keyboard shortcuts may not work when using compiz\n\n";
		#~ warn $@ . "\n\n";
	#~ }

	#GCONF
	my $client        = Gnome2::GConf::Client->get_default;
	my $shortcut_full = "/apps/metacity/global_keybindings/run_command_screenshot";
	my $shortcut_sel  = "/apps/metacity/global_keybindings/run_command_window_screenshot";
	my $command_full  = "/apps/metacity/keybinding_commands/command_screenshot";
	my $command_sel   = "/apps/metacity/keybinding_commands/command_window_screenshot";

	eval{
		#set values
		if ( $keybinding_active->get_active() ) {
			
			$client->set( $command_full, { type => 'string', value => "$shutter_path --full" } );
			$client->set( $shortcut_full, { type  => 'string', value => $key } );
			
			#compiz if available
			#~ if(defined $cs && defined $cs_k){
				#~ $cs->set(dbus_string "$shutter_path --full");
				#~ 
				#~ #currently not needed because keys are copied from gconf
				#~ $cs_k->set(dbus_string $key);
			#~ }
			
		} else {
			
			$client->set( $command_full,  { type => 'string', value => 'gnome-screenshot', } );
			$client->set( $shortcut_full, { type => 'string', value => 'Print', } );

			#compiz if available
			#~ if(defined $cs && defined $cs_k){
				#~ $cs->set(dbus_string 'gnome-screenshot');
				#~ 
				#~ #currently not needed because keys are copied from gconf
				#~ $cs_k->set(dbus_string 'Print');
			#~ }	

		}
		
		if ( $keybinding_sel_active->get_active() ) {
			
			my $mode = undef;
			if ( $combobox_keybinding_mode->get_active() == 0 ) {
				$mode = "--selection";
			} elsif ( $combobox_keybinding_mode->get_active() == 1 ) {
				$mode = "--window";
			} elsif ( $combobox_keybinding_mode->get_active() == 2 ) {
				$mode = "--section";
			} else {
				$mode = "--window";
			}
			
			$client->set( $command_sel, { type  => 'string', value => "$shutter_path $mode" } );
			$client->set( $shortcut_sel, { type  => 'string', value => $skey } );
			
			#compiz if available
			#~ if(defined $cws && defined $cws_k){
				#~ $cws->set(dbus_string "$shutter_path $mode");
				#~ 
				#~ #currently not needed because keys are copied from gconf
				#~ $cws_k->set(dbus_string $skey);
			#~ }

		} else {
			
			$client->set( $command_sel, { type  => 'string', value => 'gnome-screenshot --window' } );
			$client->set( $shortcut_sel, { type => 'string', value => '<Alt>Print' } );
			
			#compiz if available
			#~ if(defined $cws && defined $cws_k){
				#~ $cws->set(dbus_string 'gnome-screenshot --window');
#~ 
				#~ #currently not needed because keys are copied from gconf
				#~ $cws_k->set(dbus_string '<Alt>Print');
			#~ }	
			
		}

	};
	if($@){
		#show error message
		#~ my $response = $shutter_dialog->dlg_error_message( 
			#~ $@,
			#~ $d->get(  "There was an error configuring the keybindings." )
		#~ );				
	}

	return TRUE;
}

sub fct_load_settings {
	my ( $data, $profilename ) = @_;

	#settings file
	my $settingsfile = "$ENV{ HOME }/.shutter/settings.xml";
	$settingsfile = "$ENV{ HOME }/.shutter/profiles/$profilename.xml"
		if ( defined $profilename );

	my $settings_xml;
	if ( $shutter_hfunct->file_exists($settingsfile) ) {
		eval {
			$settings_xml = XMLin( IO::File->new($settingsfile) );

			if ( $data eq 'profile_load' ) {

				#migration from gscrot to shutter
				#maybe we can drop this in future releases
				# 0 := jpeg
				# 1 := png
				unless(defined $settings_xml->{'general'}->{'app_version'}){
					if($settings_xml->{'general'}->{'filetype'} == 0){
						$combobox_type->set_active($int_jpeg);			
					}elsif($settings_xml->{'general'}->{'filetype'} == 1){
						$combobox_type->set_active($int_png);		
					}
				#shutter
				}else{
					$combobox_type->set_active($settings_xml->{'general'}->{'filetype'});	
				}

				$scale->set_value( $settings_xml->{'general'}->{'quality'} );
				utf8::decode $settings_xml->{'general'}->{'filename'};
				$filename->set_text( $settings_xml->{'general'}->{'filename'} );

				utf8::decode $settings_xml->{'general'}->{'folder'};
				$saveDir_button->set_filename( $settings_xml->{'general'}->{'folder'} );

				#FIXME
				#this is a dirty hack to force the setting to be enabled in session tab
				#at the moment i simply dont know why the filechooser "caches" the old value
				# => weird...
				$settings_xml->{'general'}->{'folder_force'} = TRUE;

				#wrksp -> submenu
				$current_monitor_active->set_active( $settings_xml->{'general'}->{'current_monitor_active'} );

				#selection tool -> submenu
				$tool_advanced->set_active(TRUE)
					if $settings_xml->{'general'}->{'selection_tool'} == 1;
				$tool_simple->set_active(TRUE)
					if $settings_xml->{'general'}->{'selection_tool'} == 2;
				$zoom_active->set_active( $settings_xml->{'general'}->{'zoom_active'} );
				$zoom_size1->set_active(TRUE)
					if $settings_xml->{'general'}->{'zoom_size'} == 1;
				$zoom_size2->set_active(TRUE)
					if $settings_xml->{'general'}->{'zoom_size'} == 2;
				$zoom_size3->set_active(TRUE)
					if $settings_xml->{'general'}->{'zoom_size'} == 3;

				#determining timeout
				my $web_menu = $shutter_tool->{_web}->get_menu;
				my @timeouts = $web_menu->get_children;
				my $timeout  = undef;
				foreach (@timeouts) {
					$timeout = $_->get_children->get_text;
					$timeout =~ /([0-9]+)/;
					$timeout = $1;
					if ( $settings_xml->{'general'}->{'web_timeout'} == $timeout ) {
						$_->set_active(TRUE);
					}
				}

				#advanced settings
				my $model = $progname->get_model;
				utf8::decode $settings_xml->{'general'}->{'prog'};
				$model->foreach( \&fct_iter_programs, $settings_xml->{'general'}->{'prog'} );
				$progname_active->set_active( $settings_xml->{'general'}->{'prog_active'} );
				$im_colors_active->set_active( $settings_xml->{'general'}->{'im_colors_active'} );
				$combobox_im_colors->set_active( $settings_xml->{'general'}->{'im_colors'} );
				$delay->set_value( $settings_xml->{'general'}->{'delay'} );
				$delay_active->set_active( $settings_xml->{'general'}->{'delay_active'} );
				$thumbnail->set_value( $settings_xml->{'general'}->{'thumbnail'} );
				$thumbnail_active->set_active( $settings_xml->{'general'}->{'thumbnail_active'} );
				$combobox_border->set_active( $settings_xml->{'general'}->{'border'} );
				$combobox_cursor->set_active( $settings_xml->{'general'}->{'cursor'} );

				#behavior
				$hide_active->set_active( $settings_xml->{'general'}->{'autohide'} );
				$autocopy_active->set_active( $settings_xml->{'general'}->{'autocopy'} );
				$close_at_close_active->set_active( $settings_xml->{'general'}->{'close_at_close'} );
				#~ $save_at_close_active->set_active( $settings_xml->{'general'}->{'save_at_close'} );

				#keybindings
				$keybinding_active->set_active( $settings_xml->{'general'}->{'keybinding'} );
				$keybinding_sel_active->set_active( $settings_xml->{'general'}->{'keybinding_sel'} );

				utf8::decode $settings_xml->{'general'}->{'capture_key'};
				utf8::decode $settings_xml->{'general'}->{'capture_sel_key'};
				
				$capture_key->set_text( $settings_xml->{'general'}->{'capture_key'} );
				$capture_sel_key->set_text( $settings_xml->{'general'}->{'capture_sel_key'} );
				$combobox_keybinding_mode->set_active( $settings_xml->{'general'}->{'keybinding_mode'} );

				#ftp_upload
				utf8::decode $settings_xml->{'general'}->{'ftp_uri'};
				utf8::decode $settings_xml->{'general'}->{'ftp_mode'};
				utf8::decode $settings_xml->{'general'}->{'ftp_username'};
				utf8::decode $settings_xml->{'general'}->{'ftp_password'};
				
				$ftp_remote_entry->set_text( $settings_xml->{'general'}->{'ftp_uri'} );
				$ftp_mode_combo->set_active( $settings_xml->{'general'}->{'ftp_mode'} );
				$ftp_username_entry->set_text( $settings_xml->{'general'}->{'ftp_username'} );
				$ftp_password_entry->set_text( $settings_xml->{'general'}->{'ftp_password'} );

				#load account data from profile
				&fct_load_accounts($profilename);
				if ( defined $accounts_tree ) {
					&fct_load_accounts_tree;
					$accounts_tree->set_model($accounts_model);
					&fct_set_model_accounts($accounts_tree);
				}

			#endif profile load
			}else{
							
				#we store the version info, so we know if there was a new version installed
				#when starting new version we clear the cache on first startup
				if (defined $settings_xml->{'general'}->{'app_version'}){
					if(SHUTTER_VERSION . REV ne $settings_xml->{'general'}->{'app_version'}){
						$shutter_common->set_clear_cache(TRUE);
					}	
				}else{
					$shutter_common->set_clear_cache(TRUE);
				}

				#get plugins from cache unless param is set to ignore it
				if ( !$shutter_common->get_clear_cache ) {

					foreach my $plugin_key ( sort keys %{ $settings_xml->{'plugins'} } ) {
						utf8::decode $settings_xml->{'plugins'}->{$plugin_key}->{'binary'};

						#check if plugin still exists in filesystem
						if ( $shutter_hfunct->file_exists( $settings_xml->{'plugins'}->{$plugin_key}->{'binary'} ) ) {
							
							#restore newlines <![CDATA[<br>]]> tags => \n
							$settings_xml->{'plugins'}->{$plugin_key}->{'tooltip'} =~ s/\<\!\[CDATA\[\<br\>\]\]\>/\n/g;
							
							utf8::decode $settings_xml->{'plugins'}->{$plugin_key}->{'name_plugin'};
							utf8::decode $settings_xml->{'plugins'}->{$plugin_key}->{'category'};
							utf8::decode $settings_xml->{'plugins'}->{$plugin_key}->{'tooltip'};
							utf8::decode $settings_xml->{'plugins'}->{$plugin_key}->{'lang'};
							$plugins{$plugin_key}->{'binary'}   = $settings_xml->{'plugins'}->{$plugin_key}->{'binary'};
							$plugins{$plugin_key}->{'name'}     = $settings_xml->{'plugins'}->{$plugin_key}->{'name_plugin'};
							$plugins{$plugin_key}->{'category'} = $settings_xml->{'plugins'}->{$plugin_key}->{'category'};
							$plugins{$plugin_key}->{'tooltip'}  = $settings_xml->{'plugins'}->{$plugin_key}->{'tooltip'};
							$plugins{$plugin_key}->{'lang'}     = $settings_xml->{'plugins'}->{$plugin_key}->{'lang'} || "shell";
							$plugins{$plugin_key}->{'recent'}   = $settings_xml->{'plugins'}->{$plugin_key}->{'recent'};
						} else {
							next;
						}
					}

				}

			} 

		};
		if ($@) {
			$shutter_dialog->dlg_error_message( $@, $d->get("Settings could not be restored!") );
			unlink $settingsfile;
		}else{
			&dlg_status_message( 1, $d->get("Settings loaded successfully") );				
		}			

	} #endif file exists

	return $settings_xml;
}

sub fct_get_program_model {
	my $model = Gtk2::ListStore->new( 'Gtk2::Gdk::Pixbuf', 'Glib::String', 'Glib::Scalar' );

	my $icontheme = Gtk2::IconTheme->get_for_screen( Gtk2::Gdk::Screen->get_default );

	#FIXME - use png as default mime type (is this clever enough?)
	my ( $default, @mapps ) = File::MimeInfo::Applications::mime_applications('image/png');
	
	#currently we use File::MimeInfo::Applications and Gnome2::VFS::Mime::Type
	#because of the following error
	#
	#libgnomevfs-WARNING **: 
	#Cannot call gnome_vfs_mime_application_get_icon 
	#with a GNOMEVFSMimeApplication structure constructed 
	#by the deprecated application registry 
	my $mime_type = Gnome2::VFS::Mime::Type->new ('image/png');
	my @apps = $mime_type->get_all_applications();
	
	#no app determined!
	unless (scalar @apps && scalar @mapps){
		return $model;			
	}

	#find icon and app
	#we use File::DesktopEntry instead of the Gnome one
	#for opening files
	foreach my $mapp (@mapps){
		foreach my $app (@apps){
			
			$app->{'name'} = $shutter_hfunct->utf8_decode($app->{'name'});
			
			#FIXME - kde apps do not support the freedesktop standards (.desktop files)
			#we simply cut the kde* / kde4* substring here
			#is it possible to get the wrong app if there 
			#is the kde3 and the kde4 version of an app installed?
			#
			#I think so ;-)
			$app->{'id'} =~ s/^(kde4|kde)-//g;
			if($mapp->{'file'} =~ m/$app->{'id'}/){
				my $icon_pixbuf;
				my $icon_name = $mapp->Icon;
				if($icon_name){
					#cut image formats
					$icon_name =~ s/(.png|.svg|.gif|.jpeg|.jpg)//g;				
					if ( $icontheme->has_icon( $icon_name ) ) {
						my ( $iw, $ih ) = Gtk2::IconSize->lookup('menu');
						$icon_pixbuf = $icontheme->load_icon( $icon_name, $ih, 'generic-fallback' );
					}else{
						$icon_pixbuf = undef;	
					}
				}else{
					$icon_pixbuf = undef;
				}
				$model->set( $model->append, 0, $icon_pixbuf, 1, $app->{'name'}, 2, $mapp );
				last;
			}	
		}
	}

	return $model;
}

sub fct_load_accounts {
	my ($profilename) = @_;

	#accounts file
	my $accountsfile = "$ENV{ HOME }/.shutter/accounts.xml";
	$accountsfile = "$ENV{ HOME }/.shutter/profiles/$profilename\_accounts.xml"
		if ( defined $profilename );

	my $accounts_xml;
	eval { $accounts_xml = XMLin( IO::File->new($accountsfile) ) if $shutter_hfunct->file_exists($accountsfile); };

	if ($@) {
		$shutter_dialog->dlg_error_message( $@, $d->get("Account-settings could not be restored!") );
		unlink $accountsfile;
	}

	#account data, load defaults if nothing is set
	unless ( exists( $accounts_xml->{'ubuntu-pics.de'} ) ) {
		$accounts{'ubuntu-pics.de'}->{host}     = "ubuntu-pics.de";
		$accounts{'ubuntu-pics.de'}->{username} = "";
		$accounts{'ubuntu-pics.de'}->{password} = "";
	} else {
		$accounts{'ubuntu-pics.de'}->{host}     = $accounts_xml->{'ubuntu-pics.de'}->{host};
		$accounts{'ubuntu-pics.de'}->{username} = $accounts_xml->{'ubuntu-pics.de'}->{username};
		$accounts{'ubuntu-pics.de'}->{password} = $accounts_xml->{'ubuntu-pics.de'}->{password};
	}

	$accounts{'ubuntu-pics.de'}->{register} = "http://www.ubuntu-pics.de/registrieren.html";

	#account data, load defaults if nothing is set
	unless ( exists( $accounts_xml->{'imageshack.us'} ) ) {
		$accounts{'imageshack.us'}->{host}     = "imageshack.us";
		$accounts{'imageshack.us'}->{username} = "";
		$accounts{'imageshack.us'}->{password} = "";
	} else {
		$accounts{'imageshack.us'}->{host}     = $accounts_xml->{'imageshack.us'}->{host};
		$accounts{'imageshack.us'}->{username} = $accounts_xml->{'imageshack.us'}->{username};
		$accounts{'imageshack.us'}->{password} = $accounts_xml->{'imageshack.us'}->{password};
	}

	$accounts{'imageshack.us'}->{register} = "http://my.imageshack.us/registration/";

	unless ( exists( $accounts_xml->{'imagebanana.com'} ) ) {
		$accounts{'imagebanana.com'}->{host}     = "imagebanana.com";
		$accounts{'imagebanana.com'}->{username} = "";
		$accounts{'imagebanana.com'}->{password} = "";
	} else {
		$accounts{'imagebanana.com'}->{host}     = $accounts_xml->{'imagebanana.com'}->{host};
		$accounts{'imagebanana.com'}->{username} = $accounts_xml->{'imagebanana.com'}->{username};
		$accounts{'imagebanana.com'}->{password} = $accounts_xml->{'imagebanana.com'}->{password};
	}

	$accounts{'imagebanana.com'}->{register} = "http://www.imagebanana.com/myib/registrieren/";

	foreach ( keys %accounts ) {
		utf8::decode $accounts{$_}->{'host'};
		utf8::decode $accounts{$_}->{'username'};
		utf8::decode $accounts{$_}->{'password'};
		$accounts{$_}->{'register_color'} = "blue";
		$accounts{$_}->{'register_text'}  = $d->get("click me");
	}

	return TRUE;
}

sub fct_open_files {
	my (@new_files) = @_;

	return FALSE if scalar(@new_files) < 1;

	my $open_dialog = Gtk2::MessageDialog->new( $window, [qw/modal destroy-with-parent/], 'info', 'close', $d->get("Loading files") );

	$open_dialog->set_title("Shutter");

	$open_dialog->set( 'secondary-text' => $d->get("Please wait while your selected files\nare being integrated into Shutter") . "." );

	$open_dialog->signal_connect( response => sub { $_[0]->destroy } );

	my $open_progress = Gtk2::ProgressBar->new;
	$open_progress->set_no_show_all(TRUE);
	$open_progress->set_ellipsize('middle');
	$open_progress->set_orientation('left-to-right');
	$open_progress->set_fraction(0);

	$open_dialog->vbox->add($open_progress);

	#do not show when min at startup
	unless ( $shutter_common->get_min ) {
		$open_progress->show;
		$open_dialog->show_all;
	}

	my $num_files = scalar(@new_files);
	my $count     = 0;
	foreach (@new_files) {

		my $new_uri = Gnome2::VFS::URI->new ($shutter_hfunct->utf8_decode(Gnome2::VFS->unescape_string($_)));

		#refresh the progressbar
		$count++;
		$open_progress->set_fraction( $count / $num_files );
		$open_progress->set_text($new_uri->to_string);

		#refresh tray icon
		if ( $icon && $icon->isa('Gtk2::StatusIcon') ) {
			$icon->set_blinking(TRUE);
		}

		#refresh gui
		&fct_update_gui;

		#do the real work
		if(&fct_integrate_screenshot_in_notebook( $new_uri, undef )){
			&dlg_status_message( 1, $new_uri->to_string . " " . $d->get("opened") );	
		}
	}
	$open_dialog->response('ok');

	#refresh tray icon
	if ( $icon && $icon->isa('Gtk2::StatusIcon') ) {
		$icon->set_blinking(FALSE);
	}

	return TRUE;
}

sub fct_load_session {

	#session file
	my $sessionfile = "$ENV{ HOME }/.shutter/session.xml";

	eval {
		my $session_xml = XMLin( IO::File->new($sessionfile) )
			if $shutter_hfunct->file_exists($sessionfile);

		return FALSE if scalar( keys %{$session_xml} ) < 1;

		my $restore_dialog = Gtk2::MessageDialog->new( $window, [qw/modal destroy-with-parent/], 'info', 'close', 'none' );

		$restore_dialog->set( 'text' => $d->get("Restoring session") );

		$restore_dialog->set( 'secondary-text' => $d->get("Please wait while your saved session is being restored") . "." );

		$restore_dialog->signal_connect( response => sub { $_[0]->destroy } );

		my $restore_progress = Gtk2::ProgressBar->new;
		$restore_progress->set_no_show_all(TRUE);
		$restore_progress->set_ellipsize('middle');
		$restore_progress->set_orientation('left-to-right');
		$restore_progress->set_fraction(0);

		$restore_dialog->vbox->add($restore_progress);

		#do not show when min at startup
		unless ( $shutter_common->get_min ) {
			$restore_progress->show;
			$restore_dialog->show_all;
			$restore_progress->grab_focus;
		}

		my $num_files = scalar( keys %{$session_xml} );
		my $count     = 0;
		foreach ( sort keys %{$session_xml} ) {

			#refresh the progressbar
			$count++;
			$restore_progress->set_fraction( $count / $num_files );
			$restore_progress->set_text( ${$session_xml}{$_}{'filename'} );

			#refresh tray icon
			if ( $icon && $icon->isa('Gtk2::StatusIcon') ) {
				$icon->set_blinking(TRUE);
			}

			#refresh gui
			&fct_update_gui;

			#do the real work
			my $new_uri = Gnome2::VFS::URI->new( ${$session_xml}{$_}{'filename'} );
			&fct_integrate_screenshot_in_notebook( $new_uri, undef );

		}
	
		$restore_dialog->response('ok');

		#refresh tray icon
		if ( $icon && $icon->isa('Gtk2::StatusIcon') ) {
			$icon->set_blinking(FALSE);			
		}
		
	};
	if ($@) {
		$shutter_dialog->dlg_error_message( $@, $d->get("Session could not be restored!") );

		unlink $sessionfile;

		#refresh tray icon
		if ( $icon && $icon->isa('Gtk2::StatusIcon') ) {
			$icon->set_blinking(FALSE);
		}

	}

	return TRUE;
}

sub fct_screenshot_exists {
	my ($key) = @_;

	#check if file still exists
	unless ( $session_screens{$key}->{'uri'}->exists ) {
		&dlg_status_message( 1, $session_screens{$key}->{'long'} . " " . $d->get("not found") );

		return FALSE;
	}
	return TRUE;
}

sub fct_delete {

	my $key = &fct_get_current_file;

	#single file
	if ($key) {

		if ( $session_screens{$key}->{'uri'}->exists ) {

			#cancel handle
			if ( exists $session_screens{$key}->{'handle'} ) {
				
				$session_screens{$key}->{'handle'}->cancel;
			}

			#find trash directory
			my $trash_uri = Gnome2::VFS->find_directory( Gnome2::VFS::URI->new( $ENV{'HOME'} ), 'trash', TRUE, TRUE, 755 );

			#move to trash
			$trash_uri = $trash_uri->append_file_name( $session_screens{$key}->{'short'} );
			$session_screens{$key}->{'uri'}->move( $trash_uri, TRUE ) if $session_screens{$key}->{'uri'}->exists;

		}

		$notebook->remove_page( $notebook->get_current_page );    #delete tab
		&dlg_status_message( 1, $session_screens{$key}->{'long'} . " " . $d->get("deleted") )
			if defined( $session_screens{$key}->{'long'} );

		if(defined $session_screens{$key}->{'iter'} && $session_start_screen{'first_page'}->{'model'}->iter_is_valid($session_screens{$key}->{'iter'})){
			$session_start_screen{'first_page'}->{'model'}->remove( $session_screens{$key}->{'iter'} );
		}

		#~ #very, very defensive cleanup
		#~ #currently i don't know if that makes any sense?		
		#~ foreach(keys %{$session_screens{$key}}){
			#~ eval { 
				#~ if($session_screens{$key}->{$_}->can('isa')){
					#~ print "Destroying: ".$_."\n";# if $session_screens{$key}->{$_}->isa('Glib::Object');
					#~ $session_screens{$key}->{$_}->free;
				#~ }
			#~ };
			#~ delete $session_screens{$key}->{$_};
		#~ }

		delete $session_screens{$key};

		$window->show_all unless $is_hidden;

		#session tab
	} else {

		my @to_delete;
		$session_start_screen{'first_page'}->{'view'}->selected_foreach(
			sub {
				my ( $view, $path ) = @_;
				my $iter = $session_start_screen{'first_page'}->{'model'}->get_iter($path);
				if ( defined $iter ) {
					my $key = $session_start_screen{'first_page'}->{'model'}->get_value( $iter, 2 );
					$notebook->remove_page( $notebook->page_num( $session_screens{$key}->{'tab_child'} ) );
					
					if ( $session_screens{$key}->{'uri'}->exists ) {

						#cancel handle
						if ( exists $session_screens{$key}->{'handle'} ) {
							
							$session_screens{$key}->{'handle'}->cancel;
						}

						#find trash directory
						my $trash_uri = Gnome2::VFS->find_directory( Gnome2::VFS::URI->new( $ENV{'HOME'} ), 'trash', TRUE, TRUE, 755 );

						#move to trash
						$trash_uri = $trash_uri->append_file_name( $session_screens{$key}->{'short'} );
						$session_screens{$key}->{'uri'}->move( $trash_uri, TRUE );

					}

					#copy to array
					#we delete the files from hash and model 
					#when exiting the sub 
					push @to_delete, $key; 

				}
			},
			undef
		);
		
		#delete from hash and model
		foreach my $key (@to_delete){
			if(defined $session_screens{$key}->{'iter'} && $session_start_screen{'first_page'}->{'model'}->iter_is_valid($session_screens{$key}->{'iter'})){
				$session_start_screen{'first_page'}->{'model'}->remove( $session_screens{$key}->{'iter'} );
			}

			delete $session_screens{$key};
		}

		&dlg_status_message( 1, $d->get("Selected screenshots deleted") );

		$window->show_all unless $is_hidden;

	}

	&fct_update_first_tab;

	return TRUE;
}

sub fct_remove_all {

	foreach my $key ( keys %session_screens ) {
		if ( exists $session_screens{$key}->{'handle'} ) {

			#cancel handle
			$session_screens{$key}->{'handle'}->cancel;
		}

		$notebook->remove_page( $notebook->page_num( $session_screens{$key}->{'tab_child'} ) );

		if(defined $session_screens{$key}->{'iter'} && $session_start_screen{'first_page'}->{'model'}->iter_is_valid($session_screens{$key}->{'iter'})){
			$session_start_screen{'first_page'}->{'model'}->remove( $session_screens{$key}->{'iter'} );
		}

		delete( $session_screens{$key} );
	}

	&dlg_status_message( 1, $d->get("All screenshots removed") );
	$window->show_all unless $is_hidden;

	&fct_update_first_tab;

	return TRUE;
}

sub fct_remove {
	my $key = shift;

	$key = &fct_get_current_file unless $key;

	#single file
	if ($key) {

		if ( exists $session_screens{$key}->{'handle'} ) {

			#cancel handle
			$session_screens{$key}->{'handle'}->cancel;
		}

		$notebook->remove_page( $notebook->page_num( $session_screens{$key}->{'tab_child'} ) );    #delete tab
		&dlg_status_message( 1, $session_screens{$key}->{'long'} . " " . $d->get("removed from session") )
			if defined( $session_screens{$key}->{'long'} );

		if(defined $session_screens{$key}->{'iter'} && $session_start_screen{'first_page'}->{'model'}->iter_is_valid($session_screens{$key}->{'iter'})){
			$session_start_screen{'first_page'}->{'model'}->remove( $session_screens{$key}->{'iter'} );
		}

		delete( $session_screens{$key} );                                                          # delete from hash

		$window->show_all unless $is_hidden;

	} else {
		
		my @to_remove;
		$session_start_screen{'first_page'}->{'view'}->selected_foreach(
			sub {
				my ( $view, $path ) = @_;
				my $iter = $session_start_screen{'first_page'}->{'model'}->get_iter($path);
				if ( defined $iter ) {
					my $key = $session_start_screen{'first_page'}->{'model'}->get_value( $iter, 2 );

					if ( exists $session_screens{$key}->{'handle'} ) {

						#cancel handle
						$session_screens{$key}->{'handle'}->cancel;
					}

					$notebook->remove_page( $notebook->page_num( $session_screens{$key}->{'tab_child'} ) );

					#copy to array
					#we remove the files from hash and model 
					#when exiting the sub 
					push @to_remove, $key; 

				}
			},
			undef
		);

		#delete from hash and model
		foreach my $key (@to_remove){
			if(defined $session_screens{$key}->{'iter'} && $session_start_screen{'first_page'}->{'model'}->iter_is_valid($session_screens{$key}->{'iter'})){
				$session_start_screen{'first_page'}->{'model'}->remove( $session_screens{$key}->{'iter'} );
			}

			delete $session_screens{$key};
		}

		&dlg_status_message( 1, $d->get("Selected screenshots removed") );

		$window->show_all unless $is_hidden;

	}

	&fct_update_first_tab;

	return TRUE;
}

sub fct_update_gui {

	while ( Gtk2->events_pending ) {
		Gtk2->main_iteration;
	}
	Gtk2::Gdk->flush;

	return TRUE;
}

sub fct_clipboard {
	my ($widget, $mode) = @_;

	my $key = &fct_get_current_file;

	#single file
	if ($key) {

		return FALSE unless &fct_screenshot_exists($key);

		if($mode eq 'image'){
			my $pixbuf = Gtk2::Gdk::Pixbuf->new_from_file( $session_screens{$key}->{'long'} );
			$clipboard->set_image( $pixbuf );
		}else{
			$clipboard->set_text( $session_screens{$key}->{'long'} );	
		}
			
		&dlg_status_message( 1, $session_screens{$key}->{'long'} . " " . $d->get("copied to clipboard") );

	}
	return TRUE;
}

sub fct_select_all {

	$session_start_screen{'first_page'}->{'view'}->select_all;

	return TRUE;
}

sub fct_plugin {

	my $key = &fct_get_current_file;

	my @plugin_array;

	#single file
	if ($key) {

		return FALSE unless &fct_screenshot_exists($key);

		unless ( keys %plugins > 0 ) {
			$shutter_dialog->dlg_error_message( $d->get("No plugin installed"), $d->get("Failed") );
		} else {
			push( @plugin_array, $key );
			&dlg_plugin(@plugin_array);
		}

		#session tab
	} else {

		$session_start_screen{'first_page'}->{'view'}->selected_foreach(
			sub {
				my ( $view, $path ) = @_;
				my $iter = $session_start_screen{'first_page'}->{'model'}->get_iter($path);
				if ( defined $iter ) {
					my $key = $session_start_screen{'first_page'}->{'model'}->get_value( $iter, 2 );
					push( @plugin_array, $key );
				}

			},
			undef
		);
		&dlg_plugin(@plugin_array);
	}
	return TRUE;
}

sub fct_rename {

	my $key = &fct_get_current_file;

	my @rename_array;

	#single file
	if ($key) {

		return FALSE unless &fct_screenshot_exists($key);

		print "Renaming of file " . $session_screens{$key}->{'long'} . " started\n"
			if $shutter_common->get_debug;
		push (@rename_array, $key);
	
	} else {
		$session_start_screen{'first_page'}->{'view'}->selected_foreach(
			sub {
				my ( $view, $path ) = @_;
				my $iter = $session_start_screen{'first_page'}->{'model'}->get_iter($path);
				if ( defined $iter ) {
					my $key = $session_start_screen{'first_page'}->{'model'}->get_value( $iter, 2 );
					push (@rename_array, $key);
				}
			},
			undef
		);
	}

	&dlg_rename(@rename_array);

	return TRUE;
}

sub fct_draw {

	my $key = &fct_get_current_file;

	my @draw_array;

	#single file
	if ($key) {

		return FALSE unless &fct_screenshot_exists($key);
		push (@draw_array, $key);

	} else {
		$session_start_screen{'first_page'}->{'view'}->selected_foreach(
			sub {
				my ( $view, $path ) = @_;
				my $iter = $session_start_screen{'first_page'}->{'model'}->get_iter($path);
				if ( defined $iter ) {
					my $key = $session_start_screen{'first_page'}->{'model'}->get_value( $iter, 2 );
					push (@draw_array, $key);
				}
			},
			undef
		);
	}

	#open drawing tool
	foreach my $key (@draw_array){
		my $drawing_tool = Shutter::Draw::DrawingTool->new($shutter_common, $view_d, $selector_d, $dragger_d);
		$drawing_tool->show( $session_screens{$key}->{'long'}, $session_screens{$key}->{'filetype'}, \%session_screens );		
	}

	&fct_control_main_window (TRUE, 'show');

	return TRUE;
}

sub fct_take_screenshot {
	my ( $widget, $data, $folder_from_config ) = @_;

	#disable signal-handler
	$SIG{USR1}  = 'IGNORE';
	$SIG{USR2}  = 'IGNORE';
	$SIG{RTMIN} = 'IGNORE';
	$SIG{RTMAX} = 'IGNORE';

	my $quality_value             = $scale->get_value();
	my $delay_value               = undef;
	my $thumbnail_value           = $thumbnail->get_value;
	my $filename_value            = undef;
	my $filetype_value            = undef;
	my $folder                    = undef;
	my $screenshot                = undef;
	my $screenshot_name           = undef;
	my $screenshot_thumbnail      = undef;
	my $screenshot_thumbnail_name = undef;
	my $thumbnail_ending          = "thumb";
	print "\n$data was emitted by widget $widget\n"
		if $shutter_common->get_debug;
	
	#determine current file type (name - description)
	$combobox_type->get_active_text =~ /(.*) -/;
	$filetype_value = $1;
	unless ($filetype_value) {
		$shutter_dialog->dlg_error_message( $d->get("No valid filetype specified"), $d->get("Failed") );
		&fct_control_main_window( TRUE, 'show' );
		return FALSE;
	}

	#determine folder to save
	$folder = $saveDir_button->get_filename || $folder_from_config;
	utf8::decode $folder;

	if ( $delay_active->get_active ) {
		$delay_value = $delay->get_value;
	} else {
		$delay_value = 0;
	}

	#prepare filename, parse wild-cards
	$filename_value = $filename->get_text();
	utf8::decode $filename_value;
	$filename_value = strftime $filename_value , localtime;

	#get next filename (auto increment using a wild card or manually)
	my $uri = &fct_get_next_filename( $filename_value, $folder, $filetype_value );

	#no valid filename was determined, exit here
	unless($uri){
		my $response = $shutter_dialog->dlg_error_message( 
			$d->get( "There was an error determining the filename." ),
			$d->get("Failed") 
		);		
		&fct_control_main_window( TRUE, 'show' );
		return FALSE;
	}

	#fullscreen screenshot
	if ( $data eq "raw" || $data eq "tray_raw" ) {
		my $wnck_screen = Gnome2::Wnck::Screen->get_default;
		unless ( $filename_value =~ /[a-zA-Z0-9]+/
			&& defined($folder)
			&& defined($filetype_value) )
		{
			$shutter_dialog->dlg_error_message( 
				$d->get("No valid filename specified"), 
				$d->get("Failed") 
			);
			&fct_control_main_window( TRUE, 'show');
			return FALSE;
		}

		my $screenshooter = Shutter::Screenshot::Workspace->new(
			$shutter_common, $combobox_cursor->get_active,
			$delay_value, $wnck_screen->get_active_workspace,
			undef, undef, $current_monitor_active->get_active
		);
		$screenshot = $screenshooter->workspace();
		undef $screenshooter;

		#window
	} elsif ( $data eq "window"
		|| $data eq "tray_window"
		|| $data eq "section"
		|| $data eq "tray_section" )
	{
		unless ( $filename_value =~ /[a-zA-Z0-9]+/ ) {
			$shutter_dialog->dlg_error_message( $d->get("No valid filename specified"), $d->get("Failed") );
			&fct_control_main_window( TRUE, 'show');
			return FALSE;
		}

		my $screenshooter = Shutter::Screenshot::Window->new(
			$shutter_common, $combobox_cursor->get_active, $delay_value, 
			$combobox_border->get_active, undef, $data, $is_hidden
		);
		$screenshot = $screenshooter->window();

		#selection
	} elsif ( $data eq "select" || $data eq "tray_select" ) {
		unless ( $filename_value =~ /[a-zA-Z0-9]+/ ) {
			$shutter_dialog->dlg_error_message( $d->get("No valid filename specified"), $d->get("Failed") );
			&fct_control_main_window( TRUE, 'show');
			return FALSE;
		}
		if ( $tool_advanced->get_active ) {
					
			my $screenshooter = Shutter::Screenshot::SelectorAdvanced->new( $shutter_common, $combobox_cursor->get_active, $delay_value, $view, $selector, $dragger, $nav );
			$screenshot = $screenshooter->select_advanced();

		} else {

			my $zoom_size_factor = 1;
			$zoom_size_factor = 2 if ( $zoom_size2->get_active );
			$zoom_size_factor = 3 if ( $zoom_size3->get_active );
			my $screenshooter = Shutter::Screenshot::SelectorSimple->new( $shutter_common, $combobox_cursor->get_active,
				$delay_value, $zoom_size_factor, $zoom_active->get_active );
			$screenshot = $screenshooter->select_simple();

		}

		#web
	} elsif ( $data eq "web" || $data eq "tray_web" ) {

		$screenshot = &dlg_website( $uri->get_path(), $filetype_value, $quality_value );
		if ( $screenshot && $screenshot =~ /[a-zA-Z]/ ) {
			#error if $screenshot is not a Gtk2::Gdk::Pixbuf
			unless($screenshot =~ /Gtk2::Gdk::Pixbuf/){
				$shutter_dialog->dlg_error_message( $d->get("Unable to capture website"), 
													$d->get("Failed"),
													undef, undef,
													undef, undef,
													undef, undef,
													$screenshot );
				&dlg_status_message( 1, $d->get("Unable to capture website"), $d->get("Failed") );
				&fct_control_main_window( TRUE, 'show');
				return FALSE;
			}
		}else{
			$screenshot = 5;	
		}
		
	} elsif ( $data =~ /^shutter_window_direct(.*)/ ) {
		
		my $xid = $1;
		print "Selected xid: $xid\n" if $shutter_common->get_debug;
		unless ( $filename_value =~ /[a-zA-Z0-9]+/ ) {
			$shutter_dialog->dlg_error_message( $d->get("No valid filename specified"), $d->get("Failed") );
			&fct_control_main_window( TRUE, 'show');
			return FALSE;
		}
		my $screenshooter = Shutter::Screenshot::Window->new( 
				$shutter_common, $combobox_cursor->get_active, $delay_value, 
				$combobox_border->get_active, $xid, $data, $is_hidden );
		$screenshot = $screenshooter->window_by_xid();

	} elsif ( $data =~ /^shutter_wrksp_direct/ ) {

		#we need to handle different wm, e.g. metacity, compiz here
		my $selected_workspace = undef;
		my $vpx                = undef;
		my $vpy                = undef;

		#compiz
		if ( $data =~ /compiz(\d*)x(\d*)/ ) {
			$vpx = $1;
			$vpy = $2;
			print "Sel. Viewport: $vpx, $vpy\n" if $shutter_common->get_debug;

			#metacity etc.
		} elsif ( $data =~ /shutter_wrksp_direct(.*)/ ) {
			$selected_workspace = $1;
			print "Sel. Workspace: $selected_workspace\n"
				if $shutter_common->get_debug;
		}

		unless ( $filename_value =~ /[a-zA-Z0-9]+/ ) {
			$shutter_dialog->dlg_error_message( $d->get("No valid filename specified"), $d->get("Failed") );
			&fct_control_main_window( TRUE, 'show');
			return FALSE;
		}
		my $screenshooter = Shutter::Screenshot::Workspace->new( $shutter_common, $combobox_cursor->get_active,
			$delay_value, $selected_workspace, $vpx, $vpy, $current_monitor_active->get_active );
		$screenshot = $screenshooter->workspace();

	}

	#screenshot was taken at this stage...
	#start postprocessing here

	#...successfully???
	unless ($screenshot) {
			
		#show error dialog
		my $response = $shutter_dialog->dlg_error_message( 
			$d->get( "Maybe mouse pointer could not be grabbed or the selected area is invalid." ),
			$d->get( "Error while taking the screenshot." )
		);
			
		&dlg_status_message( 1, $d->get("Error while taking the screenshot.") );
		&fct_control_main_window( TRUE, 'show');
		return FALSE;
	} else {

		#user aborted screenshot
		if ( $screenshot == 5 ) {
			&dlg_status_message( 1, $d->get("Capture aborted by user") );
			&fct_control_main_window( TRUE, 'show');
			return FALSE;
		}

		#we have to use the path (e.g. /home/username/file1.png)
		#so we can save the screenshot_properly
		$screenshot_name = $uri->get_path;
		#maybe / is set as uri (get_path returns undef)
		#in this case nothing is returned when using get_path
		#we use the directory name and the short name in this case
		#(anyway - most users won't have permissions to write to /)
		$screenshot_name = "/". $uri->extract_short_name unless $screenshot_name;
		
		#parse wild cards
		my $swidth  = $screenshot->get_width;
		my $sheight = $screenshot->get_height;

		$screenshot_name =~ s/\%24w/$swidth/g;
		$screenshot_name =~ s/\%24h/$sheight/g;

		#update uri after parsing as well, so we can check if file exists for example
		$uri = Gnome2::VFS::URI->new ($screenshot_name);
		
		#maybe the uri already exists, so we have to append some digits (e.g. testfile01(0002).png)
		#we don't do this when taking a web screenshot,
		#because gnome-web-photo creates the file immediately
		#we would save two files in this case 
		#because the new file would always "exist"
		if($data ne "web" && $data ne "tray_web"){
			if ( $uri->exists ) {
				my $count             = 1;
				my $filename_value = fileparse( $uri->get_path, '\..*' );
				my $existing_filename = $filename_value;
				while ( $uri->exists ) {
					$filename_value = $existing_filename . "(" . sprintf( "%03d", $count++ ) . ")";
					$uri 	= Gnome2::VFS::URI->new($folder);
					$uri    = $uri->append_string("$filename_value.$filetype_value");
					print "Checking new uri after parsing: " . $uri->to_string . "\n" if $shutter_common->get_debug;
				}
			}
		}
		
		#we have to update the path again
		$screenshot_name = $uri->get_path();

		print "Trying to save file to $screenshot_name\n"
			if $shutter_common->get_debug;

		#finally save pixbuf
		unless ($shutter_pix->save_pixbuf_to_file($screenshot, $screenshot_name, $screenshot_name, $filetype_value, $quality_value)){
			&fct_control_main_window( TRUE, 'show');
			return FALSE;			
		}

	}    #end screenshot successfull
	if ( $uri->exists ) {

		#quantize
		if ( $im_colors_active->get_active ) {
			my $colors;
			if($combobox_im_colors->get_active == 0){
				$colors = 16;
			}elsif($combobox_im_colors->get_active == 1){
				$colors = 64;
			}elsif($combobox_im_colors->get_active == 2){
				$colors = 256;
			}
			&fct_imagemagick_perform( 'reduce_colors', $screenshot_name, $colors );
		}

		#generate the thumbnail
		if ( $thumbnail_active->get_active ) {

			#calculate size
			my $twidth  = int( $screenshot->get_width *  ( $thumbnail_value / 100 ) );
			my $theight = int( $screenshot->get_height * ( $thumbnail_value / 100 ) );

			#create thumbail
			$screenshot_thumbnail = Gtk2::Gdk::Pixbuf->new_from_file_at_scale( $screenshot_name, $twidth, $theight, TRUE );

			#save path of thumbnail
			my ($name, $folder, $ext) = fileparse( $uri->get_path, '\..*' );
			$screenshot_thumbnail_name = $folder . "/$name-$thumbnail_ending.$filetype_value";

			#parse wild cards
			$screenshot_thumbnail_name =~ s/\%24w/$twidth/g;
			$screenshot_thumbnail_name =~ s/\%24h/$theight/g;

			print "Trying to save file to $screenshot_thumbnail_name\n"
				if $shutter_common->get_debug;

			#finally save pixbuf
			unless($shutter_pix->save_pixbuf_to_file($screenshot_thumbnail, $screenshot_thumbnail_name, $screenshot_thumbnail_name, $filetype_value, $quality_value)){
				&fct_control_main_window( TRUE, 'show');
				return FALSE;			
			}

		}

		#integrate it into the notebook
		my $new_key_screenshot = &fct_integrate_screenshot_in_notebook( $uri, $screenshot );

		#thumbnail as well if present
		my $new_key_screenshot_thumbnail = &fct_integrate_screenshot_in_notebook( Gnome2::VFS::URI->new($screenshot_thumbnail_name), $screenshot_thumbnail )
			if $thumbnail_active->get_active;

		#autocopy to clipboard if configured
		if ( $autocopy_active->get_active() ) {
			$clipboard->set_image($screenshot);
		}

		#open screenshot with configured program
		if ( $progname_active->get_active ) {
			my $progname_value 	= undef;
			my $appname_value  	= undef;
			my $model         	= $progname->get_model();
			my $progname_iter 	= $progname->get_active_iter();
			if ($progname_iter) {
				$progname_value = $model->get_value( $progname_iter, 2 );
				$appname_value 	= $model->get_value( $progname_iter, 1 );
			}
			&fct_open_with_program($progname_value, $appname_value);
		}
		print "screenshot successfully saved to $screenshot_name!\n"
			if $shutter_common->get_debug;
		&dlg_status_message( 1, "$session_screens{$new_key_screenshot}->{'short'} " . $d->get("saved") );
	} else {
		#show error dialog
		my $response = $shutter_dialog->dlg_error_message( 
			$d->get( "Maybe mouse pointer could not be grabbed or the selected area is invalid." ),
			$d->get( "Error while taking the screenshot." )
		);
		&dlg_status_message( 1, $d->get("Error while taking the screenshot.") );
	}

	&fct_control_main_window( TRUE, 'show');

	undef $screenshot;
	undef $screenshot_thumbnail;

	return TRUE;
}

sub fct_upload {

	my $key = &fct_get_current_file;

	my @upload_array;

	#single file
	if ($key) {

		return FALSE unless &fct_screenshot_exists($key);
		push( @upload_array, $session_screens{$key}->{'long'} );
		&dlg_upload(@upload_array);

		#session tab
	} else {

		$session_start_screen{'first_page'}->{'view'}->selected_foreach(
			sub {
				my ( $view, $path ) = @_;
				my $iter = $session_start_screen{'first_page'}->{'model'}->get_iter($path);
				if ( defined $iter ) {
					my $key = $session_start_screen{'first_page'}->{'model'}->get_value( $iter, 2 );
					return FALSE unless &fct_screenshot_exists($key);
					push( @upload_array, $session_screens{$key}->{'long'} );
				}

			},
			undef
		);
		&dlg_upload(@upload_array);
	}
	return TRUE;
}

sub fct_print {

	my $key = &fct_get_current_file;

	my @pages;
	unless ($key) {
		$session_start_screen{'first_page'}->{'view'}->selected_foreach(
			sub {
				my ( $view, $path ) = @_;
				my $iter = $session_start_screen{'first_page'}->{'model'}->get_iter($path);
				if ( defined $iter ) {
					my $key = $session_start_screen{'first_page'}->{'model'}->get_value( $iter, 2 );
					push( @pages, $session_screens{$key}->{'long'} );
				}

			}
		);
	} else {
		push( @pages, $session_screens{$key}->{'long'} );
	}

	my $op = Gtk2::PrintOperation->new;
	$op->set_job_name( SHUTTER_NAME . " - " . SHUTTER_VERSION . " - " . localtime );
	$op->set_n_pages( scalar @pages );
	$op->set_unit('pixel');
	$op->set_show_progress(TRUE);
	$op->set_default_page_setup($pagesetup);

	#restore settings if prossible
	if ( $shutter_hfunct->file_exists("$ENV{ HOME }/.shutter/printing.xml") ) {
		eval {
			my $ssettings = Gtk2::PrintSettings->new_from_file("$ENV{ HOME }/.shutter/printing.xml");
			$op->set_print_settings($ssettings);
		};
	}

	$op->signal_connect(
		'status-changed' => sub {
			my $op = shift;
			&dlg_status_message( 1, $op->get_status_string );
		}
	);

	$op->signal_connect(
		'draw-page' => sub {
			my $op  = shift;
			my $pc  = shift;
			my $int = shift;

			#manip cairo context
			my $cr = $pc->get_cairo_context;

			#see if pixbuf fits on the printing area
			my $pixbuf = Gtk2::Gdk::Pixbuf->new_from_file( $pages[$int] );
			if ( $pc->get_width < $pixbuf->get_width || $pc->get_height < $pixbuf->get_height ) {
				$pixbuf = Gtk2::Gdk::Pixbuf->new_from_file_at_scale( $pages[$int], $pc->get_width, $pc->get_height, TRUE );
			}

			Gtk2::Gdk::Cairo::Context::set_source_pixbuf( $cr, $pixbuf, 0, 0 );

			$cr->paint;
		}
	);

	$op->run( 'print-dialog', $window );

	#save settings
	my $settings = $op->get_print_settings;
	eval { $settings->to_file("$ENV{ HOME }/.shutter/printing.xml"); };

	return TRUE;
}

sub fct_open_with_program {
	my $dentry 		= shift;
	my $trans_name 	= shift;

	#no program set - exit
	return FALSE unless $dentry;

	#trans_name is optional here,
	#we use the name of the desktop entry if 
	#trans_name is not present
	my $name = $trans_name || $dentry->Name;

	my $key = &fct_get_current_file;

	my $exec_call;
	#single file
	if ($key) {

		return FALSE unless &fct_screenshot_exists($key);

		#everything is fine -> open it
		if ( $dentry->wants_uris ) {
			$exec_call = $dentry->parse_Exec( $session_screens{$key}->{'uri'}->to_string );
		} else {
			$exec_call = $dentry->parse_Exec( $session_screens{$key}->{'long'} );
		}

		&dlg_status_message( 1, $session_screens{$key}->{'long'} . " " . $d->get("opened with") . " " . $name );

		#session tab
	} else {

		my @open_files;

		$session_start_screen{'first_page'}->{'view'}->selected_foreach(
			sub {
				my ( $view, $path ) = @_;
				my $iter = $session_start_screen{'first_page'}->{'model'}->get_iter($path);
				if ( defined $iter ) {
					my $key = $session_start_screen{'first_page'}->{'model'}->get_value( $iter, 2 );
					if ( $dentry->wants_uris ) {
						push @open_files, $session_screens{$key}->{'uri'}->to_string;
					} else {
						push @open_files, $session_screens{$key}->{'long'};
					}
				}
			},
			undef
		);
		if ( @open_files > 0 ) {
			if ( $dentry->wants_list ) {
				$exec_call = $dentry->parse_Exec(@open_files);
			} else {
				foreach my $file (@open_files) {
					$exec_call .= $dentry->parse_Exec($file) . ";";
				}
			}
			&dlg_status_message( 1, $d->get("Opened all files with") . " " . $name );
		}
	}

	if ($exec_call) {
		foreach ( split /;/, $exec_call ) {
			print Dumper $_ . " &" if $shutter_common->get_debug;
			system( $_ . " &" );
		}

	}
	return TRUE;
}

sub fct_execute_plugin {
	my $arrayref = $_[1];
	my ( $plugin_value, $plugin_name, $plugin_lang, $key, $plugin_dialog, $plugin_progress ) = @$arrayref;

	unless ( $shutter_hfunct->file_exists( $session_screens{$key}->{'long'} ) ) {
		return FALSE;
	}

	#if it is a native perl plugin, use a plug to integrate it properly
	if ( $plugin_lang eq "perl" ) {		
		#hide plugin dialog
		$plugin_dialog->hide if defined $plugin_dialog;

		#dialog to show the plugin
		my $sdialog = Gtk2::Dialog->new( $plugin_name, $window, [qw/modal destroy-with-parent/] );
		$sdialog->set_resizable(FALSE);
		$sdialog->set_has_separator(FALSE); 
		# Ensure that the dialog box is destroyed when the user responds.
		$sdialog->signal_connect (response => sub { $_[0]->destroy });

		#initiate the socket to draw the contents of the plugin to our dialog
		my $socket = Gtk2::Socket->new;
		$sdialog->vbox->add($socket);
		$socket->signal_connect(
			'plug-removed' => sub {
				$sdialog->destroy();
				return TRUE;
			}
		);
		
		printf( "\n", $socket->get_id );
		
		my $pid = fork;
		if ( $pid < 0 ) {
			$shutter_dialog->dlg_error_message( $d->get("Could not execute plugin") . ": " . $plugin_name, $d->get("Failed") );
		}
		if ( $pid == 0 ) {		
			exec(
				sprintf(
					"$^X $plugin_value %d '$session_screens{$key}->{'long'}' $session_screens{$key}->{'width'} $session_screens{$key}->{'height'} $session_screens{$key}->{'filetype'}\n",
					$socket->get_id )
			);
		}
				
		$sdialog->show_all;
		$sdialog->run;

		waitpid($pid, 0);
			
		#check exit code
		if($? == 0){
			&dlg_status_message( 1, $d->get("Successfully executed plugin") . ": " . $plugin_name );
		}elsif($? / 256 == 1 ){
			&dlg_status_message( 1, $d->get("Could not execute plugin") . ": " . $plugin_name );
		}
		
		#...if not => simple execute the plugin via system (e.g. shell plugins)
	} else {

		print
			"$plugin_value $session_screens{$key}->{'long'} $session_screens{$key}->{'width'} $session_screens{$key}->{'height'} $session_screens{$key}->{'filetype'} submitted to plugin\n"
			if $shutter_common->get_debug;
		
		#create a new process, so we are able to cancel the current operation
		my $plugin_process = Proc::Simple->new;

		$plugin_process->start(
			sub {
				system("'$plugin_value' '$session_screens{$key}->{'long'}' '$session_screens{$key}->{'width'}' '$session_screens{$key}->{'height'}' '$session_screens{$key}->{'filetype'}' ");				
				POSIX::_exit(0);
			}
		);
		
		#ignore delete-event during execute
		$plugin_dialog->signal_connect(
			'delete-event' => sub{
				return TRUE;		
			} 
		);

		#we are also able to show a little progress bar to give some feedback
		#to the user. there is no real progress because we are just executing a shell script
		while ( $plugin_process->poll ) {
			$plugin_progress->set_text($plugin_name." - ".$session_screens{$key}->{'short'});
			$plugin_progress->pulse;
			&fct_update_gui;
			usleep 100000;
		}

		&fct_update_gui;

		#finally show some status messages
		if ( $plugin_process->exit_status() == 0 ) {
			&dlg_status_message( 1, $d->get("Successfully executed plugin") . ": " . $plugin_name );
		}else{
			$shutter_dialog->dlg_error_message( $d->get("Could not execute plugin") . ": " . $plugin_name, $d->get("Failed") );
		}

	}

	return TRUE;
}

sub fct_update_first_tab {

	#FILE INFOS
	#--------------------------------------			
	$session_start_screen{'first_page'}->{'statistics_counter'}->set_text(
		scalar( keys(%session_screens) ) . " "
			. $d->nget( "screenshot during this session", "screenshots during this session", scalar( keys(%session_screens) ) ) );

	#handle total size in session
	my $total_size = 0;
	foreach ( keys %session_screens ) {
		next unless $session_screens{$_}->{'size'};
		$total_size += $session_screens{$_}->{'size'};
	}
	$session_start_screen{'first_page'}->{'size_counter'}
		->set_text( $d->get("Total size") . ": " . $shutter_hfunct->utf8_decode( Gnome2::VFS->format_file_size_for_display($total_size) ) );

	#SESSION AND SETTINGS INFO
	#--------------------------------------		
	if ( $filename && $saveDir_button && $combobox_settings_profiles ) {

		if ( $combobox_settings_profiles->get_active_text ) {
			#display text on label...
			$session_start_screen{'first_page'}->{'settings_label'}
				->set_markup( "<b>" . $d->get("Current Preferences") . "</b>" . " (" . $combobox_settings_profiles->get_active_text . ")" );
			#...and statusbar
			$status2->push(1, $d->get("Current Profile") . ": " . $combobox_settings_profiles->get_active_text);
		} else {
			$session_start_screen{'first_page'}->{'settings_label'}->set_markup( "<b>" . $d->get("Current Preferences") . "</b>" );
			$status2->push(1, "");
		}

		my $current_folder = $saveDir_button->get_filename;

		if ( $settings_xml->{'general'}->{'folder_force'} || !$current_folder ) {
			if ( exists $settings_xml->{'general'}->{'folder'} ) {
				$current_folder = $settings_xml->{'general'}->{'folder'};
			} else {
				$current_folder = $ENV{'HOME'};
			}
			$settings_xml->{'general'}->{'folder_force'} = FALSE;
		}

		if ( $filename->get_text ne "" ) {
			$session_start_screen{'first_page'}->{'filename_label'}->set_text( $d->get("Filename") . ": " . $filename->get_text );
		} else {
			$session_start_screen{'first_page'}->{'filename_label'}->set_text( $d->get("Filename") . ": -" );
		}

		$session_start_screen{'first_page'}->{'folder_label'}->set_text( $d->get("Directory") . ": " . $current_folder );
	}

	return TRUE;
}

sub fct_save_as {
	my (@keys) = @_;
	
	foreach my $key (@keys){
		
		my $fs = Gtk2::FileChooserDialog->new(
			$d->get("Choose a location to save to"),
			$window, 'save',
			'gtk-cancel' => 'reject',
			'gtk-save'   => 'accept'
		);

		$fs->set_current_folder( $session_screens{$key}->{'folder'} );
		$fs->set_current_name( $session_screens{$key}->{'short'} );

		my $extra_hbox = Gtk2::HBox->new;

		my $label_save_as_type = Gtk2::Label->new( $d->get("Image format") . ":" );

		my $combobox_save_as_type = Gtk2::ComboBox->new_text;

		#add supported formats to combobox
		#the user can decide to save in jpeg, png or bmp format
		my $counter = 0;
		my $png_counter = undef;
		foreach ( Gtk2::Gdk::Pixbuf->get_formats ) {
			
			#add all known formats to the dialog
			$combobox_save_as_type->insert_text( $counter, $_->{name} . " - " . $_->{description} );
			
			#set active when mime_type is matching
			#loop because multiple mime types are registered for fome file formats
			foreach my $mime (@{$_->{mime_types}}){
				$combobox_save_as_type->set_active($counter)
					if $mime eq $session_screens{$key}->{'mime_type'};		
				
				#save png_counter as well as fallback
				$png_counter = $counter if $mime eq 'image/png';
			}
			$counter++;
		}
		
		#something went wrong here
		#filetype was not detected automatically
		#set to png as default
		unless($combobox_save_as_type->get_active_text){
			if(defined $png_counter){
				$combobox_save_as_type->set_active($png_counter);
			}	
		}

		$combobox_save_as_type->signal_connect(
			'changed' => sub {
				my $filename = $fs->get_filename;

				my $choosen_format = $combobox_save_as_type->get_active_text;
				$choosen_format =~ s/ \-.*//;    #get png or jpeg for example
				#~ print $choosen_format . "\n";

				#parse filename
				my ( $short, $folder, $ext ) = fileparse( $filename, '\..*' );

				$fs->set_current_name( $short . "." . $choosen_format );
			}
		);

		$extra_hbox->pack_start( $label_save_as_type,    FALSE, FALSE, 5 );
		$extra_hbox->pack_start( $combobox_save_as_type, FALSE, FALSE, 5 );

		my $align_save_as_type = Gtk2::Alignment->new( 1, 0, 0, 0 );

		$align_save_as_type->add($extra_hbox);
		$align_save_as_type->show_all;

		$fs->set_extra_widget($align_save_as_type);

		my $fs_resp = $fs->run;

		if ( $fs_resp eq "accept" ) {
			my $filename = $fs->get_filename;

			#parse filename
			my ( $short, $folder, $ext ) = fileparse( $filename, '\..*' );

			#handle file format
			my $choosen_format = $combobox_save_as_type->get_active_text;
			$choosen_format =~ s/ \-.*//;    #get png or jpeg for example

			$filename = $folder . $short . "." . $choosen_format;

			unless ( $shutter_hfunct->file_exists($filename) ) {
				#save as (pixbuf, new_filename, filetype, quality - auto here, old_filename)
				my $pixbuf = Gtk2::Gdk::Pixbuf->new_from_file( $session_screens{$key}->{'long'} );
				if($shutter_pix->save_pixbuf_to_file($pixbuf, $filename, $session_screens{$key}->{'long'}, $choosen_format)){

					#cancel handle
					if ( exists $session_screens{$key}->{'handle'} ) {
						
						$session_screens{$key}->{'handle'}->cancel;
					}
					if(&fct_update_tab( $key, undef, Gnome2::VFS::URI->new($filename) )){
						#setup a new filemonitor, so we get noticed if the file changed
						&fct_add_file_monitor($key);

						&dlg_status_message( 1, "$session_screens{ $key }->{ 'long' } " . $d->get("saved") );
					}
					
				}
				
			} else {

				#ask the user to replace the image
				#replace button
				my $replace_btn = Gtk2::Button->new_with_mnemonic( $d->get("_Replace") );
				$replace_btn->set_image( Gtk2::Image->new_from_stock( 'gtk-save-as', 'button' ) );

				my $response = $shutter_dialog->dlg_warning_message(
					sprintf( $d->get("The image already exists in %s. Replacing it will overwrite its contents."), "'" . $folder . "'"),
					sprintf( $d->get( "An image named %s already exists. Do you want to replace it?"), "'" . $short.$ext . "'" ),
					undef, undef, undef,
					$replace_btn, undef, undef
				);

				if ( $response == 40 ) {
					my $pixbuf = Gtk2::Gdk::Pixbuf->new_from_file( $session_screens{$key}->{'long'} );
					if($shutter_pix->save_pixbuf_to_file($pixbuf, $filename, $session_screens{$key}->{'long'}, $choosen_format)){

						#cancel handle
						if ( exists $session_screens{$key}->{'handle'} ) {
							
							$session_screens{$key}->{'handle'}->cancel;
						}

						if(&fct_update_tab( $key, undef, Gnome2::VFS::URI->new($filename) )){

							#setup a new filemonitor, so we get noticed if the file changed
							&fct_add_file_monitor($key);

							#maybe file is in session as well, need to set the handler again ;-)
							foreach my $searchkey ( keys %session_screens ) {
								next if $key eq $searchkey;
								if ( $session_screens{$searchkey}->{'long'} eq $filename ) {
									$session_screens{$searchkey}->{'changed'} = TRUE;
									&fct_update_tab($searchkey);
								}
							}	

							&dlg_status_message( 1, "$session_screens{ $key }->{ 'long' } " . $d->get("saved") );					

						}

					}	

				}

			}

		} 	
	
		$fs->destroy();
		
	}
		
}

sub fct_get_file_by_index {
	my $index = shift;
	
	return unless $index;

	#get current page
    my $curr_page = $notebook->get_nth_page( $index );

	my $key = undef;
	#and loop through hash to find the corresponding key
	if($curr_page){
		foreach ( keys %session_screens ) {
			next unless ( exists $session_screens{$_}->{'tab_child'} );
			if ( $session_screens{$_}->{'tab_child'} == $curr_page ) {
				$key = $_;
				last;
			}
		}
	}
	
	return $key;
}

sub fct_get_current_file {

	#get current page
    my $curr_page = $notebook->get_nth_page( $notebook->get_current_page );

	my $key = undef;
	#and loop through hash to find the corresponding key
	if($curr_page){
		foreach ( keys %session_screens ) {
			next unless ( exists $session_screens{$_}->{'tab_child'} );
			if ( $session_screens{$_}->{'tab_child'} == $curr_page ) {
				$key = $_;
				last;
			}
		}
	}
	
	return $key;
}

sub fct_update_quick_profile_selector {
	my ($combobox_settings_profiles, $current_profiles_ref) = @_;

	#populate quick selector as well
	if(scalar @{$current_profiles_ref} > 0){
		$shutter_menu->{_menuitem_quicks}->set_sensitive(TRUE);
		$shutter_menu->{_menuitem_quicks}->set_submenu( fct_ret_profile_menu( $combobox_settings_profiles, $current_profiles_ref ) );
	}else{
		$shutter_menu->{_menuitem_quicks}->remove_submenu;
		$shutter_menu->{_menuitem_quicks}->set_sensitive(FALSE);
	}	
	return TRUE;
}

sub fct_update_tab {

	#mandatory
	my $key = shift;
	return FALSE unless $key;

	#optional, e.g.used by fct_integrate...
	my $pixbuf = shift;
	my $uri    = shift;

	$session_screens{$key}->{'uri'}      = $uri if $uri;
	$session_screens{$key}->{'mtime'} 	 = -1 unless $session_screens{$key}->{'mtime'};

	#something wrong here
	unless(defined $session_screens{$key}->{'uri'}){
		return FALSE;	
	}

	#sometimes there are some read errors
	#because the CHANGED signal gets emitted by the file monitor
	#but the file is still in use (e.g. plugin, external app)
	#we try to read the fileinfos and the file itsels several times
	#until throwing an error
	my $error_counter = 0;
	while($error_counter <= MAX_ERROR){

		my $fileinfo  = $session_screens{$key}->{'uri'}->get_file_info('default');

		#does the file exist?
		if($session_screens{$key}->{'uri'}->exists){
			
			#maybe we need no update
			if ($fileinfo->{'mtime'} == $session_screens{$key}->{'mtime'} && !$uri ){
				print "Updating fileinfos REJECTED for key: $key (not modified)\n" if $shutter_common->get_debug;			
				return TRUE;
			}

			print "Updating fileinfos for key: $key\n" if $shutter_common->get_debug;

			#FILEINFO
			#--------------------------------------
			$session_screens{$key}->{'mtime'}    = $fileinfo->{'mtime'};
			$session_screens{$key}->{'size'}     = $fileinfo->{'size'};

			$session_screens{$key}->{'short'}    = $session_screens{$key}->{'uri'}->extract_short_name;
			$session_screens{$key}->{'long'}     = $session_screens{$key}->{'uri'}->get_path;
			$session_screens{$key}->{'folder'}   = $session_screens{$key}->{'uri'}->extract_dirname;
			$session_screens{$key}->{'filetype'} = $session_screens{$key}->{'short'};
			$session_screens{$key}->{'filetype'} =~ s/.*\.//ig;

			#just the name
			$session_screens{$key}->{'name'} = $session_screens{$key}->{'short'};
			$session_screens{$key}->{'name'} =~ s/\.$session_screens{$key}->{'filetype'}//g;

			#mime type
			$session_screens{$key}->{'mime_type'} = Gnome2::VFS->get_mime_type_for_name( $session_screens{$key}->{'uri'}->to_string );

			#THUMBNAIL
			#--------------------------------------
			eval {

				#maybe we have a pixbuf already (e.g. after taking a screenshot)
				unless ($pixbuf) {
					$pixbuf = Gtk2::Gdk::Pixbuf->new_from_file( $session_screens{$key}->{'long'} );		
				}

			};
			if ($@) {

				#increment error counter 
				#and go to next try
				$error_counter++;
				sleep 1;
				#we need to reset the modification time
				#because the change would not be 
				#recognized otherwise
				$session_screens{$key}->{'mtime'} = -1;
				next;
			
			}else{

				#setting pixbuf
				$session_screens{$key}->{'image'}->set_pixbuf( $pixbuf );
				
				#UPDATE INFOS WHEN IDLE
				#--------------------------------------		
				Glib::Idle->add (sub{

					#get dimensions - using the pixbuf
					$session_screens{$key}->{'width'}  = $pixbuf->get_width;
					$session_screens{$key}->{'height'} = $pixbuf->get_height;

					#create tempfile
					#maybe we have to restore the file later
					my ( $tmpfh, $tmpfilename ) = tempfile(UNLINK => 1);
					$session_screens{$key}->{'temp'} = $tmpfilename;				
					cp($session_screens{$key}->{'long'}, $session_screens{$key}->{'temp'});						

					#update tab icon - and other GUI Elements
					my $thumb = $shutter_thumb->get_thumbnail(
						$session_screens{$key}->{'uri'}->to_string,
						$session_screens{$key}->{'mime_type'},
						$session_screens{$key}->{'mtime'},
						0.2
					);
					$session_screens{$key}->{'tab_icon'}->set_from_pixbuf( $thumb );

					$session_screens{$key}->{'filename_label'}->set_text( $session_screens{$key}->{'uri'}->extract_short_name );
					$tooltips->set_tip( $session_screens{$key}->{'filename_label'}, $session_screens{$key}->{'uri'}->to_string );

					$session_screens{$key}->{'folder_label'}->set_text( $session_screens{$key}->{'uri'}->extract_dirname );
					$tooltips->set_tip( $session_screens{$key}->{'folder_label'}, $session_screens{$key}->{'uri'}->extract_dirname );

					$session_screens{$key}->{'mime_type_label'}->set_text( $session_screens{$key}->{'mime_type'} );

					$session_screens{$key}->{'size_label'}->set_text( $shutter_hfunct->utf8_decode( Gnome2::VFS->format_file_size_for_display( $session_screens{$key}->{'size'} ) ) );

					$session_screens{$key}->{'geometry_label'}->set_text( $session_screens{$key}->{'width'} . "x" . $session_screens{$key}->{'height'} );

					#UPDATE FIRST TAB - VIEW
					#--------------------------------------				

					#update view icon
					my $thumb_view = $shutter_thumb->get_thumbnail(
						$session_screens{$key}->{'uri'}->to_string,
						$session_screens{$key}->{'mime_type'},
						$session_screens{$key}->{'mtime'},
						0.5
					);

					unless(defined $session_screens{$key}->{'iter'} && $session_start_screen{'first_page'}->{'model'}->iter_is_valid($session_screens{$key}->{'iter'})){
						$session_screens{$key}->{'iter'} = $session_start_screen{'first_page'}->{'model'}->append;
						$session_start_screen{'first_page'}->{'model'}->set( $session_screens{$key}->{'iter'}, 0, $thumb_view, 1, $session_screens{$key}->{'short'}, 2, $key );
					}else{
						$session_start_screen{'first_page'}->{'model'}->set( $session_screens{$key}->{'iter'}, 0, $thumb_view, 1, $session_screens{$key}->{'short'}, 2, $key );					
					}

					&fct_update_first_tab;

					return FALSE;
				});

				return TRUE;
						
			}
		
		#file does not exist
		}else{

			#mark file as deleted
			$session_screens{$key}->{'deleted'} = TRUE;	

			#we only handle one case here:
			#file was deleted in filesystem and we got informed about that...	
			my $response = $shutter_dialog->dlg_question_message(
				$d->get("Try to resave the file?"),
				sprintf( $d->get("Image %s was not found on disk"), "'" . $session_screens{$key}->{'long'} . "'" ),
				'gtk-discard', 'gtk-save'
			);
			
			#handle different responses
			if($response == 10){

				$notebook->remove_page( $notebook->page_num( $session_screens{$key}->{'tab_child'} ) );    #delete tab
				&dlg_status_message( 1, $session_screens{$key}->{'long'} . " " . $d->get("removed from session") )
					if defined( $session_screens{$key}->{'long'} );

				if(defined $session_screens{$key}->{'iter'} && $session_start_screen{'first_page'}->{'model'}->iter_is_valid($session_screens{$key}->{'iter'})){
					$session_start_screen{'first_page'}->{'model'}->remove( $session_screens{$key}->{'iter'} );
				}

				delete( $session_screens{$key} );    
				
			}elsif($response == 20){
				
				#try to resave the file
				my $pixbuf = Gtk2::Gdk::Pixbuf->new_from_file( $session_screens{$key}->{'temp'} );
				if($shutter_pix->save_pixbuf_to_file($pixbuf, $session_screens{$key}->{'long'}, $session_screens{$key}->{'long'}, $session_screens{$key}->{'filetype'})){

					#setup a new filemonitor, so we get noticed if the file changed
					&fct_add_file_monitor($key);

					&dlg_status_message( 1, $session_screens{$key}->{'long'} . " " . $d->get("saved"));
				
					&fct_update_first_tab;
					return TRUE;
				
				#resave failed => delete the screenshot	
				}else{

					$notebook->remove_page( $notebook->page_num( $session_screens{$key}->{'tab_child'} ) );    #delete tab
					&dlg_status_message( 1, $session_screens{$key}->{'long'} . " " . $d->get("removed from session") )
						if defined( $session_screens{$key}->{'long'} );

					if(defined $session_screens{$key}->{'iter'} && $session_start_screen{'first_page'}->{'model'}->iter_is_valid($session_screens{$key}->{'iter'})){
						$session_start_screen{'first_page'}->{'model'}->remove( $session_screens{$key}->{'iter'} );
					}

					delete( $session_screens{$key} );    				

				}	
			}
			
			&fct_update_first_tab;
			return FALSE;

		}	 
				
	}#end while($error_counter <= MAX_ERROR){

	#could not load the file => show an error message
	my $response = $shutter_dialog->dlg_error_message( 
		sprintf ( $d->get(  "Error while opening image %s." ), "'" . $session_screens{$key}->{'long'} . "'" ) ,
		$d->get( "There was an error opening the image." ),
		undef, undef, undef,
		undef, undef, undef,
		$@
	);	

	$notebook->remove_page( $notebook->page_num( $session_screens{$key}->{'tab_child'} ) );    #delete tab
	&dlg_status_message( 1, $session_screens{$key}->{'long'} . " " . $d->get("removed from session") )
		if defined( $session_screens{$key}->{'long'} );

	if(defined $session_screens{$key}->{'iter'} && $session_start_screen{'first_page'}->{'model'}->iter_is_valid($session_screens{$key}->{'iter'})){
		$session_start_screen{'first_page'}->{'model'}->remove( $session_screens{$key}->{'iter'} );
	}

	delete( $session_screens{$key} );    
	
	&fct_update_first_tab;
	return FALSE;

}

sub fct_get_latest_tab_key {
	my $max_key = 0;
	foreach my $key ( keys %session_screens ) {
		$key =~ /\[(.*)\]/;
		$max_key = $1 if ( $1 > $max_key );
	}
	return $max_key + 1;
}

sub fct_imagemagick_perform {
	my ( $function, $file, $data ) = @_;
	my $result 	= undef;
	$file = $shutter_hfunct->switch_home_in_file($file);
	
	if ( $function eq "reduce_colors" ) {
		$result = `convert $file -colors $data $file`;
	} 

	return $result;
}

sub fct_check_installed_programs {

	#update list of available programs in settings dialog as well
	if ($progname) {

		my $model         = $progname->get_model();
		my $progname_iter = $progname->get_active_iter();

		#get last prog
		my $progname_value;
		if ( defined $progname_iter ) {
			$progname_value = $model->get_value( $progname_iter, 1 );
		}

		#rebuild model with new hash of installed programs...
		$model = &fct_get_program_model;
		$progname->set_model($model);

		#...and try to set last	value
		if ($progname_value) {
			$model->foreach( \&fct_iter_programs, $progname_value );
		} else {
			$progname->set_active(0);
		}

		#nothing has been set
		if ( $progname->get_active == -1 ) {
			$progname->set_active(0);
		}
	}

	return TRUE;
}

sub fct_get_next_filename {

	my ( $filename_value, $folder, $filetype_value ) = @_;

	$filename_value =~ s/\\//g;

	#auto increment
	if ( $filename_value =~ /\%N{1,}/ ) {

		#how many Ns are used? (important for formatting)
		my $pos_proc = index( $filename_value, "%", 0 );
		my $n_counter = 0;
		$pos_proc++;

		while ( $pos_proc <= length($filename_value) ) {
			if ( index( $filename_value, "N", $pos_proc ) != -1 ) {
				$n_counter++;
				$pos_proc++;
			} else {
				last;
			}
		}
		print "$n_counter Ns used in wild-card\n" if $shutter_common->get_debug;
		my $marks = "";
		my $i     = 0;

		while ( $i < $n_counter ) {
			$marks .= '\d';
			$i++;
		}

		$filename_value =~ s/\%N{1,}/$marks/g;
		print "Searching for files with pattern: $filename_value.$filetype_value\n"
			if $shutter_common->get_debug;

		#get_all files from directory
		#we handle the listing with GnomeVFS to read remote dirs as well
		my @files;
		my ( $result, $uri_list ) = Gnome2::VFS::Directory->open( $folder, 'default' );

		#could not open directory, show error message and return
		unless ($result eq 'ok'){
			
			my $response = $shutter_dialog->dlg_error_message( 
				sprintf( $d->get( "Error while opening directory %s."), "'" . $folder. "'" ),
				$d->get( "There was an error determining the filename." ),
				undef, undef, undef,
				undef, undef, undef,
				Gnome2::VFS->result_to_string ($result)
			);

			return FALSE;

		}

		#reading all files in current directory
		while ( my ( $result, $file ) = $uri_list->read_next ) {
			if ( $result eq 'ok' ) {
				my $fileinfo = Gnome2::VFS::FileInfo->new($file);
				my $search_pattern = $filename_value."\.".$filetype_value;
				push @files, $fileinfo->{'name'} if $fileinfo->{'name'} =~ /$search_pattern/;
			} elsif ( $result eq 'error-eof' ) {
				$uri_list->close();
				last;
			} else {
				next;
			}
		}

		@files = sort { $b cmp $a } @files;

		if ( $shutter_common->get_debug ) {
			print "All files in directory for this pattern:\n";
			foreach (@files) {
				print $_. " \n";
			}
		}

		#check pos of %NN
		#~ $filename_value =~ s/\\d/d/g;
		my $pos = index( "$filename_value", '\d', 0 );
		my $next_count = 0;
		unless ( $pos == -1 ) {
			foreach (@files) {
				$next_count = substr( $_, $pos, $n_counter );
				next unless $next_count =~ /^(\d+\.?\d*|\.\d+)$/;
				print "Counter at position $pos - $next_count is currently greatest value...\n"
					if $shutter_common->get_debug;
				last;
			}
		}
		$next_count = 0 unless $next_count =~ /^(\d+\.?\d*|\.\d+)$/;
		$next_count = sprintf( "%0" . $n_counter . "d", $next_count + 1 );
		$marks = quotemeta $marks;
		$filename_value =~ s/$marks/$next_count/g;
	}

	#create new uri
	my $new_uri = Gnome2::VFS::URI->new("$folder/$filename_value.$filetype_value");
	if ( $new_uri->exists ) {
		my $count             = 1;
		my $existing_filename = $filename_value;
		while ( $new_uri->exists ) {
			$filename_value = $existing_filename . "(" . sprintf( "%03d", $count++ ) . ")";
			$new_uri 	= Gnome2::VFS::URI->new($folder);
			$new_uri    = $new_uri->append_string("$filename_value.$filetype_value");
			print "Checking new uri: " . $new_uri->to_string . "\n" if $shutter_common->get_debug;
		}
	}

	return $new_uri;
}

sub fct_check_installed_plugins {

	my $plugin_dialog = Gtk2::MessageDialog->new( $window, [qw/modal destroy-with-parent/], 'info', 'close', $d->get("Updating plugin information") );
	$plugin_dialog->{destroyed} = FALSE;

	$plugin_dialog->set_title("Shutter");
	
	$plugin_dialog->set( 'secondary-text' => $d->get("Please wait while Shutter updates the plugin information") . "." );

	$plugin_dialog->signal_connect( response => sub { $plugin_dialog->{destroyed} = TRUE; $_[0]->destroy; } );
	
	$plugin_dialog->set_resizable(TRUE);

	my $plugin_progress = Gtk2::ProgressBar->new;
	$plugin_progress->set_no_show_all(TRUE);
	$plugin_progress->set_ellipsize('middle');
	$plugin_progress->set_orientation('left-to-right');
	$plugin_progress->set_fraction(0);

	$plugin_dialog->vbox->add($plugin_progress);
	
	my @plugin_paths = ( "$shutter_root/share/shutter/resources/system/plugins/*/*", "$ENV{'HOME'}/.shutter/plugins/*/*" );

	#fallback icon
	# maybe the plugin 
	# does not provide a custom icon
	my $fb_pixbuf_path 	= "$shutter_root/share/shutter/resources/icons/executable.svg";
	my $fb_pixbuf		= Gtk2::Gdk::Pixbuf->new_from_file_at_size( $fb_pixbuf_path, Gtk2::IconSize->lookup('menu') );

	foreach my $plugin_path (@plugin_paths) {
		my @plugins = glob($plugin_path);
		foreach (@plugins) {
			if ( -d $_ ) {
				my $dir_name = $_;

				#parse filename
				my ( $name, $folder, $type ) = fileparse( $dir_name, '\..*' );
				
				#file exists
				if ( $shutter_hfunct->file_exists("$dir_name/$name") ) {

					#file is executable
					if ( $shutter_hfunct->file_executable("$dir_name/$name") ) {

						#new plugin information?
						unless ( $plugins{$_}->{'binary'}
							&& $plugins{$_}->{'name'}
							&& $plugins{$_}->{'category'}
							&& $plugins{$_}->{'tooltip'}
							&& $plugins{$_}->{'lang'} )
						{
														
							#show dialog and progress bar
							if(!$plugin_dialog->window && !$plugin_dialog->{destroyed}){
								$plugin_progress->show;
								$plugin_dialog->show_all;
							}

							print "\nINFO: new plugin information detected - $dir_name/$name\n";

							#path to executable
							$plugins{$_}->{'binary'} = "$dir_name/$name";

							#name
							$plugins{$_}->{'name'} = &fct_plugin_get_info( $plugins{$_}->{'binary'}, 'name' );

							#category
							$plugins{$_}->{'category'} = &fct_plugin_get_info( $plugins{$_}->{'binary'}, 'sort' );

							#tooltip
							$plugins{$_}->{'tooltip'} = &fct_plugin_get_info( $plugins{$_}->{'binary'}, 'tip' );

							#language (shell, perl etc.)
							#=> directory name
							my $folder_name = dirname($dir_name);
							$folder_name =~ /.*\/(.*)/;
							$plugins{$_}->{'lang'} = $1;

							#refresh the progressbar
							$plugin_progress->pulse;
							$plugin_progress->set_text($plugins{$_}->{'binary'});

							#refresh gui
							&fct_update_gui;

						}

						$plugins{$_}->{'lang'} = "shell"
							if $plugins{$_}->{'lang'} eq "";

						chomp( $plugins{$_}->{'name'} );
						chomp( $plugins{$_}->{'category'} );
						chomp( $plugins{$_}->{'tooltip'} );
						chomp( $plugins{$_}->{'lang'} );

						#pixbuf
						$plugins{$_}->{'pixbuf'} = $plugins{$_}->{'binary'} . ".png"
							if ( $shutter_hfunct->file_exists( $plugins{$_}->{'binary'} . ".png" ) );
						$plugins{$_}->{'pixbuf'} = $plugins{$_}->{'binary'} . ".svg"
							if ( $shutter_hfunct->file_exists( $plugins{$_}->{'binary'} . ".svg" ) );

						if ( $shutter_hfunct->file_exists( $plugins{$_}->{'pixbuf'} ) ) {
							$plugins{$_}->{'pixbuf_object'}
								= Gtk2::Gdk::Pixbuf->new_from_file_at_size( $plugins{$_}->{'pixbuf'}, Gtk2::IconSize->lookup('menu') );
						} else {
							$plugins{$_}->{'pixbuf'} 		= $fb_pixbuf_path;
							$plugins{$_}->{'pixbuf_object'} = $fb_pixbuf;
						}
						if ( $shutter_common->get_debug ) {
							print "$plugins{$_}->{'name'} - $plugins{$_}->{'binary'}\n";
						}
						
					}else{
						my $changed = chmod(0755, "$dir_name/$name");
						unless($changed){
							print "\nERROR: plugin exists but is not executable - $dir_name/$name\n";
							delete $plugins{$_};
						}
					} #endif plugin is executable
					
				} else {
					delete $plugins{$_};
				}    #endif plugin exists
			
			}
		}
	}

	#destroys the plugin dialog
	$plugin_dialog->response('ok');

	return TRUE;
}

sub fct_plugin_get_info {
	my ( $plugin, $info ) = @_;

	my $plugin_info = `$plugin $info`;
	utf8::decode $plugin_info;
	
	return $plugin_info;
}

sub fct_iter_programs {
	my ( $model, $path, $iter, $search_for ) = @_;
	my $progname_value = $model->get_value( $iter, 1 );
	return FALSE if $search_for ne $progname_value;
	$progname->set_active_iter($iter);
	return TRUE;
}

sub fct_ret_workspace_menu {
	my $init = shift;

	my $menu_wrksp = Gtk2::Menu->new;

	my $screen = Gnome2::Wnck::Screen->get_default;
	$screen->force_update();

	#we determine the wm name but on older
	#version of libwnck (or the bindings)
	#the needed method is not available
	#in this case we use gdk to do it
	#
	#this leads to a known problem when switching
	#the wm => wm_name will still remain the old one
	my $wm_name = Gtk2::Gdk::Screen->get_default->get_window_manager_name;
	if($screen->can('get_window_manager_name')){
		$wm_name = $screen->get_window_manager_name;
	}

	my $active_workspace = $screen->get_active_workspace;
	
	#we need to handle different window managers here because there are some different models related
	#to workspaces and viewports
	#	compiz uses "one workspace" - "multiple viewports" model for example
	#	default gnome wm metacity simply uses multiple workspaces
	#we will try to handle them by name

	#compiz
	if ( $wm_name =~ /compiz/ && $active_workspace) {

		#calculate viewports with size of workspace
		my $vpx = $active_workspace->get_viewport_x;
		my $vpy = $active_workspace->get_viewport_y;

		my $n_viewports_column = int( $active_workspace->get_width / $screen->get_width );
		my $n_viewports_rows   = int( $active_workspace->get_height / $screen->get_height );

		#rows
		for ( my $j = 0; $j < $n_viewports_rows; $j++ ) {

			#columns
			for ( my $i = 0; $i < $n_viewports_column; $i++ ) {
				my @vp = ( $i * $screen->get_width, $j * $screen->get_height );
				my $vp_name = "$wm_name x: $i y: $j";

				print "shutter_wrksp_direct_compiz" . $vp[0] . "x" . $vp[1] . "\n"
					if $shutter_common->get_debug;

				my $vp_item = Gtk2::MenuItem->new_with_label( ucfirst $vp_name );
				$vp_item->signal_connect(
					'activate' => \&evt_take_screenshot,
					"shutter_wrksp_direct_compiz" . $vp[0] . "x" . $vp[1]
				);
				$menu_wrksp->append($vp_item);

				#do not offer current viewport
				if ( $vp[0] == $vpx && $vp[1] == $vpy ) {
					$vp_item->set_sensitive(FALSE);
				}
			}    #columns
		}    #rows

		#all other wm manager like metacity etc.
		#we could add more of them here if needed
	} else {

		my @workspaces = ();
		for ( my $wcount = 0; $wcount < $screen->get_workspace_count; $wcount++ ) {
			push( @workspaces, $screen->get_workspace($wcount) );
		}

		foreach my $space (@workspaces) {
			next unless defined $space;

			my $wrkspace_item = Gtk2::MenuItem->new_with_label( $space->get_name );
			$wrkspace_item->signal_connect(
				'activate' => \&evt_take_screenshot,
				"shutter_wrksp_direct" . $space->get_number
			);
			$menu_wrksp->append($wrkspace_item);
			if ($active_workspace && $active_workspace->get_number == $space->get_number ) {
				$wrkspace_item->set_sensitive(FALSE);
			}
		}
	}

	my $n_mons = Gtk2::Gdk::Screen->get_default->get_n_monitors;

	#use only current monitore
	$menu_wrksp->append( Gtk2::SeparatorMenuItem->new );
	if ($init) {
		$current_monitor_active = Gtk2::CheckMenuItem->new_with_label( $d->get("Limit to current monitor") );
		if ( defined $settings_xml->{'general'}->{'current_monitor_active'} ) {
			$current_monitor_active->set_active( $settings_xml->{'general'}->{'current_monitor_active'} );
		} else {
			$current_monitor_active->set_active(FALSE);
		}
		$menu_wrksp->append($current_monitor_active);
	} else {
		$current_monitor_active->reparent($menu_wrksp);
	}

	$tooltips->set_tip(
		$current_monitor_active,
		sprintf(
			$d->nget(
				"This option is only useful when you are running a multi-monitor system (%d monitor detected).\nEnable it to capture only the current monitor.",
				"This option is only useful when you are running a multi-monitor system (%d monitors detected).\nEnable it to capture only the current monitor.",
				$n_mons
			),
			$n_mons
		)
	);
	if ( $n_mons > 1 ) {
		$current_monitor_active->set_sensitive(TRUE);
	} else {
		$current_monitor_active->set_active(FALSE);
		$current_monitor_active->set_sensitive(FALSE);
	}

	$shutter_tool->{_full}->set_menu($menu_wrksp);
	$menu_wrksp->show_all();
	return $menu_wrksp;
}

sub fct_ret_window_menu {
	my $screen = Gnome2::Wnck::Screen->get_default;
	$screen->force_update();

	my $active_workspace = $screen->get_active_workspace;

	my $menu_windows = Gtk2::Menu->new;
	foreach my $win ( $screen->get_windows_stacked ) {
		if ($active_workspace && $win->is_visible_on_workspace( $active_workspace ) ) {
			my $window_item = Gtk2::ImageMenuItem->new_with_label( $win->get_name );
			$window_item->set_image( Gtk2::Image->new_from_pixbuf( $win->get_mini_icon ) );
			$window_item->signal_connect(
				'activate' => \&evt_take_screenshot,
				"shutter_window_direct" . $win->get_xid
			);
			$menu_windows->append($window_item);
		}
	}
	$shutter_tool->{_window}->set_menu($menu_windows);
	$menu_windows->show_all;
	return $menu_windows;
}

sub fct_ret_tray_menu {

	my $tray_menu       = Gtk2::Menu->new();
	
	#selection
	my $menuitem_select = Gtk2::ImageMenuItem->new_with_mnemonic( $d->get('_Selection') );
	if($icontheme->has_icon('applications-accessories')){
		$menuitem_select->set_image(
			Gtk2::Image->new_from_icon_name( 'applications-accessories', 'menu' )	
		);
	}else{
		$menuitem_select->set_image(
			Gtk2::Image->new_from_pixbuf(
				Gtk2::Gdk::Pixbuf->new_from_file_at_size( "$shutter_root/share/shutter/resources/icons/selection.svg", Gtk2::IconSize->lookup('menu') )
			)
		);
	}
	$menuitem_select->signal_connect(
		activate => \&evt_take_screenshot,
		'tray_select'
	);
	
	#full screen
	my $menuitem_raw = Gtk2::ImageMenuItem->new_from_stock( 'gtk-fullscreen' );
	$menuitem_raw->signal_connect(
		activate => \&evt_take_screenshot,
		'tray_raw'
	);
	
	#window
	my $menuitem_window = Gtk2::ImageMenuItem->new_with_mnemonic( $d->get('W_indow') );
	if($icontheme->has_icon('preferences-system-windows')){
		$menuitem_window->set_image( Gtk2::Image->new_from_icon_name( 'preferences-system-windows', 'menu' ) );	
	}else{
		$menuitem_window->set_image(
			Gtk2::Image->new_from_pixbuf(
				Gtk2::Gdk::Pixbuf->new_from_file_at_size( "$shutter_root/share/shutter/resources/icons/sel_window.svg", Gtk2::IconSize->lookup('menu') )
			)
		);
	}
	$menuitem_window->signal_connect(
		activate => \&evt_take_screenshot,
		'tray_window'
	);
	
	#section
	my $menuitem_window_sect = Gtk2::ImageMenuItem->new_with_mnemonic( $d->get('Se_ction') );
	if($icontheme->has_icon('gdm-xnest')){
		$menuitem_window_sect->set_image( Gtk2::Image->new_from_icon_name( 'gdm-xnest', 'menu' ) );	
	}else{
		$menuitem_window_sect->set_image(
			Gtk2::Image->new_from_pixbuf(
				Gtk2::Gdk::Pixbuf->new_from_file_at_size(
					"$shutter_root/share/shutter/resources/icons/sel_window_section.svg",
					Gtk2::IconSize->lookup('menu')
				)
			)
		);
	}
	$menuitem_window_sect->signal_connect(
		activate => \&evt_take_screenshot,
		'tray_section'
	);
	
	#web
	my $menuitem_web = Gtk2::ImageMenuItem->new_with_mnemonic( $d->get('_Web') );
	$menuitem_web->set_sensitive($gnome_web_photo);
	if($icontheme->has_icon('applications-internet')){
		$menuitem_web->set_image( Gtk2::Image->new_from_icon_name( 'applications-internet', 'menu' ) );		
	}else{
		$menuitem_web->set_image(
			Gtk2::Image->new_from_pixbuf(
				Gtk2::Gdk::Pixbuf->new_from_file_at_size( "$shutter_root/share/shutter/resources/icons/web_image.svg", Gtk2::IconSize->lookup('menu') )
			)
		);
	}
	$menuitem_web->signal_connect(
		activate => \&evt_take_screenshot,
		'tray_web'
	);
	
	#info
	my $menuitem_info = Gtk2::ImageMenuItem->new_from_stock( 'gtk-about' );
	$menuitem_info->signal_connect( "activate", \&evt_about, $window );
	
	#quit
	my $menuitem_quit = Gtk2::ImageMenuItem->new_from_stock( 'gtk-quit' );
	$menuitem_quit->signal_connect( "activate", \&evt_delete_window, 'quit' );
	
	$tray_menu->append($menuitem_select);
	$tray_menu->append( Gtk2::SeparatorMenuItem->new );
	$tray_menu->append($menuitem_raw);
	$tray_menu->append( Gtk2::SeparatorMenuItem->new );
	$tray_menu->append($menuitem_window);
	$tray_menu->append($menuitem_window_sect);
	$tray_menu->append( Gtk2::SeparatorMenuItem->new );
	$tray_menu->append($menuitem_web);
	$tray_menu->append( Gtk2::SeparatorMenuItem->new );
	$tray_menu->append($menuitem_info);
	$tray_menu->append($menuitem_quit);
	$tray_menu->show_all;

	return $tray_menu;
}

sub fct_ret_sel_menu {

	#PREF MENU
	my $menu_settings = Gtk2::Menu->new;
	$zoom_active = Gtk2::CheckMenuItem->new_with_label( $d->get("Enable zoom window") );
	if ( defined $settings_xml->{'general'}->{'zoom_active'} ) {
		$zoom_active->set_active( $settings_xml->{'general'}->{'zoom_active'} );
	} else {
		$zoom_active->set_active(TRUE);
	}

	my $menu_size  = Gtk2::MenuItem->new_with_label( $d->get("Size of zoom window") );
	my $menu_size2 = Gtk2::Menu->new;
	$zoom_size1 = Gtk2::RadioMenuItem->new( undef,       $d->get("Small") );
	$zoom_size2 = Gtk2::RadioMenuItem->new( $zoom_size1, $d->get("Medium") );
	$zoom_size3 = Gtk2::RadioMenuItem->new( $zoom_size1, $d->get("Large") );

	if ( defined $settings_xml->{'general'}->{'zoom_size'} ) {
		$zoom_size1->set_active(TRUE)
			if $settings_xml->{'general'}->{'zoom_size'} == 1;
		$zoom_size2->set_active(TRUE)
			if $settings_xml->{'general'}->{'zoom_size'} == 2;
		$zoom_size3->set_active(TRUE)
			if $settings_xml->{'general'}->{'zoom_size'} == 3;
	} else {
		$zoom_size1->set_active(TRUE);
	}

	#TOP MENU
	my $menu_sel = Gtk2::Menu->new;

	#advanced tool
	$tool_advanced = Gtk2::RadioMenuItem->new( undef, $d->get("Advanced selection tool") );

	#simple tool
	$tool_simple = Gtk2::RadioMenuItem->new( $tool_advanced, $d->get("Simple selection tool") );

	#and some more preferences
	my $advanced_settings = Gtk2::MenuItem->new_with_label( $d->get("Preferences") );

	$menu_sel->append($tool_advanced);
	$menu_sel->append($tool_simple);
	$menu_sel->append($advanced_settings);

	$menu_size->set_submenu($menu_size2);
	$menu_size2->append($zoom_size1);
	$menu_size2->append($zoom_size2);
	$menu_size2->append($zoom_size3);

	$menu_settings->append($zoom_active);
	$menu_settings->append($menu_size);
	$advanced_settings->set_submenu($menu_settings);

	$tool_simple->signal_connect(
		'activate' => sub {
			my $widget = shift;
			if ( $widget->get_active ) {
				$advanced_settings->set_sensitive(TRUE);
			} else {
				$advanced_settings->set_sensitive(FALSE);
			}
		}
	);

	#set saved/default settings
	if ( defined $settings_xml->{'general'}->{'selection_tool'} ) {
		if ( $settings_xml->{'general'}->{'selection_tool'} == 1 ) {
			$tool_advanced->set_active(TRUE);
			$advanced_settings->set_sensitive(FALSE);
		} elsif ( $settings_xml->{'general'}->{'selection_tool'} == 2 ) {
			$tool_simple->set_active(TRUE);
			$advanced_settings->set_sensitive(TRUE);
		}
	} else {
		$tool_advanced->set_active(TRUE);
		$advanced_settings->set_sensitive(FALSE);
	}

	$tooltips->set_tip( $tool_advanced,
		$d->get("The advanced selection tool allows you to enlarge/shrink or move your selected area\nuntil you finally take the screenshot.") );

	$tooltips->set_tip( $tool_simple,
		$d->get("The simple selection tool is the fastest way of taking a screenshot.\nIt provides an optional zoom window for precise shots.") );

	$menu_sel->show_all;

	return $menu_sel;
}

sub fct_ret_program_menu {
	my $icontheme     = Gtk2::IconTheme->get_for_screen( Gtk2::Gdk::Screen->get_default );
	my $menu_programs = Gtk2::Menu->new;

	#take $key (mime) directly
	my $key = &fct_get_current_file;

	#FIXME - different mime types
	#have different apps registered
	#we should restrict the offeres apps
	#by comparing the selected
	#
	#currently we just take the last selected file into account
	#
	#search selected files for mime...
	unless ($key) {
		$session_start_screen{'first_page'}->{'view'}->selected_foreach(
			sub {
				my ( $view, $path ) = @_;
				my $iter = $session_start_screen{'first_page'}->{'model'}->get_iter($path);
				if ( defined $iter ) {
					$key = $session_start_screen{'first_page'}->{'model'}->get_value( $iter, 2 );
				}
			}
		);
	}

	#still no key? => leave sub
	unless( $key ){
		$shutter_menu->{_menuitem_reopen_default}->visible(FALSE);
		$shutter_menu->{_menuitem_reopen}->set_sensitive(FALSE);
		return $menu_programs;		
	}

	#no valid hash entry?
	unless (exists $session_screens{$key}->{'mime_type'}){
		$shutter_menu->{_menuitem_reopen_default}->visible(FALSE);
		$shutter_menu->{_menuitem_reopen}->set_sensitive(FALSE);
		return $menu_programs;	
	}

	#determine apps registered with that mime type	
	my ( $default, @mapps ) = File::MimeInfo::Applications::mime_applications( $session_screens{$key}->{'mime_type'} );
	
	#currently we use File::MimeInfo::Applications and Gnome2::VFS::Mime::Type
	#because of the following error
	#
	#libgnomevfs-WARNING **: 
	#Cannot call gnome_vfs_mime_application_get_icon 
	#with a GNOMEVFSMimeApplication structure constructed 
	#by the deprecated application registry 
	my $mime_type = Gnome2::VFS::Mime::Type->new ($session_screens{$key}->{'mime_type'});
	my @apps = $mime_type->get_all_applications;

	#no app determined!
	unless (scalar @apps && scalar @mapps){
		$shutter_menu->{_menuitem_reopen_default}->visible(FALSE);
		$shutter_menu->{_menuitem_reopen}->set_sensitive(FALSE);
		return $menu_programs;			
	}

	#no default app determined!
	unless ($default){
		$shutter_menu->{_menuitem_reopen_default}->visible(FALSE);					
	}
	
	my $default_matched = FALSE;
	foreach my $app (@apps) {
		
		$app->{'name'} = $shutter_hfunct->utf8_decode($app->{'name'});
		
		#FIXME - kde apps do not support the freedesktop standards (.desktop files)
		#we simply cut the kde* / kde4* substring here
		#is it possible to get the wrong app if there 
		#is the kde3 and the kde4 version of an app installed?
		#
		#I think so ;-)
		$app->{'id'} =~ s/^(kde4|kde)-//g;

		my $program_item = undef; 
		
		#default app
		if($default && $default->{'file'} =~ m/$app->{'id'}/){
			
			#set flag
			$default_matched = TRUE;
			
			#remove old handler
			#strange things happen when we do not remove it
			if(exists $shutter_menu->{_menuitem_reopen_default}{hid} 
				&& $shutter_menu->{_menuitem_reopen_default}->signal_handler_is_connected($shutter_menu->{_menuitem_reopen_default}{hid}))
			{
				$shutter_menu->{_menuitem_reopen_default}->signal_handler_disconnect($shutter_menu->{_menuitem_reopen_default}{hid});
			}
			
			$program_item = $shutter_menu->{_menuitem_reopen_default};
			$program_item->{'default'} = TRUE;
			
			$shutter_menu->{_menuitem_reopen_default}->show;
			$shutter_menu->{_menuitem_reopen_default}->set_sensitive(TRUE);

			#change label of the default app entry
			$shutter_menu->{_menuitem_reopen_default}->foreach (sub {
				if($_[0] =~ /Gtk2::AccelLabel/){
					$_[0]->set_label(sprintf( $d->get("_Open with %s"), "'".$app->{'name'}."'"));
					return undef;
				}
			});	
				
		#other apps			
		}else{
			$program_item = Gtk2::ImageMenuItem->new_with_label( $app->{'name'} );			
			$menu_programs->append($program_item);
		}

		#find icon and app
		#we use File::DesktopEntry instead of the Gnome one
		#for opening files
		my $oapp = undef; 
		foreach my $mapp (@mapps){
			if($mapp->{'file'} =~ m/$app->{'id'}/){
				$oapp = $mapp;
				last;	
			}	
		}
	
		#match found!
		if ($oapp){
			my $icon_name = $oapp->Icon;
			if($icon_name){
				#cut image formats
				$icon_name =~ s/(.png|.svg|.gif|.jpeg|.jpg)//g;
				if ( $icontheme->has_icon( $icon_name ) ) {
					my ( $iw, $ih ) = Gtk2::IconSize->lookup('menu');
					my $icon_pixbuf = $icontheme->load_icon( $icon_name, $ih, 'generic-fallback' );
					$program_item->set_image( Gtk2::Image->new_from_pixbuf($icon_pixbuf) );
				}
			}
			my $hid = $program_item->signal_connect(
				'activate' => sub {
					&fct_open_with_program($oapp, $app->{'name'});
				}
			);
			
			#save hid when default app
			#to remove the handler next time we open the menu
			$shutter_menu->{_menuitem_reopen_default}{hid} = $hid if $program_item->{'default'};
			
		#no match found -> destroy current menu entry		
		}else{
			$program_item->destroy;
		}		
		
	}	
	
	#no default app matched!
	unless($default_matched){
		$shutter_menu->{_menuitem_reopen_default}->visible(FALSE);	
	}
	
	#menu does not contain any item
	unless($menu_programs->get_children){
		$shutter_menu->{_menuitem_reopen}->set_sensitive(FALSE);
	}
	
	$menu_programs->show_all;
	return $menu_programs;
}

sub fct_ret_web_menu {
	
	my $menu_web = Gtk2::Menu->new;
	
	my $timeout0 = Gtk2::RadioMenuItem->new( undef, $d->get("Timeout") . ": 0" );
	my $timeout1 = Gtk2::RadioMenuItem->new( $timeout0, $d->get("Timeout") . ": 10" );
	my $timeout2 = Gtk2::RadioMenuItem->new( $timeout0, $d->get("Timeout") . ": 30" );
	my $timeout3 = Gtk2::RadioMenuItem->new( $timeout0, $d->get("Timeout") . ": 60" );
	my $timeout4 = Gtk2::RadioMenuItem->new( $timeout0, $d->get("Timeout") . ": 120" );

	$tooltips->set_tip( $timeout0, $d->get("The timeout in seconds, or 0 to disable timeout" ));
	$tooltips->set_tip( $timeout1, $d->get("The timeout in seconds, or 0 to disable timeout" ));
	$tooltips->set_tip( $timeout2, $d->get("The timeout in seconds, or 0 to disable timeout" ));
	$tooltips->set_tip( $timeout3, $d->get("The timeout in seconds, or 0 to disable timeout" ));
	$tooltips->set_tip( $timeout4, $d->get("The timeout in seconds, or 0 to disable timeout" ));
	
	$timeout2->set_active(TRUE);
	$menu_web->append($timeout0);
	$menu_web->append($timeout1);
	$menu_web->append($timeout2);
	$menu_web->append($timeout3);
	$menu_web->append($timeout4);

	if ( defined $settings_xml->{'general'}->{'web_timeout'} ) {

		#determining timeout
		my @timeouts = $menu_web->get_children;
		my $timeout  = undef;
		foreach (@timeouts) {
			$timeout = $_->get_children->get_text;
			$timeout =~ /([0-9]+)/;
			$timeout = $1;
			if ( $settings_xml->{'general'}->{'web_timeout'} == $timeout ) {
				$_->set_active(TRUE);
			}
		}
	}
	$menu_web->show_all;
	return $menu_web;
}

sub fct_ret_profile_menu {
	my $combobox_settings_profiles = shift;
	my $current_profiles_ref       = shift;

	my $menu_profile = Gtk2::Menu->new;

	my $group   = undef;
	my $counter = 0;
	foreach my $profile ( @{$current_profiles_ref} ) {
		my $profile_item = Gtk2::RadioMenuItem->new( $group, $profile );
		$profile_item->set_active(TRUE)
			if $profile eq $combobox_settings_profiles->get_active_text;
		$profile_item->signal_connect(
			'toggled' => sub {
				my $widget = shift;
				return TRUE unless $widget->get_active;

				for ( my $i = 0; $i < scalar @{$current_profiles_ref}; $i++ ) {
					$combobox_settings_profiles->set_active($i);
					$current_profile_indx = $i;
					if ( $profile eq $combobox_settings_profiles->get_active_text ) {
						&evt_apply_profile( $widget, $combobox_settings_profiles, $current_profiles_ref );
						last;
					}
				}
			}
		);
		$group = $profile_item unless $group;
		$menu_profile->append($profile_item);
		$counter++;
	}

	$menu_profile->show_all;
	return $menu_profile;
}

sub fct_load_accounts_tree {

	$accounts_model
		= Gtk2::ListStore->new( 'Glib::String', 'Glib::String', 'Glib::String', 'Glib::String', 'Glib::String', 'Glib::String', 'Glib::String' );

	foreach ( keys %accounts ) {
		my $hidden_text = "";
		for ( my $i = 1; $i <= length( $accounts{$_}->{'password'} ); $i++ ) {
			$hidden_text .= '*';
		}
		$accounts_model->set(
			$accounts_model->append, 0, $accounts{$_}->{'host'},     1, $accounts{$_}->{'username'},       2,
			$hidden_text,            3, $accounts{$_}->{'register'}, 4, $accounts{$_}->{'register_color'}, 5,
			$accounts{$_}->{'register_text'}
		);
	}

	return TRUE;
}

sub fct_load_plugin_tree {

	my $effects_model = Gtk2::ListStore->new(
		'Gtk2::Gdk::Pixbuf', 'Glib::String', 'Glib::String', 
		'Glib::String', 'Glib::String', 'Glib::String', 
		'Glib::String',
	);
	foreach ( sort keys %plugins ) {
		if ( $plugins{$_}->{'binary'} ) {
		
			#we need to update the pixbuf of the plugins again in some cases
			#
			#pixbufs are not cached and therefore not checked at startup if
			#the cached plugin is not in the plugin path
			#(maybe changed the installation dir)
			unless($plugins{$_}->{'pixbuf'} || $plugins{$_}->{'pixbuf_object'}){
				$plugins{$_}->{'pixbuf'} = $plugins{$_}->{'binary'} . ".png"
					if ( $shutter_hfunct->file_exists( $plugins{$_}->{'binary'} . ".png" ) );
				$plugins{$_}->{'pixbuf'} = $plugins{$_}->{'binary'} . ".svg"
					if ( $shutter_hfunct->file_exists( $plugins{$_}->{'binary'} . ".svg" ) );
		
				if ( $shutter_hfunct->file_exists( $plugins{$_}->{'pixbuf'} ) ) {
					$plugins{$_}->{'pixbuf_object'}= Gtk2::Gdk::Pixbuf->new_from_file_at_size( $plugins{$_}->{'pixbuf'}, Gtk2::IconSize->lookup('menu') );
				} else {
					$plugins{$_}->{'pixbuf'} = "$shutter_root/share/shutter/resources/icons/executable.svg";
					$plugins{$_}->{'pixbuf_object'}= Gtk2::Gdk::Pixbuf->new_from_file_at_size( $plugins{$_}->{'pixbuf'}, Gtk2::IconSize->lookup('menu') );
				}
			}

			$effects_model->set(
				$effects_model->append,     
				0, $plugins{$_}->{'pixbuf_object'}, 1, $plugins{$_}->{'name'},
				2, $plugins{$_}->{'category'}, 3, $plugins{$_}->{'tooltip'},  
				4, $plugins{$_}->{'lang'}, 5, $plugins{$_}->{'binary'}, 6, $_,
			);
		} else {
			print "\nWARNING: Plugin $_ is not configured properly, ignoring\n";
			delete $plugins{$_};
		}
	}

	return $effects_model;
}

sub fct_set_model_accounts {
	my $accounts_tree = $_[0];

	my @columns = $accounts_tree->get_columns;
	foreach (@columns) {
		$accounts_tree->remove_column($_);
	}

	#host
	my $tv_clmn_name_text = Gtk2::TreeViewColumn->new;
	$tv_clmn_name_text->set_title( $d->get("Host") );
	my $renderer_name_accounts = Gtk2::CellRendererText->new;
	$tv_clmn_name_text->pack_start( $renderer_name_accounts, FALSE );
	$tv_clmn_name_text->set_attributes( $renderer_name_accounts, text => 0 );
	$accounts_tree->append_column($tv_clmn_name_text);

	my $renderer_username_accounts = Gtk2::CellRendererText->new;
	$renderer_username_accounts->set( editable => TRUE );
	$renderer_username_accounts->signal_connect(
		'edited' => sub {
			my ( $cell, $text_path, $new_text, $model ) = @_;
			my $path = Gtk2::TreePath->new_from_string($text_path);
			my $iter = $model->get_iter($path);

			#save entered username to the hash
			$accounts{ $model->get_value( $iter, 0 ) }->{'username'} = $new_text;

			$model->set( $iter, 1, $new_text );
		},
		$accounts_model
	);
	
	my $tv_clmn_username_text = Gtk2::TreeViewColumn->new_with_attributes( $d->get("Username"), $renderer_username_accounts, text => 1 );
	$tv_clmn_username_text->set_max_width(100);
	$accounts_tree->append_column($tv_clmn_username_text);

	#password
	my $tv_clmn_password_text = Gtk2::TreeViewColumn->new;
	$tv_clmn_password_text->set_max_width(100);
	$tv_clmn_password_text->set_title( $d->get("Password") );
	my $renderer_password_accounts = Gtk2::CellRendererText->new;
	$renderer_password_accounts->set( editable => TRUE );

	$renderer_password_accounts->signal_connect(
		'edited' => sub {
			my ( $cell, $text_path, $new_text, $model ) = @_;
			my $path        = Gtk2::TreePath->new_from_string($text_path);
			my $iter        = $model->get_iter($path);
			my $hidden_text = "";

			for ( my $i = 1; $i <= length($new_text); $i++ ) {
				$hidden_text .= '*';
			}
			
			$accounts{ $model->get_value( $iter, 0 ) }->{'password'} = $new_text;    #save entered password to the hash
			$model->set( $iter, 2, $hidden_text );
		},
		$accounts_model
	);

	$tv_clmn_password_text->pack_start( $renderer_password_accounts, FALSE );
	$tv_clmn_password_text->set_attributes( $renderer_password_accounts, text => 2 );
	$accounts_tree->append_column($tv_clmn_password_text);

	#register
	my $tv_clmn_pix_text = Gtk2::TreeViewColumn->new;
	$tv_clmn_pix_text->set_title( $d->get("Register") );
	my $ren_text = Gtk2::CellRendererText->new();
	$tv_clmn_pix_text->pack_start( $ren_text, FALSE );
	$tv_clmn_pix_text->set_attributes( $ren_text, 'text', ( $d->get(5) ), 'foreground', 4 );
	$accounts_tree->append_column($tv_clmn_pix_text);

	return TRUE;
}

sub fct_set_model_plugins {	
	my $effects_tree = $_[0];

	#~ my @columns = $effects_tree->get_columns;
	#~ foreach (@columns) {
		#~ $effects_tree->remove_column($_);
	#~ }

	#icon
	$effects_tree->set_tooltip_column(3)
		if Gtk2->CHECK_VERSION( 2, 11, 0 );
	
	my $tv_clmn_pix_text = Gtk2::TreeViewColumn->new;
	$tv_clmn_pix_text->set_resizable(TRUE);
	$tv_clmn_pix_text->set_title( $d->get("Icon") );
	my $renderer_pix_effects = Gtk2::CellRendererPixbuf->new;
	$tv_clmn_pix_text->pack_start( $renderer_pix_effects, FALSE );
	$tv_clmn_pix_text->set_attributes( $renderer_pix_effects, pixbuf => 0 );
	$effects_tree->append_column($tv_clmn_pix_text);

	#name
	my $tv_clmn_text_text = Gtk2::TreeViewColumn->new;
	$tv_clmn_text_text->set_resizable(TRUE);
	$tv_clmn_text_text->set_title( $d->get("Name") );
	my $renderer_text_effects = Gtk2::CellRendererText->new;
	$tv_clmn_text_text->pack_start( $renderer_text_effects, FALSE );
	$tv_clmn_text_text->set_attributes( $renderer_text_effects, text => 1 );

	$effects_tree->append_column($tv_clmn_text_text);

	#category
	my $tv_clmn_category_text = Gtk2::TreeViewColumn->new;
	$tv_clmn_category_text->set_resizable(TRUE);
	$tv_clmn_category_text->set_title( $d->get("Category") );
	my $renderer_category_effects = Gtk2::CellRendererText->new;
	$tv_clmn_category_text->pack_start( $renderer_category_effects, FALSE );
	$tv_clmn_category_text->set_attributes( $renderer_category_effects, text => 2 );
	$effects_tree->append_column($tv_clmn_category_text);

	#tooltip column
	unless ( Gtk2->CHECK_VERSION( 2, 12, 0 ) ) {
		my $tv_clmn_descr_text = Gtk2::TreeViewColumn->new;
		$tv_clmn_descr_text->set_resizable(TRUE);
		$tv_clmn_descr_text->set_title( $d->get("Description") );
		my $renderer_descr_effects = Gtk2::CellRendererText->new;
		$tv_clmn_descr_text->pack_start( $renderer_descr_effects, FALSE );
		$tv_clmn_descr_text->set_attributes( $renderer_descr_effects, text => 3 );
		$effects_tree->append_column($tv_clmn_descr_text);
	}

	#language
	my $tv_clmn_lang_text = Gtk2::TreeViewColumn->new;
	$tv_clmn_lang_text->set_resizable(TRUE);
	$tv_clmn_lang_text->set_title( $d->get("Language") );
	my $renderer_lang_effects = Gtk2::CellRendererText->new;
	$tv_clmn_lang_text->pack_start( $renderer_lang_effects, FALSE );
	$tv_clmn_lang_text->set_attributes( $renderer_lang_effects, text => 4 );
	$effects_tree->append_column($tv_clmn_lang_text);

	#path
	my $tv_clmn_path_text = Gtk2::TreeViewColumn->new;
	$tv_clmn_path_text->set_resizable(TRUE);
	$tv_clmn_path_text->set_title( $d->get("Path") );
	my $renderer_path_effects = Gtk2::CellRendererText->new;
	$tv_clmn_path_text->pack_start( $renderer_path_effects, FALSE );
	$tv_clmn_path_text->set_attributes( $renderer_path_effects, text => 5 );
	$effects_tree->append_column($tv_clmn_path_text);

	return TRUE;
}

sub fct_init_depend {

	print "\nINFO: checking installed components...\n\n";
	
	#imagemagick/perlmagick
	unless ( File::Which::which('convert') ) {
		die "ERROR: imagemagick is missing --> aborting!\n\n";
	}

	#gnome-web-photo
	unless ( File::Which::which('gnome-web-photo') ) {
		warn "WARNING: gnome-web-photo is missing --> screenshots of websites will be disabled!\n\n";
		$gnome_web_photo = FALSE;
	}

	#goocanvas
	eval { require Goo::Canvas };
	if ($@) {
		warn "WARNING: Goo::Canvas/libgoocanvas is missing --> drawing tool will be disabled!\n\n";
		$goocanvas = FALSE;
	}

	return TRUE;
}

sub fct_init {

	#are there any command line params?
	if ( @ARGV > 0 ) {
		foreach my $arg (@ARGV) {
			$arg =~ s/.{2}//;
			if ( $arg eq "debug" ) {
				$shutter_common->set_debug(TRUE);
			} elsif ( $arg eq "help" ) {
				$shutter_hfunct->usage;
				exit;
			} elsif ( $arg eq "clear_cache" ) {
				$shutter_common->set_clear_cache(TRUE);
			} elsif ( $arg eq "min_at_startup" ) {
				$shutter_common->set_min(TRUE);
			} elsif ( $arg eq "disable_systray" ) {
				$shutter_common->set_disable_systray(TRUE);
			} elsif ( $arg eq "section" ) {

				#is there already a process of shutter running?
				my @shutter_pids = `pidof -o $$ -x $shutter_path`;
				foreach (@shutter_pids) {
					kill RTMAX => $_;
					die;
				}
				$shutter_common->set_start_with("section");
				$shutter_common->set_min(TRUE);
			} elsif ( $arg eq "selection" ) {

				#is there already a process of shutter running?
				my @shutter_pids = `pidof -o $$ -x $shutter_path`;
				foreach (@shutter_pids) {
					kill RTMIN => $_;
					die;
				}
				$shutter_common->set_start_with("select");
				$shutter_common->set_min(TRUE);
			} elsif ( $arg eq "window" ) {

				#is there already a process of shutter running?
				my @shutter_pids = `pidof -o $$ -x $shutter_path`;
				foreach (@shutter_pids) {
					kill USR2 => $_;
					die;
				}
				$shutter_common->set_start_with("window");
				$shutter_common->set_min(TRUE);
			} elsif ( $arg eq "full" ) {

				#is there already a process of shutter running?
				my @shutter_pids = `pidof -o $$ -x $shutter_path`;
				foreach (@shutter_pids) {
					kill USR1 => $_;
					die;
				}
				$shutter_common->set_start_with("raw");
				$shutter_common->set_min(TRUE);
			} else {
				warn "ERROR: illegal command " . $arg . " \n\n";
				$shutter_hfunct->usage;
				exit;
			}
			print "INFO: command " . $arg . " recognized!\n\n";
		}
	} else {
		print "INFO: no command line parameters set...\n\n";
	}

	#an old .shutter file existing?
	unlink("$ENV{ 'HOME' }/.shutter")
		if ( $shutter_hfunct->file_exists("$ENV{ 'HOME' }/.shutter") );

	#an old .shutter/settings.conf file existing?
	unlink("$ENV{ 'HOME' }/.shutter/settings.conf")
		if ( $shutter_hfunct->file_exists("$ENV{ 'HOME' }/.shutter/settings.conf") );


	#migrate from gscrot to shutter
	#if an .gscrot folder exists in the home dir
	#we copy the contents to a newly created .shutter
	#folder
	if(-d "$ENV{ 'HOME' }/.gscrot"){
		if(File::Copy::Recursive::dircopy("$ENV{ 'HOME' }/.gscrot", "$ENV{ 'HOME' }/.shutter")){
			print "INFO: successfully copied all files from .gscrot to .shutter...\n\n";
			rmtree("$ENV{ 'HOME' }/.gscrot");
		}else{
			die $!;	
		}
	}

	#is there already a .shutter folder?
	mkdir("$ENV{ 'HOME' }/.shutter")
		unless ( -d "$ENV{ 'HOME' }/.shutter" );

	#...and a profiles folder?
	mkdir "$ENV{'HOME'}/.shutter/profiles"
		unless ( -d "$ENV{'HOME'}/.shutter/profiles" );

	return TRUE;
}

sub fct_init_framework_versions {
	if ( $shutter_common->get_debug ) {
		print "\nINFO: gathering system information...";
		print "\n";
		printf "Glib %s \n", $Glib::VERSION;
		printf "Gtk2 %s \n", $Gtk2::VERSION;
		print "\n";

		# The version info stuff appeared in 1.040.
		print "Glib built for "
			. join( ".", Glib->GET_VERSION_INFO )
			. ", running with "
			. join( ".", &Glib::major_version, &Glib::minor_version, &Glib::micro_version ) . "\n"
			if $Glib::VERSION >= 1.040;
		print "Gtk2 built for "
			. join( ".", Gtk2->GET_VERSION_INFO )
			. ", running with "
			. join( ".", &Gtk2::major_version, &Gtk2::minor_version, &Gtk2::micro_version ) . "\n"
			if $Gtk2::VERSION >= 1.040;
		print "\n";
	}
	return TRUE;
}

#--------------------------------------

#dialogs
#--------------------------------------

sub dlg_status_message {
	my $index = shift;
	my $status_text = shift;
	
	$status1->pop(1);
	Glib::Source->remove ($session_start_screen{'first_page'}->{'statusbar_timer'}) if defined $session_start_screen{'first_page'}->{'statusbar_timer'};
	$status1->push( $index, $status_text );

	#...and remove it
	$session_start_screen{'first_page'}->{'statusbar_timer'} = Glib::Timeout->add(
		5000,
		sub {
			$status1->pop(1);
			return FALSE;
		}
	);
	
	return TRUE;
}

sub dlg_rename {
	my (@file_to_rename_keys) = @_;

	foreach my $key (@file_to_rename_keys){

		my $input_dialog = Gtk2::MessageDialog->new( $window, [qw/modal destroy-with-parent/], 'other', 'none', undef );

		$input_dialog->set_title("Rename");

		$input_dialog->set( 'image' => Gtk2::Image->new_from_stock( 'gtk-save-as', 'dialog' ) );

		$input_dialog->set( 'text' => sprintf( $d->get( "Rename image %s"), "'$session_screens{$key}->{'short'}'" ) );

		$input_dialog->set( 'secondary-text' => $d->get("New filename") . ": " );

		#rename button
		my $rename_btn = Gtk2::Button->new_with_mnemonic( $d->get("_Rename") );
		$rename_btn->set_image( Gtk2::Image->new_from_stock( 'gtk-save-as', 'button' ) );
		$rename_btn->can_default(TRUE);

		$input_dialog->add_button( 'gtk-cancel', 10 );
		$input_dialog->add_action_widget( $rename_btn, 20 );

		$input_dialog->set_default_response(20);

		my $new_filename_vbox = Gtk2::VBox->new();
		my $new_filename_hint = Gtk2::Label->new();
		my $new_filename      = Gtk2::Entry->new();
		$new_filename->set_activates_default(TRUE);
		
		#here are all invalid char codes
		my @invalid_codes = (47,92,63,37,42,58,124,34,60,62,44,59,35,38);
		$new_filename->signal_connect('key-press-event' => sub {
			my $new_filename 	= shift;
			my $event 			= shift;
			
			my $input = Gtk2::Gdk->keyval_to_unicode ($event->keyval); 
			
			#invalid input
			#~ print $input."\n";
			if(grep($input == $_, @invalid_codes)){
				my $char = chr($input);
				$char = '&amp;' if $char eq '&';
				$new_filename_hint->set_markup("<span size='small'>" . 
												sprintf($d->get("Reserved character %s is not allowed to be in a filename.") , "'".$char."'") 
												. "</span>");	
				return TRUE;
			}else{
				#clear possible message when valid char is entered
				$new_filename_hint->set_markup("<span size='small'></span>");						
				return FALSE;
			}
		});

		#enable/disable rename button
		#e.g. if no text is in entry
		$new_filename->signal_connect('changed' => sub {
			if(length($new_filename->get_text)){
				$rename_btn->set_sensitive(TRUE);	
			}else{
				$rename_btn->set_sensitive(FALSE);
			}
			return TRUE;
		});

		#show just the name of the image
		$new_filename->set_text( $session_screens{$key}->{'name'} );
		if(length($new_filename->get_text)){
			$rename_btn->set_sensitive(TRUE);	
		}else{
			$rename_btn->set_sensitive(FALSE);
		}

		$new_filename_vbox->pack_start_defaults($new_filename);
		$new_filename_vbox->pack_start_defaults($new_filename_hint);
		$input_dialog->vbox->add($new_filename_vbox);
		$input_dialog->show_all;

		#run dialog
		my $input_response = $input_dialog->run;

		#handle user responses here
		if ( $input_response == 20 ) {

			my $new_name = $new_filename->get_text;
			$new_name = $session_screens{$key}->{'folder'} . "/" . $new_name . "." . $session_screens{$key}->{'filetype'};

			#create uris for following action (e.g. update tab, move etc.)
			my $new_uri = Gnome2::VFS::URI->new($new_name);
			my $old_uri = $session_screens{$key}->{'uri'};

			if($new_uri){

				#filenames eq? -> nothing to do here
				unless ( $session_screens{$key}->{'long'} eq $new_name ) {

					#does the "renamed" file already exists?
					unless ( $shutter_hfunct->file_exists($new_name) ) {

						#ok => rename it

						#cancel handle
						if ( exists $session_screens{$key}->{'handle'} ) {
							
							$session_screens{$key}->{'handle'}->cancel;
						}

						my $result = $old_uri->move ($new_uri, TRUE);
						if ($result eq 'ok'){
					
							&fct_update_tab( $key, undef, $new_uri );

							#setup a new filemonitor, so we get noticed if the file changed
							&fct_add_file_monitor($key);	

							&dlg_status_message( 1, $session_screens{$key}->{'long'} . " " . $d->get("renamed") );

						}else{

							my $response = $shutter_dialog->dlg_error_message(
								sprintf( $d->get(  "Error while renaming the image %s."), "'" . $old_uri->extract_short_name . "'"),
								sprintf( $d->get(  "There was an error renaming the image to %s."), "'" . $new_uri->extract_short_name . "'" ),
								undef, undef, undef,
								undef, undef, undef,
								Gnome2::VFS->result_to_string ($result)
							);	
					
						}

					} else {

						#ask the user to replace the image
						#replace button
						my $replace_btn = Gtk2::Button->new_with_mnemonic( $d->get("_Replace") );
						$replace_btn->set_image( Gtk2::Image->new_from_stock( 'gtk-save-as', 'button' ) );

						my $response = $shutter_dialog->dlg_warning_message(
							sprintf( $d->get("The image already exists in %s. Replacing it will overwrite its contents."), "'" . $new_uri->extract_dirname . "'"),
							sprintf( $d->get( "An image named %s already exists. Do you want to replace it?"), "'" . $new_uri->extract_short_name . "'"),
							undef, undef, undef,
							$replace_btn, undef, undef
						);

						#rename == replace_btn was hit
						if ( $response == 40 ) {

							#ok => rename it

							#cancel handle
							if ( exists $session_screens{$key}->{'handle'} ) {
								
								$session_screens{$key}->{'handle'}->cancel;
							}

							my $result = $old_uri->move ($new_uri, TRUE);
							if ($result eq 'ok'){
				
								&fct_update_tab( $key, undef, $new_uri );

								#setup a new filemonitor, so we get noticed if the file changed
								&fct_add_file_monitor($key);	

								&dlg_status_message( 1, $session_screens{$key}->{'long'} . " " . $d->get("renamed") );

							}else{

								my $response = $shutter_dialog->dlg_error_message(
									sprintf( $d->get(  "Error while renaming the image %s."), "'" . $old_uri->extract_short_name . "'"),
									sprintf( $d->get(  "There was an error renaming the image to %s."), "'" . $new_uri->extract_short_name . "'" ),
									undef, undef, undef,
									undef, undef, undef,
									Gnome2::VFS->result_to_string ($result)
								);	
						
							}

							#maybe file is in session as well, need to set the handler again ;-)
							foreach my $searchkey ( keys %session_screens ) {
								next if $key eq $searchkey;
								if ( $session_screens{$searchkey}->{'long'} eq $new_name ) {
									#cancel handle
									if ( exists $session_screens{$searchkey}->{'handle'} ) {
										
										$session_screens{$searchkey}->{'handle'}->cancel;
									}

									&fct_update_tab($searchkey, undef, $new_uri);

									#setup a new filemonitor, so we get noticed if the file changed
									&fct_add_file_monitor($searchkey);	
							
								}
							}
							$input_dialog->destroy();
							next;
						}
						$input_dialog->destroy();
						next;
					}

				}

			}else{

				#uri object could not be created
				#=> uri illegal
				my $response = $shutter_dialog->dlg_error_message(
					sprintf( $d->get(  "Error while renaming the image %s."), "'" . $old_uri->extract_short_name . "'"),
					sprintf( $d->get(  "There was an error renaming the image to %s."), "'" . $new_name . "'" ),
					undef, undef, undef,
					undef, undef, undef,
					$d->get("Invalid Filename")
				);			
				
			}
		
		}

		$input_dialog->destroy();
		next;

	}
	
}

sub dlg_plugin {
	my (@file_to_plugin_keys) = @_;

	my $dlg_header    = $d->get("Choose a plugin");
	my $plugin_dialog = Gtk2::Dialog->new(
		$dlg_header,
		$window,
		[qw/modal destroy-with-parent/],
		'gtk-cancel'  => 'reject',
		'gtk-execute' => 'accept'
	);
	$plugin_dialog->set_default_response('accept');
	$plugin_dialog->set_size_request(350, -1);
	$plugin_dialog->set_resizable(FALSE);
	
	my $model = Gtk2::ListStore->new( 'Gtk2::Gdk::Pixbuf', 'Glib::String', 'Glib::String', 'Glib::String', 'Glib::String', 'Glib::String' );

	#temp variables to restore the
	#recent plugin
	my $recent_time = 0;
	my $iter_lastex_plugin = undef;
	foreach my $pkey ( sort keys %plugins ) {

		#check if plugin allows current filetype
		#~ my $nfiles_ok += scalar grep($plugins{$pkey}->{'ext'} =~ /$session_screens{$_}->{'mime_type'}/, @file_to_plugin_keys);
		#~ next if scalar @file_to_plugin_keys > $nfiles_ok;
		
		if ( $plugins{$pkey}->{'binary'} ne "" ) {

			my $new_iter = $model->append;
			$model->set(
				$new_iter, 0, $plugins{$pkey}->{'pixbuf_object'}, 1, $plugins{$pkey}->{'name'},    2,
				$plugins{$pkey}->{'binary'}, 3, $plugins{$pkey}->{'lang'},          4, $plugins{$pkey}->{'tooltip'}, 5,
				$pkey
			);
			
			#initialize $iter_lastex_plugin
			#with first new iter
			$iter_lastex_plugin = $new_iter unless defined $iter_lastex_plugin;
			
			#restore the recent plugin
			#($plugins{$plugin_key}->{'recent'} is a timestamp)
			#
			#we keep the new_iter in mind
			if (defined $plugins{$pkey}->{'recent'} && 
				$plugins{$pkey}->{'recent'} > $recent_time){
				$iter_lastex_plugin = $new_iter;
				$recent_time = $plugins{$pkey}->{'recent'};
			}

		} else {
			print "WARNING: Program $pkey is not configured properly, ignoring\n";
		}
	
	}
	
	my $plugin_label       = Gtk2::Label->new( $d->get("Plugin") . ":" );
	my $plugin             = Gtk2::ComboBox->new($model);
	
	#plugin description
	my $plugin_descr       = Gtk2::TextBuffer->new;
	my $plugin_descr_view  = Gtk2::TextView->new_with_buffer($plugin_descr);
	$plugin_descr_view->set_sensitive(FALSE);
	$plugin_descr_view->set_wrap_mode ('word');
	my $textview_hbox = Gtk2::HBox->new( FALSE, 5 );
	$textview_hbox->set_border_width(8);
	$textview_hbox->pack_start_defaults($plugin_descr_view);

	my $plugin_descr_label = Gtk2::Label->new();
	$plugin_descr_label->set_markup( "<b>" . $d->get("Description") . "</b>" );
	my $plugin_descr_frame = Gtk2::Frame->new();
	$plugin_descr_frame->set_label_widget($plugin_descr_label);
	$plugin_descr_frame->set_shadow_type ('none');
	$plugin_descr_frame->add($textview_hbox);

	#plugin image
	my $plugin_image       = Gtk2::Image->new;
		
	#packing
	my $plugin_vbox1 = Gtk2::VBox->new( FALSE, 5 );
	my $plugin_hbox1 = Gtk2::HBox->new( FALSE, 5 );
	my $plugin_hbox2 = Gtk2::HBox->new( FALSE, 5 );
	$plugin_hbox2->set_border_width(10);

	#what plugin is selected?
	my $plugin_pixbuf = undef;
	my $plugin_name   = undef;
	my $plugin_value  = undef;
	my $plugin_lang   = undef;
	my $plugin_tip    = undef;
	my $plugin_key    = undef;
	$plugin->signal_connect(
		'changed' => sub {
			my $model       = $plugin->get_model();
			my $plugin_iter = $plugin->get_active_iter();

			if ($plugin_iter) {
				$plugin_pixbuf = $model->get_value( $plugin_iter, 0 );
				$plugin_name   = $model->get_value( $plugin_iter, 1 );
				$plugin_value  = $model->get_value( $plugin_iter, 2 );
				$plugin_lang   = $model->get_value( $plugin_iter, 3 );
				$plugin_tip    = $model->get_value( $plugin_iter, 4 );
				$plugin_key    = $model->get_value( $plugin_iter, 5 );

				$plugin_descr->set_text($plugin_tip);
				if ( $shutter_hfunct->file_exists( $plugins{$plugin_key}->{'pixbuf'} ) ) {
					$plugin_image->set_from_pixbuf( Gtk2::Gdk::Pixbuf->new_from_file_at_size( $plugins{$plugin_key}->{'pixbuf'}, 100, 100 ) );
				}
			}
		}
	);
	
	my $renderer_pix = Gtk2::CellRendererPixbuf->new;
	$plugin->pack_start( $renderer_pix, FALSE );
	$plugin->add_attribute( $renderer_pix, pixbuf => 0 );
	my $renderer_text = Gtk2::CellRendererText->new;
	$plugin->pack_start( $renderer_text, FALSE );
	$plugin->add_attribute( $renderer_text, text => 1 );
	
	#we try to activate the last executed plugin if that's possible
	$plugin->set_active_iter($iter_lastex_plugin);

	$plugin_hbox1->pack_start_defaults($plugin);

	$plugin_hbox2->pack_start_defaults($plugin_image);
	$plugin_hbox2->pack_start_defaults($plugin_descr_frame);

	$plugin_vbox1->pack_start( $plugin_hbox1, FALSE, TRUE, 1 );
	$plugin_vbox1->pack_start( $plugin_hbox2, TRUE,  TRUE, 1 );

	$plugin_dialog->vbox->add($plugin_vbox1);

	my $plugin_progress = Gtk2::ProgressBar->new;
	$plugin_progress->set_no_show_all(TRUE);
	$plugin_progress->set_ellipsize('middle');
	$plugin_progress->set_orientation('left-to-right');
	$plugin_dialog->vbox->add($plugin_progress);

	$plugin_dialog->show_all;

	my $plugin_response = $plugin_dialog->run;

	if ( $plugin_response eq "accept" ) {
		
		#anything wrong with the selected plugin?
		unless ( $plugin_value =~ /[a-zA-Z0-9]+/ ) {
			$shutter_dialog->dlg_error_message( $d->get("No plugin specified"), $d->get("Failed") );
			return FALSE;
		}

		#we save the last execution time
		#and try to preselect it when the plugin dialog is executed again
		$plugins{$plugin_key}->{'recent'} = time;

		#disable buttons and combobox
		$plugin->set_sensitive(FALSE);
		foreach my $dialog_child ($plugin_dialog->vbox->get_children){
			$dialog_child->set_sensitive(FALSE) if $dialog_child =~ /Button/;
		}

		#show the progress bar
		$plugin_progress->show;
		$plugin_progress->set_fraction(0);
		&fct_update_gui;
		my $counter = 1;

		#call execute_plugin for each file to be processed
		foreach my $key (@file_to_plugin_keys) {
			
			#update the progress bar and update gui to show changes
			#~ $plugin_progress->set_text($session_screens{$key}->{'long'});
			#~ $plugin_progress->set_fraction($counter / scalar @file_to_plugin_keys);
			#~ &fct_update_gui;
			
			#store data
			my $data = [ $plugin_value, $plugin_name, $plugin_lang, $key, $plugin_dialog, $plugin_progress ];
			&fct_execute_plugin( undef, $data );
			
			#increase counter and update gui to show updated progress bar
			$counter++;
		}

		$plugin_dialog->destroy();
		return TRUE;
	} else {
		$plugin_dialog->destroy();
		return FALSE;
	}
}

sub dlg_upload {
	my (@files_to_upload) = @_;

	return FALSE if @files_to_upload < 1;

	my $dlg_header = $d->get("Upload / Export");
	my $hosting_dialog = Gtk2::Dialog->new( $dlg_header, $window, [qw/modal destroy-with-parent/] );

	my $cancel_button = $hosting_dialog->add_button( 'gtk-cancel',       'reject' );
	my $upload_button = $hosting_dialog->add_button( $d->get("_Upload"), 'accept' );
	$upload_button->set_image( Gtk2::Image->new_from_stock( 'gtk-go-up', 'button' ) );
	$hosting_dialog->set_default_response('accept');
	my $model = Gtk2::ListStore->new( 'Glib::String', 'Glib::String', 'Glib::String', 'Glib::String' );

	foreach ( keys %accounts ) {

		#cut username so the dialog will not explode ;-)
		my $short_username = $accounts{$_}->{'username'};
		if ( length $accounts{$_}->{'username'} > 10 ) {
			$short_username = substr( $accounts{$_}->{'username'}, 0, 10 ) . "...";
		}

		$model->set( $model->append, 0, $accounts{$_}->{'host'}, 1, $accounts{$_}->{'username'}, 2, $accounts{$_}->{'password'}, 3, $short_username )
			if ($accounts{$_}->{'username'} ne "" && $accounts{$_}->{'password'} ne "" );			
		
		$model->set( $model->append, 0, $accounts{$_}->{'host'}, 1, $d->get("Guest"), 2, "", 3, $d->get("Guest") );
	}

	my $hosting_image = Gtk2::Image->new;

	#set up account combobox
	my $hosting       = Gtk2::ComboBox->new($model);
	my $renderer_host = Gtk2::CellRendererText->new;
	$hosting->pack_start( $renderer_host, FALSE );
	$hosting->add_attribute( $renderer_host, text => 0 );
	my $renderer_username = Gtk2::CellRendererText->new;
	$hosting->pack_start( $renderer_username, FALSE );
	$hosting->add_attribute( $renderer_username, text => 3 );
	#~ $hosting->signal_connect(
		#~ 'changed' => sub {
#~ 
			#~ my $model        = $hosting->get_model();
			#~ my $hosting_iter = $hosting->get_active_iter();
#~ 
			#~ if ($hosting_iter) {
				#~ my $hosting_host     = $model->get_value( $hosting_iter, 0 );
				#~ my $hosting_username = $model->get_value( $hosting_iter, 1 );
				#~ if ( $hosting_host =~ /imageshack/i ) {
					#~ $hosting_image->set_from_pixbuf(
						#~ Gtk2::Gdk::Pixbuf->new_from_file_at_scale( "$shutter_root/share/shutter/resources/icons/logo-imageshack.png", 200, 200, TRUE )
					#~ );
				#~ } elsif ( $hosting_host =~ /imagebanana/i ) {
					#~ $hosting_image->set_from_pixbuf(
						#~ Gtk2::Gdk::Pixbuf->new_from_file_at_scale( "$shutter_root/share/shutter/resources/icons/logo-imagebanana.png", 200, 200, TRUE )
					#~ );
				#~ } elsif ( $hosting_host =~ /ubuntu-pics/i ) {
					#~ $hosting_image->set_from_pixbuf(
						#~ Gtk2::Gdk::Pixbuf->new_from_file_at_scale( "$shutter_root/share/shutter/resources/icons/logo-ubuntu-pics.png", 200, 200, TRUE )
					#~ );
				#~ }
#~ 
			#~ }
		#~ },
		#~ 'changed'
	#~ );

	$hosting->set_active(0);

	#public hosting settings
	my $pub_hbox1 = Gtk2::HBox->new( FALSE, 12 );
	my $pub_hbox2 = Gtk2::HBox->new( FALSE, 12 );
	my $pub_vbox1 = Gtk2::VBox->new( FALSE, 12 );
	$pub_hbox2->set_border_width(12);
	$pub_hbox1->set_border_width(12);
	$pub_hbox2->set_border_width(12);
	$pub_vbox1->set_border_width(12);
	$pub_hbox1->pack_start( Gtk2::Label->new( $d->get("Choose account"). ":" ), FALSE, FALSE, 6 );
	$pub_hbox1->pack_start_defaults($hosting);
	$pub_vbox1->pack_start($pub_hbox1, FALSE, FALSE, 6);

	#places settings
	my $pl_hbox1 = Gtk2::HBox->new( FALSE, 12 );
	my $pl_vbox1 = Gtk2::VBox->new( FALSE, 12 );
 	$pl_hbox1->set_border_width(12);
 	$pl_vbox1->set_border_width(12);
	my $places_fc = Gtk2::FileChooserButton->new_with_backend ("Shutter - " . $d->get("Choose folder"), 'select-folder', 'gnome-vfs');	
	$places_fc->set('local-only' => FALSE);
	$pl_hbox1->pack_start( Gtk2::Label->new( $d->get("Choose folder"). ":" ), FALSE, FALSE, 6 );
	$pl_hbox1->pack_start_defaults($places_fc);
	$pl_vbox1->pack_start($pl_hbox1, FALSE, FALSE, 6);

	#ftp settings
	#we are using the same widgets as in the settings and populate
	#them with saved values when possible
	my $ftp_hbox1_dlg = Gtk2::HBox->new( FALSE, 0 );
	my $ftp_hbox2_dlg = Gtk2::HBox->new( FALSE, 0 );
	my $ftp_hbox3_dlg = Gtk2::HBox->new( FALSE, 0 );
	my $ftp_hbox4_dlg = Gtk2::HBox->new( FALSE, 0 );

	#uri
	my $ftp_entry_label_dlg = Gtk2::Label->new( $d->get("URI") . ":");
	$ftp_hbox1_dlg->pack_start( $ftp_entry_label_dlg, FALSE, TRUE, 10 );
	my $ftp_remote_entry_dlg = Gtk2::Entry->new;
	$ftp_remote_entry_dlg->set_text( $ftp_remote_entry->get_text );

	$tooltips->set_tip( $ftp_entry_label_dlg, $d->get("URI\nExample: ftp://host:port/path") );

	$tooltips->set_tip( $ftp_remote_entry_dlg, $d->get("URI\nExample: ftp://host:port/path") );

	$ftp_hbox1_dlg->pack_start( $ftp_remote_entry_dlg, TRUE, TRUE, 10 );

	#connection mode
	my $ftp_mode_label_dlg = Gtk2::Label->new( $d->get("Connection mode") . ":");
	$ftp_hbox2_dlg->pack_start( $ftp_mode_label_dlg, FALSE, TRUE, 10 );
	my $ftp_mode_combo_dlg = Gtk2::ComboBox->new_text;
	$ftp_mode_combo_dlg->insert_text( 0, $d->get("Active mode") );
	$ftp_mode_combo_dlg->insert_text( 1, $d->get("Passive mode") );
	$ftp_mode_combo_dlg->set_active( $ftp_mode_combo->get_active );

	$tooltips->set_tip( $ftp_mode_label_dlg, $d->get("Connection mode") );

	$tooltips->set_tip( $ftp_mode_combo_dlg, $d->get("Connection mode") );

	$ftp_hbox2_dlg->pack_start( $ftp_mode_combo_dlg, TRUE, TRUE, 10 );

	#username
	my $ftp_username_label_dlg = Gtk2::Label->new( $d->get("Username") . ":");
	$ftp_hbox3_dlg->pack_start( $ftp_username_label_dlg, FALSE, TRUE, 10 );
	my $ftp_username_entry_dlg = Gtk2::Entry->new;
	$ftp_username_entry_dlg->set_text( $ftp_username_entry->get_text );

	$tooltips->set_tip( $ftp_username_label_dlg, $d->get("Username") );

	$tooltips->set_tip( $ftp_username_entry_dlg, $d->get("Username") );

	$ftp_hbox3_dlg->pack_start( $ftp_username_entry_dlg, TRUE, TRUE, 10 );

	#password
	my $ftp_password_label_dlg = Gtk2::Label->new( $d->get("Password") . ":");
	$ftp_hbox4_dlg->pack_start( $ftp_password_label_dlg, FALSE, TRUE, 10 );
	my $ftp_password_entry_dlg = Gtk2::Entry->new;
	$ftp_password_entry_dlg->set_invisible_char("*");
	$ftp_password_entry_dlg->set_visibility(FALSE);
	$ftp_password_entry_dlg->set_text( $ftp_password_entry->get_text );

	$tooltips->set_tip( $ftp_password_label_dlg, $d->get("Password") );

	$tooltips->set_tip( $ftp_password_entry_dlg, $d->get("Password") );

	$ftp_hbox4_dlg->pack_start( $ftp_password_entry_dlg, TRUE, TRUE, 10 );

	my $ftp_vbox_dlg = Gtk2::VBox->new( FALSE, 0 );
	$ftp_vbox_dlg->pack_start( $ftp_hbox1_dlg, FALSE, TRUE, 3 );
	$ftp_vbox_dlg->pack_start( $ftp_hbox2_dlg, FALSE, TRUE, 3 );
	$ftp_vbox_dlg->pack_start( $ftp_hbox3_dlg, FALSE, TRUE, 3 );
	$ftp_vbox_dlg->pack_start( $ftp_hbox4_dlg, FALSE, TRUE, 3 );

	#all labels = one size
	$ftp_entry_label_dlg->set_alignment( 0, 0.5 );
	$ftp_mode_label_dlg->set_alignment( 0, 0.5 );
	$ftp_username_label_dlg->set_alignment( 0, 0.5 );
	$ftp_password_label_dlg->set_alignment( 0, 0.5 );

	my $sg_ftp_dlg = Gtk2::SizeGroup->new('horizontal');
	$sg_ftp_dlg->add_widget($ftp_entry_label_dlg);
	$sg_ftp_dlg->add_widget($ftp_mode_label_dlg);
	$sg_ftp_dlg->add_widget($ftp_username_label_dlg);
	$sg_ftp_dlg->add_widget($ftp_password_label_dlg);

	#setup notebook
	my $unotebook = Gtk2::Notebook->new;
	$unotebook->set( homogeneous  => TRUE );
	
	$unotebook->append_page($pub_vbox1, $d->get("Public hosting"));
	$unotebook->append_page($ftp_vbox_dlg, "FTP");
	$unotebook->append_page($pl_vbox1, $d->get("Places"));
	
	$unotebook->signal_connect( 'switch-page' => sub {
		my ( $unotebook, $pointer, $int ) = @_;
		
		my $hbox = $upload_button->get_child->get_child;
		foreach($hbox->get_children){
			if($int == 2 && $_ =~ /Gtk2::Label/){
				$_->set_text_with_mnemonic($d->get("_Export"));
				last;
			}elsif($_ =~ /Gtk2::Label/){
				$_->set_text_with_mnemonic($d->get("_Upload"));
				last;
			}
		}
		
	} );

	$hosting_dialog->vbox->add($unotebook);

	my $hosting_progress = Gtk2::ProgressBar->new;
	$hosting_progress->set_no_show_all(TRUE);
	$hosting_progress->set_ellipsize('middle');
	$hosting_progress->set_orientation('left-to-right');
	$hosting_dialog->vbox->add($hosting_progress);

	$hosting_dialog->show_all;
UPDIALOG: while ($hosting_dialog) {

		#initial state of dialog
		$upload_button->set_sensitive(TRUE);
		$cancel_button->set_sensitive(TRUE);
		$hosting_progress->hide;

		#DIALOG RUN
		my $hosting_response = $hosting_dialog->run;

		#running state of dialog
		$upload_button->set_sensitive(FALSE);
		$cancel_button->set_sensitive(FALSE);
		$hosting_progress->show;

		#start upload
		if ( $hosting_response eq "accept" ) {

			#public hosting
			if ( $unotebook->get_current_page == 0 ) {
				my $model            = $hosting->get_model();
				my $hosting_iter     = $hosting->get_active_iter();
				my $hosting_host     = $model->get_value( $hosting_iter, 0 );
				my $hosting_username = $model->get_value( $hosting_iter, 1 );
				my $hosting_password = $model->get_value( $hosting_iter, 2 );
				if ( $hosting_host eq "ubuntu-pics.de" ) {
					my $uploader
						= Shutter::Upload::UbuntuPics->new( $hosting_host, $shutter_common->get_debug, $shutter_root, $d, $window, SHUTTER_VERSION );
					my $counter = 1;
					$hosting_progress->set_fraction(0);
					foreach my $file ( sort @files_to_upload ) {
						$hosting_progress->set_text($file);
						
						#update gui
						&fct_update_gui;
						
						my %upload_response = $uploader->upload( $shutter_hfunct->switch_home_in_file($file), $hosting_username, $hosting_password );

						if ( is_success( $upload_response{'status'} ) ) {
							$uploader->show;
							&dlg_status_message( 1, $file . " " . $d->get("uploaded") );
						} else {
							my $response = &dlg_upload_error_message( $upload_response{'status'}, $upload_response{'max_filesize'} );

							#10 == skip all, 20 == skip, else == cancel
							last if $response == 10;
							next if $response == 20;
							redo if $response == 30;
							next UPDIALOG;
						}
						$hosting_progress->set_fraction( $counter / @files_to_upload );

						#update gui
						&fct_update_gui;
						$counter++;
					}
					$uploader->show_all;
				} elsif ( $hosting_host eq "imagebanana.com" ) {
					my $uploader
						= Shutter::Upload::ImageBanana->new( $hosting_host, $shutter_common->get_debug, $shutter_root, $d, $window, SHUTTER_VERSION );
					my $counter = 1;
					$hosting_progress->set_fraction(0);
					foreach my $file (@files_to_upload) {
						$hosting_progress->set_text($file);

						#update gui
						&fct_update_gui;
						my %upload_response = $uploader->upload( $shutter_hfunct->switch_home_in_file($file), $hosting_username, $hosting_password );

						if ( is_success( $upload_response{'status'} ) ) {
							$uploader->show;
							&dlg_status_message( 1, $file . " " . $d->get("uploaded") );
						} else {
							my $response = &dlg_upload_error_message( $upload_response{'status'}, $upload_response{'max_filesize'} );

							#10 == skip all, 20 == skip, else == cancel
							last if $response == 10;
							next if $response == 20;
							redo if $response == 30;
							next UPDIALOG;
						}
						$hosting_progress->set_fraction( $counter / @files_to_upload );

						#update gui
						&fct_update_gui;
						$counter++;
					}
					$uploader->show_all;
				} elsif ( $hosting_host eq "imageshack.us" ) {
					my $ishack = Shutter::Upload::ImageShack->new();
					
					#clear possible cookie (is this really needed here?)
					$ishack->logout;
										
					#upload
					my $counter = 1;
					$hosting_progress->set_fraction(0);
					foreach my $file (@files_to_upload) {

						#login
						eval { $ishack->login($hosting_username, $hosting_password); };
						if ($@) {
							my $response = $shutter_dialog->dlg_error_message( $d->get("Please check your credentials and try again."),
								$d->get("Login failed!") );

							next UPDIALOG;
						}

						$hosting_progress->set_text($file);

						#update gui
						&fct_update_gui;
						my $url = undef;
						eval { $url = $ishack->host( $file, undef ); };
						if ($@) {
							my $response = $shutter_dialog->dlg_error_message(
								$d->get("Please check your connectivity and try again."),
								$d->get("Connection error!"),
								$d->get("Skip all"), 
								$d->get("Skip"), 
								'gtk-redo'
							);

							#10 == skip all, 20 == skip, else == cancel
							last if $response == 10;
							next if $response == 20;
							redo if $response == 30;
							next UPDIALOG;
						}

						#get thumbnail url
						my $thumb_url = undef;
						eval { $thumb_url = $ishack->hosted_thumb; };

						if ($url) {
							$ishack->show( $hosting_host, $hosting_username, $file, $url, $thumb_url, RC_OK, $d, $window, $shutter_root );
							&dlg_status_message( 1, $file . " " . $d->get("uploaded") );
						} else {
							my $response = $shutter_dialog->dlg_error_message(
								$d->get("Please check your connectivity and try again."),
								$d->get("Connection error!"),
								$d->get("Skip all"), 
								$d->get("Skip"), 
								'gtk-redo'
							);

							#10 == skip all, 20 == skip, else == cancel
							last if $response == 10;
							next if $response == 20;
							redo if $response == 30;
							next UPDIALOG;
						}
						$hosting_progress->set_fraction( $counter / @files_to_upload );

						#update gui
						&fct_update_gui;
						$counter++;
					}
					$ishack->show_all;
				}

				#ftp
			} elsif ( $unotebook->get_current_page == 1 ) {

				#create upload object
				my $uploader = Shutter::Upload::FTP->new( $shutter_common->get_debug, $shutter_root, $d, $window, $ftp_mode_combo_dlg->get_active );

				my $counter = 1;
				my $login   = FALSE;
				$hosting_progress->set_fraction(0);

				#start upload
				foreach my $file (sort @files_to_upload) {

					#need to login?
					my @upload_response;
					unless ($login) {

						eval { $uploader->quit; };

						@upload_response = $uploader->login( $ftp_remote_entry_dlg->get_text, $ftp_username_entry_dlg->get_text,
							$ftp_password_entry_dlg->get_text );

						if ($upload_response[0]) {

							#we already get translated error messaged back
							my $response = $shutter_dialog->dlg_error_message( 
								$upload_response[1], 
								$upload_response[0],
								undef, undef, undef,
								undef, undef, undef,
								$upload_response[2]
							);
							next UPDIALOG;
						} else {
							$login = TRUE;
						}

					}

					$hosting_progress->set_text($file);

					#update gui
					&fct_update_gui;
					@upload_response = $uploader->upload( $shutter_hfunct->switch_home_in_file($file) );
				
					#upload returns FALSE if there is no error
					unless ($upload_response[0]) {
						#everything is fine here
						&dlg_status_message( 1, $file . " " . $d->get("uploaded") );
					} else {

						#we already get translated error messaged back
						my $response = $shutter_dialog->dlg_error_message( 
							$upload_response[1], 
							$upload_response[0],
							$d->get("Skip all"), 
							$d->get("Skip"),
							'gtk-redo',
							undef, undef, undef,
							$upload_response[2]
						);

						#10 == skip all, 20 == skip, 30 == redo, else == cancel
						if ( $response == 10 ) {
							last;
						} elsif ( $response == 20 ) {
							$login = FALSE;
							next;
						} elsif ( $response == 30 ) {
							$login = FALSE;
							redo;
						} else {
							next UPDIALOG;
						}

					}
					$hosting_progress->set_fraction( $counter / @files_to_upload );

					#update gui
					&fct_update_gui;
					$counter++;
				}    #end foreach
				$uploader->quit;
			
			
			#places using Gnone-VFS
			} elsif ( $unotebook->get_current_page == 2 ) {
		
				my $counter = 1;
				$hosting_progress->set_fraction(0);

				#start upload
				foreach my $file (sort @files_to_upload) {
					
					$hosting_progress->set_text($file);
					
					#update gui
					&fct_update_gui;

					my $source_uri = Gnome2::VFS::URI->new ($file);
					my $target_uri = Gnome2::VFS::URI->new ($places_fc->get_uri);
					$target_uri = $target_uri->append_file_name($source_uri->extract_short_name);

					print $source_uri->to_string . " - " . $target_uri->to_string."\n" if $shutter_common->get_debug;
					my $result;
					unless($target_uri->exists){
						$result = Gnome2::VFS::Xfer->uri ($source_uri, $target_uri, 'default', 'abort', 'replace', sub{ return TRUE });
					}else{
						$result = 'error-file-exists';	
					}

					if($result eq 'ok'){
					
						#everything is fine here
						if($target_uri->is_local){
							&dlg_status_message( 1, $file . " " . $d->get("exported") );
						}else{
							&dlg_status_message( 1, $file . " " . $d->get("uploaded") );
						}
					
					}elsif($result eq 'error-file-exists'){

						#ask the user to replace the image
						#replace button
						my $replace_btn = Gtk2::Button->new_with_mnemonic( $d->get("_Replace") );
						$replace_btn->set_image( Gtk2::Image->new_from_stock( 'gtk-save-as', 'button' ) );

						my $target_path=undef;
						if($target_uri->is_local){
							$target_path = Gnome2::VFS->unescape_string_for_display ($target_uri->extract_dirname);
						}else{								
							$target_path = Gnome2::VFS->unescape_string_for_display ($target_uri->get_scheme."://".$target_uri->get_host_name.$target_uri->extract_dirname);
						}

						my $response = $shutter_dialog->dlg_warning_message(
							sprintf( $d->get("The image already exists in %s. Replacing it will overwrite its contents."), "'" . $target_path ."'"),
							sprintf( $d->get("An image named %s already exists. Do you want to replace it?"), "'" . $target_uri->extract_short_name . "'" ),
							$d->get("Skip all"), $d->get("Skip"),
							undef,
							$replace_btn,
							undef, undef
						);

						#10 == skip all, 20 == skip, 40 == replace, else == cancel
						if ( $response == 10 ) {
							last;
						} elsif ( $response == 20 ) {
							next;
						} elsif ( $response == 40 ) {
							$result = Gnome2::VFS::Xfer->uri ($source_uri, $target_uri, 'default', 'abort', 'replace', sub{ return TRUE });
							
							#check result again
							if($result eq 'ok'){	
								#everything is fine here
								if($target_uri->is_local){
									&dlg_status_message( 1, $file . " " . $d->get("exported") );
								}else{
									&dlg_status_message( 1, $file . " " . $d->get("uploaded") );
								}			
							} else{

								my $response = &dlg_upload_error_message_gnome_vfs($target_uri, $result);

								#10 == skip all, 20 == skip, 30 == redo, else == cancel
								if ( $response == 10 ) {
									last;
								} elsif ( $response == 20 ) {
									next;
								} elsif ( $response == 30 ) {
									redo;
								} else {
									next UPDIALOG;
								}										
								
							}
						}	
						
					}else{

						my $response = &dlg_upload_error_message_gnome_vfs($target_uri, $result);

						#10 == skip all, 20 == skip, 30 == redo, else == cancel
						if ( $response == 10 ) {
							last;
						} elsif ( $response == 20 ) {
							next;
						} elsif ( $response == 30 ) {
							redo;
						} else {
							next UPDIALOG;
						}					
		
					}

					$hosting_progress->set_fraction( $counter / @files_to_upload );

					#update gui
					&fct_update_gui;
					$counter++;
													
				}
				
			}

			$hosting_dialog->destroy();
			return TRUE;
		} else {
			$hosting_dialog->destroy();
			return FALSE;
		}    #if response == accept

	}    #dialog loop
}

sub dlg_upload_error_message_gnome_vfs {
	my $target_uri = shift;
	my $result = shift;

	my $target_path=undef;
	if($target_uri->is_local){
		$target_path = Gnome2::VFS->unescape_string_for_display ($target_uri->extract_dirname);
	}else{								
		$target_path = Gnome2::VFS->unescape_string_for_display ($target_uri->get_scheme."://".$target_uri->get_host_name.$target_uri->extract_dirname);
	}

	my $response = $shutter_dialog->dlg_warning_message( 
		sprintf( $d->get(  "Error while copying the image %s."), "'" . $target_uri->extract_short_name . "'"),
		sprintf( $d->get(  "There was an error copying the image into %s."), "'" . $target_path . "'" ),
		$d->get("Skip all"), 
		$d->get("Skip"),
		'gtk-redo',
		undef,
		undef,
		undef,
		Gnome2::VFS->result_to_string ($result)
	);
	
	return $response;
	
}

sub dlg_upload_error_message {
	my ( $status, $max_filesize ) = @_;

	my $response;
	if ( $status == 999 ) {
		$response = $shutter_dialog->dlg_error_message( $d->get("Please check your credentials and try again."), $d->get("Login failed!") );
	} elsif ( $status == 998 ) {
		$response = $shutter_dialog->dlg_error_message( $d->get("Maximum filesize reached!") . " ( $max_filesize )",
			$d->get("Failed"), $d->get("Skip all"), $d->get("Skip") );
	} else {
		$response = $shutter_dialog->dlg_error_message(
			$d->get("Please check your connectivity and try again."),
			$d->get("Connection error!") . " (" . $status . ")",
			$d->get("Skip all"), $d->get("Skip"), 'gtk-redo'
		);
	}
	return $response;
}

sub dlg_website {
	my ( $filename, $filetype_value, $quality_value ) = @_;

	my $screenshot  = undef;
	my $web_process = Proc::Simple->new;
	
	#redirect outputs
	my ( $tmpfh_stdout, $tmpfilename_stdout ) = tempfile(UNLINK => 1);
	my ( $tmpfh_stderr, $tmpfilename_sterr ) = tempfile(UNLINK => 1);
  	$web_process->redirect_output ($tmpfilename_stdout, $tmpfilename_sterr);

	my $website_dialog = Gtk2::MessageDialog->new( $window, [qw/modal destroy-with-parent/], 'other', 'none', undef );

	$website_dialog->set_title("Shutter");

	$website_dialog->set( 'text' => $d->get("Take a screenshot of a website") );

	$website_dialog->set( 'secondary-text' => $d->get("URL to capture") . ": " );

	if($icontheme->has_icon('applications-internet')){
		$website_dialog->set(
			'image' => Gtk2::Image->new_from_icon_name( 'applications-internet', 'dialog' ) );		
	}else{
		$website_dialog->set(
			'image' => Gtk2::Image->new_from_pixbuf(
				Gtk2::Gdk::Pixbuf->new_from_file_at_size( "$shutter_root/share/shutter/resources/icons/web_image.svg", Gtk2::IconSize->lookup('dialog') )
			)
		);
	}

	#cancel button
	my $cancel_btn = Gtk2::Button->new_from_stock('gtk-cancel');

	#save button
	my $execute_btn = Gtk2::Button->new_from_stock('gtk-execute');
	$execute_btn->can_default(TRUE);

	$website_dialog->add_action_widget( $cancel_btn,  'cancel' );
	$website_dialog->add_action_widget( $execute_btn, 'accept' );

	$website_dialog->set_default_response('accept');

	my $website_hbox  = Gtk2::HBox->new();
	my $website_hbox2 = Gtk2::HBox->new();

	my $website = Gtk2::Entry->new;
	$website->set_text("http://www.");
	$website->set_activates_default(TRUE);
	
	#~ eval{
		#~ require Google::Search;	
	#~ };
	#~ unless($@){
#~ 
		#~ #try to use Google::Search for autocompletion
		#~ my $api_key = "ABQIAAAA1MzQeGgjv24cQH6It97vbhQ7KJkd-ijgFr7toX7MFGWAtZ4alhQBHxiKkuXsCsTQklemxTfVOgjxGg";
		#~ my $referer = "http://shutter-project.org";
		#~ my $web_compl = Gtk2::EntryCompletion->new;
		#~ $web_compl->set_popup_completion (TRUE);
		#~ $web_compl->set_text_column (0);
		#~ my $model = Gtk2::ListStore->new( 'Glib::String' );
		#~ $web_compl->set_model($model);
#~ 
		#~ $website->set_completion ($web_compl);
		#~ $website->signal_connect('changed' => sub{
#~ 
				#~ #search when idle
				#~ Glib::Idle->add (
					#~ sub{
						#~ 
						#~ #clear model for each search	
						#~ $model->clear;
						#~ 
						#~ my $search = Google::Search->Web( q => $website->get_text, key => $api_key, referer => $referer);
						#~ my $result = $search->first;
						#~ 
						#~ #append first 3 results to model
						#~ #we take 3 because of performace reasons here
						#~ while ($result) {
							#~ last if $result->number == 3;
							#~ $model->set( $model->append, 0, $result->uri );
							#~ $result = $result->next;
						#~ }
						#~ 
						#~ return FALSE;
					#~ });	
		#~ 
			#~ return FALSE;	
		#~ });
	#~ }

	my $clipboard_string = $clipboard->wait_for_text;
	print "Content of clipboard is: $clipboard_string\n"
		if $shutter_common->get_debug;

	if ( defined $clipboard_string ) {
		if (   $clipboard_string =~ /^http/
			|| $clipboard_string =~ /^file/
			|| $clipboard_string =~ /^www\./ )
		{
			$website->set_text($clipboard_string);
		}
	}

	$website_hbox->pack_start( $website, TRUE, TRUE, 12 );
	$website_dialog->vbox->add($website_hbox);

	my $website_progress = Gtk2::ProgressBar->new;
	$website_progress->set_no_show_all(TRUE);
	$website_progress->set_ellipsize('middle');
	$website_progress->set_orientation('left-to-right');
	$website_progress->set_fraction(0);
	$website_hbox2->pack_start( $website_progress, TRUE, TRUE, 12 );
	$website_dialog->vbox->add($website_hbox2);

	$website_dialog->show_all;
	my $website_response = $website_dialog->run;

	if ( $website_response eq "accept" ) {

		$execute_btn->set_sensitive(FALSE);

		#show progress bar while executing gnome-web-photo
		$website_progress->show;
		&fct_update_gui;

		my $url      = $website->get_text;
		my $hostname = $url;
		$hostname =~ s/http:\/\///;

		if ( $hostname eq "" ) {
			$shutter_dialog->dlg_error_message( $d->get("No valid url entered"), $d->get("Failed") );
			$website_dialog->destroy();
			return $screenshot;
		}

		#determining timeout
		my $web_menu = $shutter_tool->{_web}->get_menu;
		my @timeouts = $web_menu->get_children;
		my $timeout  = undef;
		foreach (@timeouts) {
			if ( $_->get_active ) {
				$timeout = $_->get_children->get_text;
				$timeout =~ /([0-9]+)/;
				$timeout = $1;
				print $timeout. "\n" if $shutter_common->get_debug;
			}
		}

		my $screenshooter = Shutter::Screenshot::Web->new( $timeout, $filetype_value, $quality_value, $url, $filename );

		Proc::Simple::debug(1) if $shutter_common->get_debug;

		$web_process->start(
			sub {
				$screenshooter->web();
				POSIX::_exit(0);
			}
		);
		
		$website_dialog->signal_connect(
			'delete-event' => sub{
				#kill process, delete file and destroy dialog
				$web_process->kill('SIGKILL');				
				unlink("$filename");
				$website_dialog->destroy();				
			} 
		);

		$cancel_btn->signal_connect(
			'clicked' => sub {
				#kill process, delete file and destroy dialog
				$web_process->kill('SIGKILL');				
				unlink("$filename");
				$website_dialog->destroy();
			}
		);

		while ( $web_process->poll ) {
			$website_progress->pulse;
			&fct_update_gui;
			usleep 100000;
		}

		#we cannot kill the process anymore
		#closing the dialog will confuse the user
		#because the image will appear in the session later on
		$cancel_btn->set_sensitive(FALSE);
		&fct_update_gui;

		#exit status == OK
		if ( $web_process->exit_status() == 0 ) {

			$website_progress->set_fraction( 2 / 3 );
			&fct_update_gui;

			eval { $screenshot = Gtk2::Gdk::Pixbuf->new_from_file($filename) };
			if ($@) {
				#reading stdout from file
				while (<$tmpfh_stdout>){
					$screenshot .= $_;	
				}
				#reading stderr from file
				while (<$tmpfh_stderr>){
					$screenshot .= $_;	
				}
				unlink($filename);
				$website_dialog->destroy();
			}

			$website_progress->set_fraction( 3 / 3 );
			&fct_update_gui;
	
		#exit status == FAIL
		}else{
			#reading stdout from file
			while (<$tmpfh_stdout>){
				$screenshot .= $_;	
			}
			#reading stderr from file
			while (<$tmpfh_stderr>){
				$screenshot .= $_;	
			}
		}

		$website_dialog->destroy();

		return $screenshot;
	} else {
		$website_dialog->destroy();

		return $screenshot;
	}
}

sub dlg_profile_name {
	my ( $curr_profile_name, $combobox_settings_profiles ) = @_;

	my $profile_dialog = Gtk2::MessageDialog->new( $window, [qw/modal destroy-with-parent/], 'other', 'none', undef );

	$profile_dialog->set_title("Shutter");

	$profile_dialog->set( 'image' => Gtk2::Image->new_from_stock( 'gtk-dialog-question', 'dialog' ) );

	$profile_dialog->set( 'text' => $d->get( "Save current preferences as new profile") );

	$profile_dialog->set( 'secondary-text' => $d->get("New profile name") . ": " );

	$profile_dialog->add_button( 'gtk-cancel', 10 );
	$profile_dialog->add_button( 'gtk-save', 20 );

	$profile_dialog->set_default_response(20);

	my $new_profile_name_vbox = Gtk2::VBox->new();
	my $new_profile_name_hint = Gtk2::Label->new();	
	my $new_profile_name      = Gtk2::Entry->new();
	$new_profile_name->set_activates_default(TRUE);

	#here are all invalid char codes
	my @invalid_codes = (47,92,63,37,42,58,124,34,60,62,44,59,35,38);
	$new_profile_name->signal_connect('key-press-event' => sub {
		my $new_profile_name 	= shift;
		my $event 			= shift;
		
		my $input = Gtk2::Gdk->keyval_to_unicode ($event->keyval); 
		
		#invalid input
		#~ print $input."\n";
		if(grep($input == $_, @invalid_codes)){
			my $char = chr($input);
			$char = '&amp;' if $char eq '&';
			$new_profile_name_hint->set_markup("<span size='small'>" . 
											sprintf($d->get("Reserved character %s is not allowed to be in a filename.") , "'".$char."'") 
											. "</span>");	
			return TRUE;
		}else{
			#clear possible message when valid char is entered
			$new_profile_name_hint->set_markup("<span size='small'></span>");						
			return FALSE;
		}
	});

	#show name of current profile
	$new_profile_name->set_text( $curr_profile_name)
		if defined $curr_profile_name;

	$new_profile_name_vbox->pack_start_defaults($new_profile_name);
	$new_profile_name_vbox->pack_start_defaults($new_profile_name_hint);
	$profile_dialog->vbox->add($new_profile_name_vbox);
	$profile_dialog->show_all;

	#run dialog
	my $profile_response = $profile_dialog->run;

	#handle user responses here
	if ( $profile_response == 20 ) {
		my $entered_name = $new_profile_name->get_text;

		if ( $shutter_hfunct->file_exists("$ENV{'HOME'}/.shutter/profiles/$entered_name.xml") ) {

			#ask the user to replace the profile
			#replace button
			my $replace_btn = Gtk2::Button->new_with_mnemonic( $d->get("_Replace") );
			$replace_btn->set_image( Gtk2::Image->new_from_stock( 'gtk-save-as', 'button' ) );

			my $response = $shutter_dialog->dlg_warning_message(
				$d->get("Replacing it will overwrite its contents."),
				sprintf( $d->get("A profile named %s already exists. Do you want to replace it?"), "'" . $entered_name . "'"),
				undef, undef, undef,
				$replace_btn, undef, undef
			);

			#rename == replace_btn was hit
			if ( $response == 40 ) {
				$profile_dialog->destroy();
				return $new_profile_name->get_text;
			} else {
				$profile_dialog->destroy();
				return FALSE;
			}
		}

		$profile_dialog->destroy();
		return $new_profile_name->get_text;
	} else {
		$profile_dialog->destroy();
		return FALSE;
	}
}

sub fct_zoom_in {
	my $key = &fct_get_current_file;
	if($key){
		$session_screens{$key}->{'image'}->zoom_in;	
	}
}

sub fct_zoom_out {
	my $key = &fct_get_current_file;
	if($key){
		$session_screens{$key}->{'image'}->zoom_out;		
	}	
}

sub fct_zoom_100 {
	my $key = &fct_get_current_file;
	if($key){
		$session_screens{$key}->{'image'}->set_zoom(1);			
	}	
}

sub fct_zoom_best {
	my $key = &fct_get_current_file;
	if($key){
		$session_screens{$key}->{'image'}->set_fitting(TRUE);			
	}	
}

sub fct_fullscreen {
	my ($widget) = @_;
	
	if($widget->get_active){
		$window->fullscreen;			
	}else{
		$window->unfullscreen;	
	}
}

#--------------------------------------

