App-ClusterSSH
view release on metacpan or search on metacpan
lib/App/ClusterSSH.pm view on Meta::CPAN
if ( $self->config->{internal_total} == 0
&& $self->config->{auto_quit} =~ /yes/i )
{
# and some clients were actually opened...
if ( $self->config->{internal_activate_autoquit} ) {
$self->debug( 2, "Autoquitting" );
$self->exit_prog;
}
}
# rebuild host menu if something has changed
$self->build_hosts_menu() if ($build_menu);
# clean out text area, anyhow
$menus{entrytext} = "";
#$self->debug( 3, "repeat completed" );
}
);
$self->debug( 2, "Repeat setup" );
return $self;
}
### Window and menu definitions ###
sub create_windows() {
my ($self) = @_;
$self->debug( 2, "create_windows: started" );
$windows{main_window}
= MainWindow->new( -title => "ClusterSSH", -class => 'cssh', );
$windows{main_window}->withdraw; # leave withdrawn until needed
if ( defined( $self->config->{console_position} )
&& $self->config->{console_position} =~ /[+-]\d+[+-]\d+/ )
{
$windows{main_window}->geometry( $self->config->{console_position} );
}
$menus{entrytext} = "";
$windows{text_entry} = $windows{main_window}->Entry(
-textvariable => \$menus{entrytext},
-insertborderwidth => 4,
-width => 25,
-class => 'cssh',
)->pack(
-fill => "x",
-expand => 1,
);
$windows{history} = $windows{main_window}->Scrolled(
"ROText",
-insertborderwidth => 4,
-width => $self->config->{history_width},
-height => $self->config->{history_height},
-state => 'normal',
-takefocus => 0,
-class => 'cssh',
);
$windows{history}->bindtags(undef);
if ( $self->config->{show_history} ) {
$windows{history}->pack(
-fill => "x",
-expand => 1,
);
}
$windows{main_window}->bind( '<Destroy>' => sub { $self->exit_prog } );
# remove all Paste events so we set them up cleanly
$windows{main_window}->eventDelete('<<Paste>>');
# Set up paste events from scratch
if ( $self->config->{key_paste} && $self->config->{key_paste} ne "null" )
{
$windows{main_window}->eventAdd(
'<<Paste>>' => '<' . $self->config->{key_paste} . '>' );
}
if ( $self->config->{mouse_paste}
&& $self->config->{mouse_paste} ne "null" )
{
$windows{main_window}->eventAdd(
'<<Paste>>' => '<' . $self->config->{mouse_paste} . '>' );
}
$windows{main_window}->bind(
'<<Paste>>' => sub {
$self->debug( 2, "PASTE EVENT" );
$menus{entrytext} = "";
my $paste_text = '';
# SelectionGet is fatal if no selection is given
Tk::catch {
$paste_text = $windows{main_window}->SelectionGet;
};
if ( !length($paste_text) ) {
warn("Got empty paste event\n");
return;
}
$self->debug( 2, "Got text :", $paste_text, ":" );
$self->update_display_text($paste_text);
# now sent it on
foreach my $svr ( keys(%servers) ) {
$self->send_text( $svr, $paste_text )
if ( $servers{$svr}{active} == 1 );
}
}
);
$windows{help} = $windows{main_window}->Dialog(
-popover => $windows{main_window},
-overanchor => "c",
-popanchor => "c",
-class => 'cssh',
-font => [
-family => "interface system",
-size => 10,
],
-text =>
"Cluster Administrator Console using SSH\n\nVersion: $VERSION.\n\n"
. "Bug/Suggestions to http://clusterssh.sf.net/",
);
$windows{manpage} = $windows{main_window}->DialogBox(
-popanchor => "c",
-overanchor => "c",
-title => "Cssh Documentation",
-buttons => ['Close'],
-class => 'cssh',
);
my $manpage = `pod2text -l -q=\"\" $0 2>/dev/null`;
if ( !$manpage ) {
$manpage
= "Help is missing.\nSee that command 'pod2text' is installed and in PATH.";
}
$windows{mantext}
= $windows{manpage}->Scrolled( "Text", )->pack( -fill => 'both' );
$windows{mantext}->insert( 'end', $manpage );
$windows{mantext}->configure( -state => 'disabled' );
lib/App/ClusterSSH.pm view on Meta::CPAN
-title => "Add Host(s) or Cluster(s)",
-buttons => [ 'Add', 'Cancel' ],
-default_button => 'Add',
-class => 'cssh',
);
my @tags = $self->cluster->list_tags();
my @external_tags = map {"$_ *"} $self->cluster->list_external_clusters();
push( @tags, @external_tags );
if ( $self->config->{max_addhost_menu_cluster_items}
&& scalar @tags )
{
if ( scalar @tags < $self->config->{max_addhost_menu_cluster_items} )
{
$menus{listbox} = $windows{addhost}->Listbox(
-selectmode => 'extended',
-height => scalar @tags,
-class => 'cssh',
)->pack();
}
else {
$menus{listbox} = $windows{addhost}->Scrolled(
'Listbox',
-scrollbars => 'e',
-selectmode => 'extended',
-height => $self->config->{max_addhost_menu_cluster_items},
-class => 'cssh',
)->pack();
}
$menus{listbox}->insert( 'end', sort @tags );
if (@external_tags) {
$menus{addhost_text} = $windows{addhost}->add(
'Label',
-class => 'cssh',
-text => '* is external',
)->pack();
#$menus{addhost_text}->insert('end','lkjh lkjj sdfl jklsj dflj ');
}
}
$windows{host_entry} = $windows{addhost}->add(
'LabEntry',
-textvariable => \$menus{host_entry},
-width => 20,
-label => 'Host',
-labelPack => [ -side => 'left', ],
-class => 'cssh',
)->pack( -side => 'left' );
$self->debug( 2, "create_windows: completed" );
return $self;
}
sub capture_map_events() {
my ($self) = @_;
# pick up on console minimise/maximise events so we can do all windows
$windows{main_window}->bind(
'<Map>' => sub {
$self->debug( 3, "Entering MAP" );
my $state = $windows{main_window}->state();
$self->debug(
3,
"state=$state previous=",
$self->config->{internal_previous_state}
);
$self->debug( 3, "Entering MAP" );
if ( $self->config->{internal_previous_state} eq $state ) {
$self->debug( 3, "repeating the same" );
}
if ( $self->config->{internal_previous_state} eq "mid-change" ) {
$self->debug( 3, "dropping out as mid-change" );
return;
}
$self->debug(
3,
"state=$state previous=",
$self->config->{internal_previous_state}
);
if ( $self->config->{internal_previous_state} eq "iconic" ) {
$self->debug( 3, "running retile" );
$self->retile_hosts();
$self->debug( 3, "done with retile" );
}
if ( $self->config->{internal_previous_state} ne $state ) {
$self->debug( 3, "resetting prev_state" );
$self->config->{internal_previous_state} = $state;
}
}
);
# $windows{main_window}->bind(
# '<Unmap>' => sub {
# $self->debug( 3, "Entering UNMAP" );
#
# my $state = $windows{main_window}->state();
# $self->debug( 3,
# "state=$state previous=$config{internal_previous_state}" );
#
# if ( $config{internal_previous_state} eq $state ) {
# $self->debug( 3, "repeating the same" );
# }
#
# if ( $config{internal_previous_state} eq "mid-change" ) {
# $self->debug( 3, "dropping out as mid-change" );
# return;
# }
#
# if ( $config{internal_previous_state} eq "normal" ) {
# $self->debug( 3, "withdrawing all windows" );
# foreach my $server ( reverse( keys(%servers) ) ) {
# $xdisplay->req( 'UnmapWindow', $servers{$server}{wid} );
# if ( $config{unmap_on_redraw} =~ /yes/i ) {
# $xdisplay->req( 'UnmapWindow',
# $servers{$server}{wid} );
# }
# }
# $xdisplay->flush();
# }
#
# if ( $config{internal_previous_state} ne $state ) {
# $self->debug( 3, "resetting prev_state" );
# $config{internal_previous_state} = $state;
# }
# }
# );
return $self;
}
# for all key event, event hotkeys so there is only 1 key binding
sub key_event {
my ($self) = @_;
my $event = $Tk::event->T;
my $keycode = $Tk::event->k;
my $keysymdec = $Tk::event->N;
my $keysym = $Tk::event->K;
my $state = $Tk::event->s || 0;
$menus{entrytext} = "";
$self->debug( 3, "=========" );
$self->debug( 3, "event =$event" );
$self->debug( 3, "keysym =$keysym (state=$state)" );
$self->debug( 3, "keysymdec=$keysymdec" );
$self->debug( 3, "keycode =$keycode" );
$self->debug( 3, "state =$state" );
$self->debug( 3, "codetosym=$keycodetosym{$keysymdec}" )
if ( $keycodetosym{$keysymdec} );
$self->debug( 3, "symtocode=$keysymtocode{$keysym}" );
$self->debug( 3, "keyboard =$keyboardmap{ $keysym }" )
if ( $keyboardmap{$keysym} );
#warn("debug stop point here");
if ( $self->config->{use_hotkeys} eq "yes" ) {
my $combo = $Tk::event->s . $Tk::event->K;
$combo =~ s/Mod\d-//;
$self->debug( 3, "combo=$combo" );
foreach my $hotkey ( grep( /key_/, keys( %{ $self->config } ) ) ) {
my $key = $self->config->{$hotkey};
next if ( $key eq "null" ); # ignore disabled keys
$self->debug( 3, "key=:$key:" );
if ( $combo =~ /^$key$/ ) {
$self->debug( 3, "matched combo" );
if ( $event eq "KeyRelease" ) {
$self->debug( 2, "Received hotkey: $hotkey" );
$self->send_text_to_all_servers(
$self->config->{macro_servername} )
if ( $hotkey eq "key_clientname" );
$self->send_text_to_all_servers(
$self->config->{macro_hostname} )
if ( $hotkey eq "key_localname" );
$self->send_text_to_all_servers(
$self->config->{macro_username} )
if ( $hotkey eq "key_username" );
$self->add_host_by_name()
if ( $hotkey eq "key_addhost" );
$self->retile_hosts("force")
if ( $hotkey eq "key_retilehosts" );
$self->show_history() if ( $hotkey eq "key_history" );
$self->exit_prog() if ( $hotkey eq "key_quit" );
}
return;
}
}
}
lib/App/ClusterSSH.pm view on Meta::CPAN
-command => sub { $self->retile_hosts },
-accelerator => $self->config->{key_retilehosts},
],
# [ "command", "Capture Terminal", -command => sub { $self->capture_terminal), ],
[ "command",
"Set all active",
-command => sub { $self->set_all_active() },
],
[ "command",
"Set half inactive",
-command => sub { $self->set_half_inactive() },
],
[ "command",
"Toggle active state",
-command => sub { $self->toggle_active_state() },
],
[ "command",
"Close inactive sessions",
-command => sub { $self->close_inactive_sessions() },
],
[ "command",
"Add Host(s) or Cluster(s)",
-command => sub { $self->add_host_by_name, },
-accelerator => $self->config->{key_addhost},
],
[ "command",
"Re-add closed session(s)",
-command => sub { $self->re_add_closed_sessions() },
],
'' # this is needed as build_host_menu always drops the
# last item
];
$menus{hosts} = $menus{bar}->cascade(
-label => 'Hosts',
-tearoff => 1,
-menuitems => $host_menu_items
);
$host_menu_static_items = scalar( @{$host_menu_items} );
$menus{send} = $menus{bar}->cascade(
-label => 'Send',
-tearoff => 1,
);
$self->populate_send_menu();
$menus{help} = $menus{bar}->cascade(
-label => 'Help',
-menuitems => [
[ 'command', "About", -command => sub { $windows{help}->Show } ],
[ 'command', "Documentation",
-command => sub { $windows{manpage}->Show }
],
],
-tearoff => 0,
);
$windows{main_window}->bind( '<KeyPress>' => [ $self => 'key_event' ], );
$windows{main_window}
->bind( '<KeyRelease>' => [ $self => 'key_event' ], );
$self->debug( 2, "create_menubar: completed" );
}
sub populate_send_menu_entries_from_xml {
my ( $self, $menu, $menu_xml ) = @_;
foreach my $menu_ref ( @{ $menu_xml->{menu} } ) {
if ( $menu_ref->{menu} ) {
$menus{ $menu_ref->{title} }
= $menu->cascade( -label => $menu_ref->{title}, );
$self->populate_send_menu_entries_from_xml(
$menus{ $menu_ref->{title} }, $menu_ref, );
if ( $menu_ref->{detach} && $menu_ref->{detach} =~ m/y/i ) {
$menus{ $menu_ref->{title} }->menu->tearOffMenu()->raise;
}
}
else {
my $accelerator = undef;
if ( $menu_ref->{accelerator} ) {
$accelerator = $menu_ref->{accelerator};
}
if ( $menu_ref->{toggle} ) {
$menus{send}->checkbutton(
-label => 'Use Macros',
-variable => \$self->config->{macros_enabled},
-offvalue => 'no',
-onvalue => 'yes',
-accelerator => $accelerator,
);
}
else {
my $command = undef;
if ( $menu_ref->{command} ) {
$command = sub {
$self->send_text_to_all_servers(
$menu_ref->{command}[0] );
};
}
$menu->command(
-label => $menu_ref->{title},
-command => $command,
-accelerator => $accelerator,
);
}
}
}
return $self;
}
sub populate_send_menu {
my ($self) = @_;
# my @menu_items = ();
if ( !-r $self->config->{send_menu_xml_file} ) {
$self->debug( 2, 'Using default send menu' );
$menus{send}->checkbutton(
-label => 'Use Macros',
-variable => \$self->config->{macros_enabled},
( run in 2.514 seconds using v1.01-cache-2.11-cpan-2398b32b56e )