|
这个例子说明了如何将Glade界面直接放在程序中方便在邮件列表和论坛上直接发布程序,以及如何用Gtk2::Helper调用网络程序防止连接超时导致界面阻塞。程序中 用Expect实现了VNC密码输入。
- #! /usr/bin/perl -w
- #----------------------------------------------------------------------
- # gtkremote.pl
- #
- # A remote desktop frontend of Gtk2/GladeXML
- #
- # Copyright (C) 2008 Viperii (hominid@tom.com)
- #
- # This library is free software; you can redistribute it and/or
- # modify it under the terms of the GNU Lesser General Public
- # License as published by the Free Software Foundation; either
- # version 2 of the License, or (at your option) any later version.
- #
- # This library 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
- # Lesser General Public License for more details.
- #
- # You should have received a copy of the GNU Lesser General Public
- # License along with this library; if not, write to the
- # Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- # Boston, MA 02111-1307, USA.
- #
- #----------------------------------------------------------------------
- use strict;
- use warnings;
- use Glib qw/TRUE FALSE/;
- use Gtk2 '-init';
- use Gtk2::Helper;
- use Gtk2::GladeXML;
- use FindBin qw($Bin);
- use Expect;
- my $CMD;
- my $PID;
- my $TAG;
- my $CONN = 0;
- my $PREFIX = '@PREFIX@';
- my $BIN_DIR = (-d $PREFIX ? "$PREFIX/bin" : $Bin);
- my $VNC_TMP = "/tmp/vncpasswd.tmp";
- $| = 1;
- my $glade_data; {local $/ = undef; $glade_data = ;}
- my $gladexml = Gtk2::GladeXML->new_from_buffer($glade_data);
- #my $gladexml = Gtk2::GladeXML->new($BIN_DIR.'/gtkremote.glade');
- $gladexml->signal_autoconnect_from_package('main');
- my $window = $gladexml->get_widget('main');
- my $host_entry = $gladexml->get_widget('entry1');
- my $port_entry = $gladexml->get_widget('entry2');
- my $user_entry = $gladexml->get_widget('entry3');
- my $pass_entry = $gladexml->get_widget('entry4');
- my $combobox = $gladexml->get_widget('combobox1');
- my $button = $gladexml->get_widget('button1');
- my $status_icon = $gladexml->get_widget('image2');
- my @prot_list = ("VNC", "RDP");
- $combobox->append_text($_) foreach (@prot_list);
- $combobox->set_active(0);
- $window->show_all();
- Gtk2->main();
- $window->destroy;
- exit 0;
- sub on_main_delete_event
- {
- kill 15 => $PID if $PID;
- unlink $VNC_TMP if -f $VNC_TMP;
- Gtk2->main_quit;
- exit;
- }
- sub on_combobox1_changed
- {
- $combobox->get_active_text eq "VNC" ? $user_entry->set_sensitive(FALSE) : $user_entry->set_sensitive(TRUE);
- }
- sub on_button1_clicked
- {
- unless($CONN)
- {
- remote_connect();
- }
- else
- {
- kill 15 => $PID if $PID;
- }
- }
- sub status_connect
- {
- $CONN = 1;
- $button->child->set_text("Disconnect");
- $status_icon->set_from_stock('gtk-connect', 'large-toolbar');
- }
- sub status_disconnect
- {
- $CONN = 0;
- $button->child->set_text("Connect");
- $status_icon->set_from_stock('gtk-disconnect', 'large-toolbar');
- }
- sub message_dialog_show
- {
- #$icon can be: a) 'info'
- # b) 'warning'
- # c) 'error'
- # d) 'question'
- #$button_type can be: a) 'none'
- # b) 'ok'
- # c) 'close'
- # d) 'cancel'
- # e) 'yes-no'
- # f) 'ok-cancel'
- my ($parent,$icon,$text,$button_type) = @_;
- my $dialog = Gtk2::MessageDialog->new_with_markup ($parent,
- [qw/modal destroy-with-parent/],
- $icon,
- $button_type,
- sprintf "$text");
- my $retval = $dialog->run;
- $dialog->destroy;
- return $retval;
- }
- sub remote_connect
- {
- status_connect();
- my $host = $host_entry->get_text;
- my $port = $port_entry->get_text;
- my $user = $user_entry->get_text;
- my $pass = $pass_entry->get_text;
- my $prot = $combobox->get_active_text;
- if($host)
- {
- if($prot eq "VNC")
- {
- unlink $VNC_TMP if -f $VNC_TMP;
- $CMD = "vncviewer $host";
- $CMD .= "::$port" if $port =~ /^(\d+)$/;
- if(length($pass) >= 6)
- {
- my $sh = Expect->spawn('/bin/sh') or die "Cannot spawn shell: $!\n";
- my $exp = new Expect;
- my $command = "vncpasswd $VNC_TMP";
- $exp->spawn($command) or die "Cannot spawn $command: $!\n";
- $exp->expect(10, 'Password:');
- $exp->send("$pass\n");
- $exp->expect(10, 'Verify:');
- $exp->send("$pass\n");
- $exp->interact();
- $exp->soft_close();
- $sh->hard_close();
- $CMD .= " -passwd $VNC_TMP";
- }
- else
- {
- message_dialog_show($window,
- 'error',
- 'VNC password too short.',
- 'ok'
- );
- status_disconnect();
- return;
- }
- }
- elsif($prot eq "RDP")
- {
- $CMD = "rdesktop $host";
- $CMD .= ":$port" if $port =~ /^(\d+)$/;
- $CMD .= " -u $user" if $user;
- $CMD .= " -p $pass" if $pass;
- }
- else
- {
- status_disconnect();
- return;
- }
- }
- else
- {
- status_disconnect();
- return;
- }
- $PID = open my $pipe, '-|', "$CMD" or die "Failed open pipe: $CMD\n";
- $TAG = Gtk2::Helper->add_watch(fileno($pipe), in => sub
- {
- if(eof($pipe))
- {
- Gtk2::Helper->remove_watch($TAG);
- close($pipe);
- unlink $VNC_TMP if -f $VNC_TMP;
- status_disconnect();
- 0;
- }
- else
- {
- #my $line = ; # stdout string.
- #print "OUTPUT: ".$line."\n" if $line;
- }
- 1;
- } );
- }
- __DATA__
-
- True
- GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK
- GTK_WIN_POS_CENTER
- GDK_WINDOW_TYPE_HINT_DIALOG
-
-
-
- True
- GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK
-
-
- True
- GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK
-
-
- 71
- 63
- True
- GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK
- gtk-network
- 6
-
-
- 53
-
-
-
-
-
-
- True
- GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK
-
-
- True
- GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK
-
-
- 39
- 22
- True
- GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK
- Host:
-
-
- 1
- 10
-
-
-
-
- 125
- 25
- True
- True
- GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK
-
-
- 78
- 10
-
-
-
-
- 34
- 23
- True
- GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK
- Port:
-
-
- 205
- 10
-
-
-
-
- 50
- 25
- True
- True
- GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK
- 5
-
-
- 240
- 10
-
-
-
-
-
-
- True
- GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK
-
-
- 61
- 22
- True
- GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK
- Protocol:
-
-
- 7
-
-
-
-
- 86
- 27
- True
- GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK
-
-
-
-
- 79
- 6
-
-
-
-
- 1
-
-
-
-
- True
- GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK
-
-
- 76
- 22
- True
- GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK
- Username:
-
-
- 8
-
-
-
-
- 115
- 25
- True
- True
- GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK
- 128
-
-
- 79
- 6
-
-
-
-
- 71
- 21
- True
- GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK
- Password:
-
-
- 36
-
-
-
-
- 115
- 25
- True
- True
- GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK
- 128
- False
-
-
- 79
- 34
-
-
-
-
- 2
-
-
-
-
- True
- GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK
-
-
- True
- True
- True
- GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK
- Connect
- 0
-
-
-
- 77
- 10
-
-
-
-
- 32
- 32
- True
- GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK
- gtk-disconnect
- 3
-
-
- 3
- 7
-
-
-
-
- 295
- 10
- True
- GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK
-
-
- 4
- 43
-
-
-
-
- 3
-
-
-
-
- 1
-
-
-
-
-
|
|
|