GTK2-Perl程序示例:远程桌面客户端gtkremote-HVH
这个例子说明了如何将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,
[*] ,
[*] $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
[*]
[*]
[*]
[*]
[*]
[*]
页:
[1]