package PACEdit;
###################################################################
# This file is part of PAC( Perl Auto Connector)
#
# Copyright (C) 2010 David Torrejon Vaquerizas
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
###################################################################
$|++;
###################################################################
# Import Modules
BEGIN
{
use FindBin qw ( $RealBin $Bin $Script );
push( @INC, $RealBin . '/lib/edit' );
}
# Standard
use strict;
use warnings;
use FindBin qw ( $RealBin $Bin $Script );
use YAML qw ( LoadFile DumpFile );
use Storable;
use Encode;
#use Data::Dumper;
# GTK2
use Gtk2 '-init';
use Gtk2::GladeXML;
use Gtk2::Ex::Simple::List;
# PAC modules
use PACUtils;
use PACMethod;
use PACExpectEntry;
use PACExecEntry;
use PACPrePostEntry;
use PACVarEntry;
use PACTermOpts;
# END: Import Modules
###################################################################
###################################################################
# Define GLOBAL CLASS variables
my $APPNAME = $PACUtils::APPNAME;
my $APPVERSION = $PACUtils::APPVERSION;
my $RES_DIR = $RealBin . '/res';
my $APPICON = $RES_DIR . '/pac64x64.png';
my $TRAYICON = $RES_DIR . '/pac_tray.png';
my $TABICON = $RES_DIR . '/pac_tab.png';
my $AUTOSTART_FILE = $RES_DIR . '/pac_start.desktop';
my $GLADE_FILE = $RES_DIR . '/pac.glade';
my $INIT_CFG_FILE = $RES_DIR . '/pac.yml';
my $CFG_DIR = $ENV{'HOME'} . '/.pac';
my $CFG_FILE = $CFG_DIR . '/pac.yml';
# END: Define GLOBAL CLASS variables
###################################################################
###################################################################
# START: Define PUBLIC CLASS methods
sub new
{
my $class = shift;
my $self = {};
$self -> {_CFG} = shift;
$self -> {_ENVIRONMENT} = undef;
$self -> {_CONNECTION} = undef;
$self -> {_GLADE} = undef;
@{ $self -> {_UNDO} } = ();
$self -> {_WINDOWEDIT} = undef;
$self -> {_SPECIFIC} = undef;
$self -> {_PRE_EXEC} = undef;
$self -> {_POST_EXEC} = undef;
$self -> {_EXPECT_EXEC} = undef;
$self -> {_MACROS} = undef;
$self -> {_LOCAL_EXEC} = undef;
$self -> {_TXTOPTSBUFFER} = undef;
# Setup known connection methods
%{ $$self{_METHODS} } = _getMethods( $self );
# Build the GUI
_initGUI( $self ) or return 0;
# Setup callbacks
_setupCallbacks( $self );
bless( $self, $class );
return $self;
}
# DESTRUCTOR
sub DESTROY
{
my $self = shift;
undef $self;
return 1;
}
# Start GUI
sub show
{
my $self = shift;
$$self{_ENVIRONMENT} = shift;
$$self{_CONNECTION} = shift;
$self -> _updateGUIPreferences;
$$self{_WINDOWEDIT} -> set_title( "Editing '$$self{_ENVIRONMENT} -> $$self{_CONNECTION}' : $APPNAME (v$APPVERSION)" );
$$self{_WINDOWEDIT} -> present;
return 1;
}
# END: Define PUBLIC CLASS methods
###################################################################
###################################################################
# START: Define PRIVATE CLASS functions
sub _initGUI
{
my $self = shift;
# Load XML Glade file
$$self{_GLADE} = Gtk2::GladeXML -> new( $GLADE_FILE ) or die "ERROR: Could not load GLADE file '$GLADE_FILE' ($!)";
# Save main, about and add windows
$$self{_WINDOWEDIT} = $$self{_GLADE} -> get_widget ('windowEdit');
#_( $self, 'alignSpecific' ) -> add( ( $$self{_SPECIFIC} = PACMethod -> new() ) -> {container} );
$$self{_SPECIFIC} = PACMethod -> new;
_( $self, 'alignSpecific' ) -> add( $PACMethod::CONTAINER );
_( $self, 'alignTermOpts' ) -> add( ( $$self{_TERMOPTS} = PACTermOpts -> new() ) -> {container} );
_( $self, 'alignVar' ) -> add( ( $$self{_VARIABLES} = PACVarEntry -> new() ) -> {container} );
_( $self, 'alignPreExec' ) -> add( ( $$self{_PRE_EXEC} = PACPrePostEntry -> new() ) -> {container} );
_( $self, 'alignPostExec' ) -> add( ( $$self{_POST_EXEC} = PACPrePostEntry -> new() ) -> {container} );
_( $self, 'alignMacros' ) -> add( ( $$self{_MACROS} = PACExecEntry -> new() ) -> {container} );
_( $self, 'alignLocal' ) -> add( ( $$self{_LOCAL_EXEC} = PACExecEntry -> new() ) -> {container} );
_( $self, 'alignExpect' ) -> add( ( $$self{_EXPECT_EXEC} = PACExpectEntry -> new() ) -> {container} );
_( $self, 'nbProps' ) -> show_all;
# Populate 'Method' combobox
my $i = 0;
foreach my $method ( sort { $a cmp $b } keys %{ $$self{_METHODS} } )
{
_( $self, 'comboMethod' ) -> append_text( $method );
$$self{_METHODS}{$method}{'position'} = $i++;
}
# Initialize main window
$$self{_WINDOWEDIT} -> set_default_icon_from_file( $APPICON );
$$self{_WINDOWEDIT} -> set_default_size( 500, 500 );
$$self{_WINDOWEDIT} -> set_position( 'center' );
return 1;
}
sub _setupCallbacks
{
my $self = shift;
# Avoid the enter of non numeric values in this entry
_( $self, 'entryPort' ) -> signal_connect( 'insert_text' => sub { $_[1] =~ s/[^\d]//go; return $_[1], $_[3]; } );
# Capture 'Method' changed
_( $self, 'comboMethod' ) -> signal_connect( changed => sub
{
&{ $$self{_METHODS}{ _( $self, 'comboMethod' ) -> get_active_text }{'updateGUI'} }();
$$self{_SPECIFIC} -> change( _( $self, 'comboMethod' ) -> get_active_text, $$self{_CFG}{'environments'}{ $$self{_ENVIRONMENT} }{ $$self{_CONNECTION} } );
$$self{_WINDOWEDIT} -> show_all;
} );
# Capture "Manual" connection checkbox
_( $self, 'cbConnManual' ) -> signal_connect( toggled => sub
{
_( $self, 'frameExpect' ) -> set_sensitive( ! _( $self, 'cbConnManual' ) -> get_active() );
_( $self, 'labelExpect' ) -> set_sensitive( ! _( $self, 'cbConnManual' ) -> get_active() );
_( $self, 'entryUser' ) -> set_sensitive( ! _( $self, 'cbConnManual' ) -> get_active() );
_( $self, 'entryPassword' ) -> set_sensitive( ! _( $self, 'cbConnManual' ) -> get_active() );
_( $self, 'cbConnShowPass' ) -> set_sensitive( ! _( $self, 'cbConnManual' ) -> get_active() );
} );
# Capture 'show password' checkbox toggled state
_( $self, 'cbConnShowPass' ) -> signal_connect( 'toggled' => sub
{
_( $self, 'entryPassword' ) -> set_visibility( _( $self, 'cbConnShowPass' ) -> get_active );
return 1;
} );
# Capture 'save' button clicked
_( $self, 'btnSaveEdit' ) -> signal_connect( 'clicked' => sub { $self -> _saveConfiguration; _( $self, 'btnCloseEdit' ) -> activate } );
# Capture 'close' button clicked
_( $self, 'btnCloseEdit' ) -> signal_connect( 'clicked' => sub { $$self{_WINDOWEDIT} -> hide; } );
# Capture window closing
$$self{_WINDOWEDIT} -> signal_connect( 'delete_event' => sub
{
$$self{_WINDOWEDIT} -> hide();
return 1;
} );
$$self{_WINDOWEDIT} -> signal_connect( 'key_press_event' => sub
{
my ( $widget, $event ) = @_;
# Capture 'Esc' keypress to close window
$event -> keyval == 65307 and $$self{_WINDOWEDIT} -> hide;
return 0;
} );
_( $self, 'nbProps' ) -> signal_connect( 'switch_page' => sub
{
$_[0] -> hide_all;
$_[0] -> show_all;
return 0;
} );
return 1;
}
sub _updateGUIPreferences
{
my $self = shift;
my $env = $$self{_ENVIRONMENT};
my $conn = $$self{_CONNECTION};
####################################
# Frame 'Connection' + 'Description'
####################################
my $lbl = "Use 'Preferences' Proxy for this connection:\n";
if ( $$self{_CFG}{'environments'}{$env}{$conn}{'use proxy'} // '0' )
{
if ( $$self{_CFG}{defaults}{'use system proxy'} // '0' )
{
$lbl .= " Gnome's SYSTEM proxy";
}
else
{
$lbl .= ' ' . $$self{_CFG}{defaults}{'proxy ip'} . ":" . $$self{_CFG}{defaults}{'proxy port'};
}
}
_( $self, 'cbConnForceUseProxy' ) -> set_label( $lbl );
_( $self, 'cbConnForceUseProxy' ) -> set_active( $$self{_CFG}{'environments'}{$env}{$conn}{'use proxy'} // '0' );
_( $self, 'cbConnManual' ) -> set_active( $$self{_CFG}{'environments'}{$env}{$conn}{'manual'} // '0' );
_( $self, 'cbConnManual' ) -> set_label( "Do NOT autologin nor check 'Expect'\n(Manual user/password login)" );
_( $self, 'entryIP' ) -> set_text( $$self{_CFG}{'environments'}{$env}{$conn}{'ip'} );
_( $self, 'entryPort' ) -> set_text( $$self{_CFG}{'environments'}{$env}{$conn}{'port'} );
_( $self, 'entryUser' ) -> set_text( $$self{_CFG}{'environments'}{$env}{$conn}{'user'} );
_( $self, 'entryPassword' ) -> set_text( $$self{_CFG}{'environments'}{$env}{$conn}{'pass'} );
_( $self, 'comboMethod' ) -> set_active( $$self{_METHODS}{ $$self{_CFG}{'environments'}{$env}{$conn}{'method'} }{'position'} // 4 );
_( $self, 'entryTabWindowTitle' ) -> set_text( $$self{_CFG}{'environments'}{$env}{$conn}{'title'} || "$env - $conn " );
&{ $$self{_METHODS}{ _( $self, 'comboMethod' ) -> get_active_text }{'updateGUI'} }( $$self{_CFG}{'environments'}{$env}{$conn}{'port'} );
##################
# TAB 'Options'
##################
$$self{_SPECIFIC} -> update( $$self{_CFG}{'environments'}{$env}{$conn} );
$$self{_TERMOPTS} -> update( $$self{_CFG}{'environments'}{$env}{$conn}{'terminal options'} );
$$self{_VARIABLES} -> update( $$self{_CFG}{'environments'}{$env}{$conn}{'variables'} );
$$self{_PRE_EXEC} -> update( $$self{_CFG}{'environments'}{$env}{$conn}{'local before'}, $$self{_CFG}{'environments'}{$env}{$conn}{'variables'} );
$$self{_POST_EXEC} -> update( $$self{_CFG}{'environments'}{$env}{$conn}{'local after'}, $$self{_CFG}{'environments'}{$env}{$conn}{'variables'} );
$$self{_MACROS} -> update( $$self{_CFG}{'environments'}{$env}{$conn}{'macros'}, $$self{_CFG}{'environments'}{$env}{$conn}{'variables'}, 'remote' );
$$self{_LOCAL_EXEC} -> update( $$self{_CFG}{'environments'}{$env}{$conn}{'local connected'}, $$self{_CFG}{'environments'}{$env}{$conn}{'variables'}, 'local' );
_( $self, 'frameExpect' ) -> set_sensitive( ! _( $self, 'cbConnManual' ) -> get_active() );
_( $self, 'labelExpect' ) -> set_sensitive( ! _( $self, 'cbConnManual' ) -> get_active() );
$$self{_EXPECT_EXEC} -> update( $$self{_CFG}{'environments'}{$env}{$conn}{'expect'}, $$self{_CFG}{'environments'}{$env}{$conn}{'variables'} );
#########################################################################
$$self{_WINDOWEDIT} -> show_all; # Without this line, $$self{_SPECIFIC} widgets WILL NOT BE SHOWN!!!!!!!!!
#########################################################################
return 1;
}
sub _saveConfiguration
{
my $self = shift;
my $env = $$self{_ENVIRONMENT};
my $conn = $$self{_CONNECTION};
##############################
# IP, Port, User, Pass, ...
##############################
$$self{_CFG}{'environments'}{$env}{$conn}{'use proxy'} = _( $self, 'cbConnForceUseProxy' ) -> get_active() || '0';
$$self{_CFG}{'environments'}{$env}{$conn}{'manual'} = _( $self, 'cbConnManual' ) -> get_active() || '0';
$$self{_CFG}{'environments'}{$env}{$conn}{'ip'} = _( $self, 'entryIP' ) -> get_chars( 0, -1 );
$$self{_CFG}{'environments'}{$env}{$conn}{'port'} = _( $self, 'entryPort' ) -> get_chars( 0, -1 );
$$self{_CFG}{'environments'}{$env}{$conn}{'user'} = _( $self, 'entryUser' ) -> get_chars( 0, -1 );
$$self{_CFG}{'environments'}{$env}{$conn}{'pass'} = _( $self, 'entryPassword' ) -> get_chars( 0, -1 );
$$self{_CFG}{'environments'}{$env}{$conn}{'method'} = _( $self, 'comboMethod' ) -> get_active_text();
$$self{_CFG}{'environments'}{$env}{$conn}{'title'} = _( $self, 'entryTabWindowTitle' ) -> get_chars( 0, -1 ) || "$env - $conn ";
##################
# Other options...
##################
$$self{_CFG}{'environments'}{$env}{$conn}{'options'} = $$self{_SPECIFIC} -> get_cfg;
$$self{_CFG}{'environments'}{$env}{$conn}{'terminal options'} = $$self{_TERMOPTS} -> get_cfg;
$$self{_CFG}{'environments'}{$env}{$conn}{'variables'} = $$self{_VARIABLES} -> get_cfg;
$$self{_CFG}{'environments'}{$env}{$conn}{'local before'} = $$self{_PRE_EXEC} -> get_cfg;
$$self{_CFG}{'environments'}{$env}{$conn}{'local after'} = $$self{_POST_EXEC} -> get_cfg;
$$self{_CFG}{'environments'}{$env}{$conn}{'expect'} = $$self{_EXPECT_EXEC} -> get_cfg;
$$self{_CFG}{'environments'}{$env}{$conn}{'macros'} = $$self{_MACROS} -> get_cfg;
$$self{_CFG}{'environments'}{$env}{$conn}{'local connected'} = $$self{_LOCAL_EXEC} -> get_cfg;
$$self{_CFG}{'tmp'}{'changed'} = 1;
# Send a signal to every started terminal for this $env - $conn to realize the new CFG
foreach my $uuid ( keys %PACMain::RUNNING )
{
next unless ( ( $PACMain::RUNNING{$uuid}{'environment'} eq $env ) && ( $PACMain::RUNNING{$uuid}{'connection'} eq $conn ) );
$PACMain::RUNNING{$uuid}{'terminal'} -> _updateCFG;
}
my $i = -1;
foreach my $data ( @{ $PACMain::FUNCS{_MAIN}{_GUI}{treeConnections} -> {data} } )
{
++$i;
next unless $$data[1] eq $conn;
$PACMain::FUNCS{_MAIN}{_GUI}{treeConnections} -> {data}[$i][0] = $$self{_METHODS}{ $$self{_CFG}{'environments'}{$env}{$conn}{'method'} }{'icon'};
}
return 1;
}
# END: Define PRIVATE CLASS functions
###################################################################
1;