TIP Recomendación para amule daemon: aMulet.pl
De Gentoo Linux Wiki
| Terminales / Shells • X Windows • Portage • Sistema • Sistema de Archivos • Kernel • Otros |
[editar] aMulet.pl
Bueno, aquí van una líneas de código que desarrolle en el foro del proyecto aMule, que puede ayudar a quien le gusten estas cosas de de la creación.Creo que dejé él código muy claro, para que pueda ser lo más claro e instructivo posible.
Este es un script en perl que utiliza Gtk2. Su misión es la que recomendó tx2z en los foros de aMule que pedía tener el icono en la barra de sistema, como si del aMule en sí se tratase. Concretamente en este thread.
Esto es lo que hace esté script, también muestra la lista de log y lanza otros procesos que forman parte del amuled como el aLinkCreator o el wxCas
Creo que el código habla por sí sólo, si hay alguna duda, la zona de discusión está abierta para solucionarlas. AnimAlf 17:28 6 oct 2006 (UTC)
| Código: aMulet.pl |
#!/usr/bin/perl -w
#
# file aMulet.pl
# Copyright by AnimAlf
#
# This lines are under the GNU General Public License.
# http://www.gnu.org/copyleft/gpl.html
#
# aMulet - la t final en catalán le indica diminutivo
# También se traduce como amuleto
use strict;
my $binaMuled = 'amuled -f';
my $apppid = "$ENV{HOME}/.tx2z.pid";
my $logMode = "warning"; # debug warning msg
my $verbose = 1; # true false
if (!defined($ENV{'DISPLAY'})){
print &appRel . "\nATENCIÓN: Este script necesita ser ejecutado bajo las X Window\n";
exit -1;
}
eval "use Gtk2::TrayIcon;";
if ($@) {
print &appRel;
print "\n\nATENCIÓN: Este script necesita el módulo Gtk2::TrayIcon\n\n";
print "Puede instalarlo a través de CPAN del siguiente modo:\n\n";
print "\t\tperl -MCPAN -e shell\n";
print "\t\tinstall Gtk2::TrayIcon\n\n";
print "bye\n";
exit -1;
}
my $modUniCode;
eval "use Unicode::MapUTF8 qw(from_utf8);";
$modUniCode = !$@;
my $config = {};
my @appList = ( 'aMuleGui', 'wxCas', 'aLinkCreator');
# Los procesos hijo envían esta señal al padre cuando terminan y ésta
# debe ser atendida, si no se quedan zombies hasta que termine el padre.
$SIG{CHLD} = \&finalHijo;
# Si se recibe cualquier señal que pueda provocar la interrupción del
# normal funcionamiento, entonces nos encargamos de finalizar correctamente.
$SIG{TERM} = $SIG{QUIT} = $SIG{HUP} = $SIG{INT} = \&finalizar;
# Iniciando Gtk2
Gtk2->init;
# Comprobaciones iniciales. Cargar configuración.
if (!&inicializar){
logsys ("msg", &appRel ." ha abortado el arranque.");
unlink $apppid or die "No puedo eliminar el archivo de bloqueo";
exit -1;
}
logsys ("msg", &appRel ." iniciado");
# Formas Gtk2
my $menu = Gtk2::Menu->new();
my $menu_opciones = Gtk2::MenuItem->new("opciones");
my $menu_aLinkCreator = Gtk2::MenuItem->new("aLinkCreator");
my $menu_wxCas = Gtk2::MenuItem->new("wxCas");
my $menu_aMuleGui = Gtk2::MenuItem->new("aMuleGui");
my $menu_verLog = Gtk2::MenuItem->new("aMule log");
my $menuSalir = Gtk2::MenuItem->new("Salir");
my $pic;
eval {$pic = Gtk2::Gdk::Pixbuf->new_from_file ($config->{'iconPath'});};
if ($@){
my @aMulet_xpm = ('18 24 17 1', ' c None', '. c #312A28', '+ c #524842',
'@ c #D42238', '# c #835128', '$ c #985A20', '% c #6A6B6A',
'& c #AA7B50', '* c #EC5867', '= c #BF7B3F', '- c #C9792F',
'; c #898989', '> c #E39854', ', c #CB9D83', '" c #A9AAAA',
') c #CDCBC9', '! c #F4F5F3', ' ',
' $ ',
' !> ',
' #! )$$ ',
' ## #-$ ',
' )##$ -,# ',
' .+##)$,) ',
' ...$,!" ',
' ".$=-$" ',
' ;==-!= ',
' " >! " ',
' ; !& ; ',
' " !)))" ',
' """"""! ',
' %!.""""); ',
' ;))";;;"%;;) ',
' ">-)";;;;"->"" ',
' )-=$,;;%@,->$) ',
' ;%--#=>>**+%%; ',
' +....&=>>>>#!))! ',
'%"-=##$>>>>=&$--;;',
'+)-=##&=>>>=#=->)+',
'%;;=$+.+>>++$->,;%', ' " . ');
$pic = Gtk2::Gdk::Pixbuf->new_from_xpm_data (@aMulet_xpm);
logsys ("warning", "Error al cargar el icono: " . $config->{'iconPath'});
logsys ("msg", "Se procede a cargar el icono interno.");
}
my $img= Gtk2::Image->new_from_pixbuf($pic->scale_simple(18, 24, "tiles"));
my $tray= Gtk2::TrayIcon->new("trayicon");
my $paraEvent = Gtk2::EventBox->new;
my $trayTooltip = Gtk2::Tooltips->new;
my $SeparadorMenu1 = Gtk2::SeparatorMenuItem->new;
my $SeparadorMenu2 = Gtk2::SeparatorMenuItem->new;
my $SeparadorMenu3 = Gtk2::SeparatorMenuItem->new;
$menu->append($menu_verLog);
$menu->append($SeparadorMenu1);
$menu->append($menu_opciones);
$menu->append($SeparadorMenu2);
$menu->append($menu_aLinkCreator);
$menu->append($menu_wxCas);
$menu->append($menu_aMuleGui);
$menu->append($SeparadorMenu3);
$menu->append($menuSalir);
$paraEvent->add($img);
$tray->add($paraEvent);
&statusText;
# Tratamiento de señales
logsys ("debug", "Asignación de señales");
$tray->signal_connect ('button-press-event' => \&ClickOnIcon);
$menu_opciones->signal_connect('activate' => \&opcionesGui);
$menu_verLog->signal_connect('activate' => \&visorTexto);
$menu_aLinkCreator->signal_connect('activate' => sub {&extAppStatus('aLinkCreator')});
$menu_wxCas->signal_connect('activate' => sub {&extAppStatus('wxCas')});
$menu_aMuleGui->signal_connect('activate' => sub {&extAppStatus('aMuleGui')});
$menuSalir->signal_connect('activate' => \&finalizar);
Glib::Timeout->add($config->{'signOnTime'}*1000, \&statusText) if $config->{'signOn'};
# show sobre los witgets para que sean visibles
logsys ("debug", "Show sobre los witgets");
$menu->show_all;
$tray->show_all;
&popUpsAct;
# iniciando bucle de mensajes
logsys ("debug", "Inicio del bucle de mensajes");
Gtk2->main;
# Fin. Aquí termina el flujo.
#############
# Funciones #
#############
# statusText Establece el texto del toolTip
sub statusText{
my $tmpStr = &appRel ." - Click derecho para opciones";
if ($config->{'signOn'}){
&onlineInfo;
# my $tmpStr;
if ($config->{'ConectStatus'}){
if ($config->{'typeId'}eq"H"){$tmpStr = "[ID alta]"}
elsif ($config->{'typeId'}eq"L"){$tmpStr = "[ID baja]"}
else {$tmpStr = "[Conectando]"}
$tmpStr .= " Down:" . $config->{'downSpeed'};
$tmpStr .= " kb/s Up:" . $config->{'upSpeed'} ." Kb/s ";
if ($config->{'kadStatus'}==2) {$tmpStr .= "[kad ok]";
} elsif ($config->{'kadStatus'}==1) {$tmpStr .= "[kad firewalled]";
} else {$tmpStr .= "[kad off]"};
} else {$tmpStr = &appRel . " [aMuled No Conectado]"}
}
$trayTooltip->set_tip($tray, $tmpStr);
$tray->send_message($config->{'signOnTime'}*1000, "[AnimAlf dice] No entiendo");
}
# signatureOn Comprueba OnlineSignature en amule.conf
sub readSignatureConf {
$config->{'signOn'} = 0;
$config->{'signOnTime'} = 0;
if (-f $config->{'aMuleDir'} . "/amule.conf"){
if ( open( CONFIGFILE, $config->{'aMuleDir'} . "/amule.conf" ) ) {
while (<CONFIGFILE>) {
if ( $_ =~ /^OnlineSignature=(.+)/ ) { $config->{'signOn'} = $1 }
if ( $_ =~ /^OnlineSignatureUpdate=(.+)/ ) { $config->{'signOnTime'} = $1 }
}
close CONFIGFILE;
}
}
}
# onlineInfo Recoge la información de amulesig.dat
sub onlineInfo {
if ( open( SIGNFILE, $config->{'aMuleDir'} . "/amulesig.dat" ) ) {
my @signFile;
while (<SIGNFILE>) {
$_ =~ /(.+)\n$/; push (@signFile, $1)
}
close SIGNFILE;
$config->{'ConectStatus'} = $signFile[0];
$config->{'nameServ'} = $signFile[1];
$config->{'ipServ'} = $signFile[2];
$config->{'portServ'} = $signFile[3];
$config->{'typeId'} = $signFile[4];
$config->{'kadStatus'} = $signFile[5];
$config->{'downSpeed'} = $signFile[6];
$config->{'upSpeed'} = $signFile[7];
$config->{'colaCli'} = $signFile[8];
$config->{'filesShared'} = $signFile[9];
$config->{'nickName'} = $signFile[10];
$config->{'totalDown'} = $signFile[11];
$config->{'totalUp'} = $signFile[12];
$config->{'aMuleVer'} = $signFile[13];
$config->{'SessionDown'} = $signFile[14];
$config->{'SessionUp'} = $signFile[15];
$config->{'TimeRun'} = $signFile[16];
}
}
# finalHijo atender la señal de los hijos (cuando terminan la mandan)
sub finalHijo {
$SIG{CHLD} = \&finalHijo;
my $pid = wait;
return unless $config->{$pid}; # El system() realiza un fork() también.
logsys ("msg", "Acaba de finalizar: " . $config->{$pid} .
" [" . $config->{$config->{$pid} . 'Pid'} . "]");
undef $config->{$config->{$pid} . 'Pid'};
undef $config->{$pid};
}
# finalizar correctamente y eliminar bloqueo
sub finalizar {
$SIG{TERM} = $SIG{QUIT} = $SIG{HUP} = $SIG{INT} = \&finalizar;
logsys ("msg", "Finalizando ...");
#Finalizar el bucle de mensajes
Gtk2->main_quit;
#Comprobar que no quede ninguna aplicación hijo en funcionamiento
#y si existe eliminarlas antes de finalizar no vayan a quedar zombies.
logsys ("msg", "Finalizando posibles hijos");
# Ahora la señal de retorno del hijo la trataremos aquí.
$SIG{CHLD} = 'DEFAULT';
foreach my $app (@appList) {
if (defined $config->{$app . "Pid"}){
logsys ("msg", "[$app] está en marcha. Finalizándolo ...");
kill ('SIGTERM', $config->{$app . "Pid"});
waitpid($config->{$app . "Pid"}, 0);
}
}
logsys ("msg", "No quedan procesos hijo de " . &appRel . " en el sistema");
#TODO Si archivo de bloqueo es usado para log volcar a otro sitio.
logsys ("warning", "TODO: volcar archivo log a log final [si se le ordena]");
logsys ("msg", "Terminada la ejecución");
logsys ("msg", "bye ;-)\n\n".&appRel."\n");
# borrar archivo de bloqueo
unlink $apppid or die "No puedo eliminar el archivo de bloqueo $apppid";
}
# flushChars transforma utf8 a iso-8859-1
sub flushChars {
my ($tmpStr) = @_;
$tmpStr =~ s/([\200-\377]+)/from_utf8({ -string => $1, -charset => 'ISO-8859-1'})/eg
if $modUniCode;
return $tmpStr;
}
#logsys Mini sistema de logs.
sub logsys {
my ($mode, $text) = @_;
my $tmpStr;
if (open LOG, ">>$apppid") {
if (($logMode eq "debug" && ($mode eq "debug" or $mode eq "warning")) ||
($logMode eq "warning" && ($mode eq "warning" or $mode eq "msg")) ||
($logMode eq "msg" && $mode eq "msg")){
my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime (time);
$year += 1900; $mon ++;
$tmpStr="[" . uc($mode) . "] " . sprintf("%02d",$mday) . "-" .
sprintf("%02d",$mon) . "-$year " . sprintf("%02d",$hour) . ":" .
sprintf("%02d",$min) . ":" . sprintf("%02d",$sec) . " $text\n";
print LOG $tmpStr; print $tmpStr if $verbose;
}
close LOG;
}
}
# ClickOnIcon se lanzará tras un click en el TrayIcon.
# Para diferenciar el botón del ratón que se pulsó.
sub ClickOnIcon {
logsys ("debug", "sub: ClickOnIcon start");
my ($widget, $event) = @_;
return 1 if $event->button == 2;
$menu->popup(undef, undef, undef, undef, $event->button,$event->time) if $event->button == 3;
&extAppStatus($config->{'appOnClick'}) if $event->button == 1;
}
# extAppStatus lanzará una instancia de la aplicación si no existe
sub extAppStatus {
logsys ("debug", "sub: extAppStatus start");
my ($refApp) = @_;
$config->{ $refApp . 'Pid'} = fork()
unless ($config->{ $refApp . 'Pid'}); # Crea un proceso hijo
die "error al hacer fork: $!" if !defined($config->{$refApp . 'Pid'});
if ( $config->{$refApp . 'Pid'} == 0) { # Si se trata del proceso hijo
logsys ("msg", "Iniciando proceso hijo con [$refApp]");
if ($config->{$refApp . 'Ok'}) {
$SIG{TERM} = $SIG{QUIT} = $SIG{HUP} = $SIG{INT} = 'DEFAULT';
logsys ("warning", "Redirección de STDOUT para $refApp a $apppid");
open STDOUT, ">>$apppid";
exec ($config->{$refApp . 'App'}) ||
die "ATENCIÓN: Falló la ejecución de $refApp";
} else {exit -1}
} else { # Circuito del proceso padre
logsys ("msg", "Circuito del proceso padre [hijo=>$refApp pid:"
. $config->{$refApp . 'Pid'} . "]");
# Asigno una clave en la configuración con el valor de la pid con el padre
$config->{$config->{$refApp . 'Pid'}} = $refApp
unless $config->{$config->{$refApp . 'Pid'}};
# a ejecutar por el proceso padre
# TODO: Enviar setFocus a la aplicación
#
}
}
# appRel nombre y versión del script
sub appRel {
$0=~/.*\/(.*)$/;
my $fileRun = $1;
$fileRun = $0 unless $fileRun;
$fileRun = "aMulet.pl [$1]" if $fileRun ne 'aMulet.pl';
return $fileRun . " v.1.2 beta";
}
# popUpsAct des/activar apartados del menú
sub popUpsAct {
$menu_aLinkCreator->set_sensitive($config->{'aLinkCreatorOk'});
$menu_wxCas->set_sensitive($config->{'wxCasOk'});
$menu_aMuleGui->set_sensitive($config->{'aMuleGuiOk'});
}
# pathsVerify comprobar la ruta de las aplicaciones
sub pathsVerify{
foreach my $app (@appList) {
$config->{$app . 'Ok'} = (-x $config->{$app . 'App'});
}
}
# inicializar comprobaciones iniciales
sub inicializar {
my $tmpStr;
my $runDaemon;
# Comprobar si ya estamos en marcha
if (-f $apppid){
my $appVerify=0;
# Comprobar si realmente la aplicación está en marcha.
if (open(APPPID, $apppid)){
my $line;
while ($line = <APPPID>) {
chop($line); last;
}
close(APPPID);
$appVerify=&isRunProcess($line);
}
if ($appVerify){
$tmpStr = "<b>" .appRel . "</b> ya está funcionando!\n\n";
$SIG{TERM} = $SIG{QUIT} = $SIG{HUP} = $SIG{INT} = 'DEFAULT';
&showMessage( 'error', flushChars($tmpStr), 'ok');
exit -1;
} else {unlink $apppid}
}
# Iniciar Bloqueo
logsys ("msg", "Iniciando archivo de bloqueo");
if (open LOG, ">$apppid"){print LOG "$$\n"}
# Cargar la configuración
logsys ("msg", "Cargando la configuración");
&loadConfig;
readSignatureConf;
# Comprobar el estado del aMule como servicio
if ($config->{'aMuledOn'}){
logsys ("msg", "Iniciando la verificación de la existencia de amuled");
if (open(PROCESOS,"ps -A |")){
while (<PROCESOS>){
$runDaemon = 1 if ($_ =~ /amuled/);
}
close PROCESOS;
}
if (!$runDaemon) { $runDaemon = 1;
logsys ("msg", "No se detecta. Iniciando amuled ...");
if (open(AMULED,"$binaMuled |")){
my $aMuleRun;
while (<AMULED>){
logsys ("msg", $_);
logsys ("msg", "ATENCIÓN: Cambie la orden [$binaMuled] bajo su responsabilidad") if $_ =~ /binary requires/;
undef $runDaemon if $_ =~ /binary requires/;
$aMuleRun = 1 if $_ =~ /Raising current running instance/;
}
close AMULED;
if ($aMuleRun){
logsys ("msg", "*"x56 );
logsys ("msg", "*"x5 ." Se ha detectado que el aMule está en marcha " ."*"x6 );
logsys ("msg", "*"x56 );
logsys ("msg", "aMulet.pl se diseñó pensando en las herramientas remotas" );
logsys ("msg", "*"x56 );
logsys ("msg", "* FUNCIONARÍA, pero no veo la necesidad de ello. STOP!!" );
logsys ("msg", "*"x56 );
undef $runDaemon;
};
logsys ("msg", "El amuled ha sido puesto en marcha.") if $runDaemon;
} else {
undef $runDaemon;
logsys ("msg", "No se ha podido ejecutar el amuled!");
logsys ("msg", "Se puede indicar en la configuración que se salte este paso");
$tmpStr = "<u><b>No se ha podido ejecutar aMuled</b></u>.\n\n";
$tmpStr .= "¿Desactivo la opción de arrancar el amuled en la configuración?\n\n";
$tmpStr .= "Desactive esta opción si el aMuled está residente en otra máquina de su red.";
$tmpStr .= "\n\nNo he detectado el aMuleGui." unless $config->{'aMuleGuiOk'};
$tmpStr .= "\nDeberá indicar donde está situado éste en la configuración" unless $config->{'aMuleGuiOk'};
my $confirmacion= &showMessage( 'question', flushChars($tmpStr), 'yes-no');
if ($confirmacion eq 'yes'){
$config->{'aMuledOn'}=0;
&saveConfig;
$runDaemon = 1;
};
}
} else {logsys ("msg", "El aMuled ha sido detectado :))");}
} else {
$runDaemon = 1;
logsys ("msg", "ATENCIÓN No se detectará ni arrancará el aMuled");
logsys ("msg", " Se puede modificar esto en la configuración");
}
# Comprobar que la aplicación que arranca tras el click en el icono existe.
# Esto no afectará al retorno de esta función.
if ($runDaemon){
logsys ("msg", "Verificando la aplicación que responde al click del icono.");
if (!$config->{$config->{'appOnClick'} . 'Ok'}){
$tmpStr = "Debe indicar en la configuración dónde residen el ejecutable\n";
$tmpStr .= "de la aplicación <b>$config->{'appOnClick'}</b> o escoger otra\n";
$tmpStr .= "aplicación que responda al click en el icono";
&showMessage( 'warning', flushChars($tmpStr), 'ok');
&opcionesGui;
}
} # TODO: Intentar mostrarlo como modal y esperar respuesta.
return $runDaemon;
}
# visorTexto Crea una ventana Gtk en la que muestra el logfile del aMule
sub visorTexto {
logsys ("debug", "sub: visorTexto start");
my ($widget, $event) = @_;
logsys ("debug", "Deshabilitando la llamada en el menú");
$widget->set_sensitive(0);
my $visorTextWin = Gtk2::Window->new("toplevel");
my $vbox = Gtk2::VBox->new;
my $scrolledwindow = Gtk2::ScrolledWindow->new;
my $textBuffer = Gtk2::TextBuffer->new;
my $ok = Gtk2::Button->new_from_stock("gtk-close");
my $textView = Gtk2::TextView->new_with_buffer($textBuffer);
my $LineaLog;
$visorTextWin->set_title('Visor de Texto');
$visorTextWin->set_position('center');
$visorTextWin->set_default_size(640, 300);
logsys ("debug", "Leyendo " . $config->{'aMuleDir'} . "/logfile");
open (LOGFILE, $config->{'aMuleDir'} . "/logfile") || logsys ("warning", $config->{'aMuleDir'} . "/logfile: $!");
while (<LOGFILE>) {$LineaLog .= $_;}
close LOGFILE;
$textView->set_editable(0);
$textView->set_cursor_visible(0);
$textBuffer->set_text($LineaLog);
$scrolledwindow->set_policy('automatic', 'automatic');
$scrolledwindow->add($textView);
$vbox->add($scrolledwindow );
$vbox->pack_end($ok, 0, 0, 3);
$visorTextWin->add($vbox);
$ok->signal_connect("clicked", sub { $visorTextWin->destroy; } );
$visorTextWin->signal_connect('destroy' => sub { $widget->set_sensitive(1); });
logsys ("msg", "Mostrando la ventana de logs");
$visorTextWin->show_all;
}
# isRunProcess comprobará si un proceso está en ejecución
sub isRunProcess {
my ($proceso) = @_;
my $runDaemon = 0;
if (open(PROCESOS,"ps -A |")){
while (<PROCESOS>){$runDaemon = 1 if $_ =~ /^$proceso\s/;}
close PROCESOS;
}
return $runDaemon;
}
sub infoOnLine {
my $tmpStr = '';
&onlineInfo if $config->{'signOn'};
if ($config->{'signOn'} && $config->{'ConectStatus'}==1){
$tmpStr = "\n\n<b>" . $config->{'nickName'} . "</b> con <b>aMule</b> [<i>";
$tmpStr .= $config->{'aMuleVer'} . "</i>]\n";
$tmpStr .= "está conectado al puerto <b>" . $config->{'portServ'};
$tmpStr .= "</b> de <b>" . $config->{'nameServ'} . "</b>\ncon <b>ID ";
$tmpStr .= $config->{'typeId'}eq"H"?"alta</b>":"baja</b>";
$tmpStr .= " y la <b>red kad ";
if ($config->{'kadStatus'}==2) {$tmpStr .= "bien conectada</b>\n";
} elsif ($config->{'kadStatus'}==1) {$tmpStr .= "en firewalled</b>\n";
} else {$tmpStr .= "desconectada</b>\n"};
$tmpStr .= "lleva ";
my $tmpStr2 = $config->{'TimeRun'} % 60 . " segundos";
my $tiempo = sprintf("%d",$config->{'TimeRun'} / 60);
$tmpStr2 = $tiempo % 60 . " minutos y $tmpStr2" if $tiempo;
$tiempo = sprintf("%d",$tiempo / 60) if $tiempo;
$tmpStr2 = $tiempo % 24 . " horas $tmpStr2" if $tiempo;
$tiempo = sprintf("%d",$tiempo / 24) if $tiempo;
$tmpStr2 = $tiempo . " dias $tmpStr2" if $tiempo;
$tmpStr .= $tmpStr2 . " conectado\n";
$tmpStr .= "y en este tiempo ha descargado: <b>";
$tmpStr .= sprintf("%.2f",$config->{'SessionDown'}/1048576) . " Mb</b>\n";
$tmpStr .= "con lo que tiene un total descagado de ";
$tmpStr .= sprintf("%.2f",$config->{'totalDown'}/1048576) . " Mb\n";
$tmpStr .= "Además comparte <b>" . $config->{'filesShared'} . "</b> archivos y en esta sesión\n";
$tmpStr .= "se han subido <b>" . sprintf("%.2f",$config->{'SessionUp'}/1048576);
$tmpStr .= " Mb</b> obteniendo un\ntotal de " . sprintf("%.2f",$config->{'totalUp'}/1048576);
$tmpStr .= " Mb subidos a la Red,\nen cola tiene ahora mismo ";
$tmpStr .= $config->{'colaCli'} . " clientes";
}
return flushChars($tmpStr);
}
# opcionesGui muestra la ventana de opciones
sub opcionesGui {
my ($widget, $event) = @_;
logsys ("debug", "Deshabilitando la llamada en el menú");
$widget->set_sensitive(0) if defined $widget;
my $guiOpciones = Gtk2::Window->new;
my $vboxPrincipal = Gtk2::VBox->new;
my $notebook = Gtk2::Notebook->new;
my $select_aMuleGui = Gtk2::RadioButton->new('appOnClick', 'aMuleGui');
my @grupo = $select_aMuleGui->get_group;
my $select_alc = Gtk2::RadioButton->new_with_label(@grupo, 'aLinkCreator');
my $select_wxcas = Gtk2::RadioButton->new_with_label(@grupo, 'wxCas');
my $check_aMuled_on = new Gtk2::CheckButton->new(flushChars('Arrancar aMule como servicio al principio (si no lo está)'));
my $vBoxTabRutas = Gtk2::VBox->new;
my $vBoxTabAbout = Gtk2::VBox->new;
my $hboxPrincipal = Gtk2::HBox->new;
my $hBoxTabRutas1 = Gtk2::HBox->new;
my $hBoxTabRutas2 = Gtk2::HBox->new;
my $hBoxTabRutas3 = Gtk2::HBox->new(1);
my $hseparator1 = Gtk2::HSeparator->new;
my $hseparator2 = Gtk2::HSeparator->new;
my $hseparator3 = Gtk2::HSeparator->new;
my $labelTabRutas = Gtk2::Label->new('General');
my $labelTabAbout = Gtk2::Label->new('About');
my $labelTabRut1 = Gtk2::Label->new('Relacionado con el Servicio amuled');
my $labelTabRut2 = Gtk2::Label->new('aMule Home Dir');
my $labelTabRut3 = Gtk2::Label->new('Ruta a las aplicaciones');
my $labelTabRut4 = Gtk2::Label->new('aMuleGui: ');
my $labelTabRut5 = Gtk2::Label->new('wxCas: ');
my $labelTabRut6 = Gtk2::Label->new('aLinkCreator: ');
my $labelTabRut7 = Gtk2::Label->new(flushChars('Icono que se mostrará en la barra'));
my $labelTabRut8 = Gtk2::Label->new('Icono:');
my $labelTabRut9 = Gtk2::Label->new(flushChars('¿Qué aplicación arrancará tras hacer click en el icono?'));
my $labelAbout1 = Gtk2::Label->new('aMulet.pl');
my $labelAbout2 = Gtk2::Label->new('by AnimAlf - AnimAlf@engendro.sytes.net');
my $labelAbout3 = Gtk2::Label->new('una idea de tx2z en http://forum.amule.org');
my $labelAbout4 = Gtk2::Label->new('Distribuido bajo la licencia GPL');
my $labelAbout5 = Gtk2::Label->new('http://www.gnu.org/copyleft/gpl.html');
my $labelAbout6 = Gtk2::Label->new;
my $edit_home_aMule = Gtk2::Entry->new;
my $edit_aMuleGui_path = Gtk2::Entry->new;
my $edit_wxcas_path = Gtk2::Entry->new;
my $edit_alc_path = Gtk2::Entry->new;
my $edit_icon_path = Gtk2::Entry->new;
my $btnOk = Gtk2::Button->new_from_stock("gtk-apply");
my $btnCancel = Gtk2::Button->new_from_stock("gtk-cancel");
my $btnRutas1 = Gtk2::Button->new('...');
my $btnRutas2 = Gtk2::Button->new('...');
my $btnRutas3 = Gtk2::Button->new('...');
my $btnRutas4 = Gtk2::Button->new('...');
my $btnRutas5 = Gtk2::Button->new('Selecciona');
my $tableTabRutas = Gtk2::Table->new(3, 3, 0 );
# Posicionando en la ventana principal
$guiOpciones->add($vboxPrincipal);
# Posicionando en el notebook (contenedor de pestañas)
$vboxPrincipal->add($notebook);
# primera pestaña
$notebook->append_page($vBoxTabRutas, $labelTabRutas);
$vBoxTabRutas->pack_start($labelTabRut1, 0, 0, 3);
$vBoxTabRutas->pack_start($hBoxTabRutas1, 0, 0, 3);
$hBoxTabRutas1->pack_start($labelTabRut2, 0, 0, 3);
$hBoxTabRutas1->add($edit_home_aMule);
$hBoxTabRutas1->pack_end($btnRutas1, 0, 0, 3);
$vBoxTabRutas->pack_start($check_aMuled_on, 0, 0, 3);
$vBoxTabRutas->pack_start($hseparator2, 0, 0, 3);
$vBoxTabRutas->pack_start($labelTabRut3, 0, 0, 3);
$vBoxTabRutas->pack_start($tableTabRutas, 0, 0, 3);
$tableTabRutas->attach($labelTabRut4, 0, 1, 0, 1, ['fill'], [], 0, 0 );
$tableTabRutas->attach($edit_aMuleGui_path, 1, 2, 0, 1, ['expand', 'fill'], [], 0, 0 );
$tableTabRutas->attach($btnRutas2, 2, 3, 0, 1, ['fill'], [], 0, 0 );
$tableTabRutas->attach($labelTabRut5, 0, 1, 1, 2, ['fill'], [], 0, 0 );
$tableTabRutas->attach($edit_wxcas_path, 1, 2, 1, 2, ['expand', 'fill'], [], 0, 0 );
$tableTabRutas->attach($btnRutas3, 2, 3, 1, 2, ['fill'], [], 0, 0 );
$tableTabRutas->attach($labelTabRut6, 0, 1, 2, 3, ['fill'], [], 0, 0 );
$tableTabRutas->attach($edit_alc_path, 1, 2, 2, 3, ['expand', 'fill'], [], 0, 0 );
$tableTabRutas->attach($btnRutas4, 2, 3, 2, 3, ['fill'], [], 0, 0 );
$vBoxTabRutas->pack_start($hseparator1, 0, 0, 3);
$vBoxTabRutas->pack_start($labelTabRut9, 0, 0, 3);
$vBoxTabRutas->pack_start($hBoxTabRutas3, 0, 0, 3);
$hBoxTabRutas3->pack_start($select_aMuleGui, 0, 0, 3);
$hBoxTabRutas3->pack_start($select_alc, 0, 0, 3);
$hBoxTabRutas3->pack_start($select_wxcas, 0, 0, 3);
$vBoxTabRutas->pack_end($hBoxTabRutas2, 0, 0, 3);
$hBoxTabRutas2->pack_start($labelTabRut8, 0, 0, 3);
$hBoxTabRutas2->add($edit_icon_path);
$hBoxTabRutas2->pack_end($btnRutas5, 0, 0, 3);
$vBoxTabRutas->pack_end($labelTabRut7, 0, 0, 3);
$vBoxTabRutas->pack_end($hseparator3, 0, 0, 3);
# Segunda pestaña
$notebook->append_page($vBoxTabAbout, $labelTabAbout);
$vBoxTabAbout->pack_start($labelAbout1, 0, 0, 3);
$vBoxTabAbout->pack_start($labelAbout2, 0, 0, 3);
$vBoxTabAbout->pack_start($labelAbout3, 0, 0, 3);
$vBoxTabAbout->pack_start($labelAbout4, 0, 0, 3);
$vBoxTabAbout->pack_start($labelAbout5, 0, 0, 3);
$vBoxTabAbout->pack_start($labelAbout6, 0, 0, 3);
# Posicionando en la parte inferior de la ventana principal
$vboxPrincipal->pack_end($hboxPrincipal, 0, 0, 3);
$hboxPrincipal->pack_start($btnOk, 0, 0, 3);
$hboxPrincipal->pack_end($btnCancel, 0, 0, 3);
$labelAbout1->set_markup('<span foreground="DarkRed" size="x-large"><b>' . appRel . ' </b></span>');
#TODO: Intentar conseguir una UrlLabel, fácil con gnome-open (pero y si no existe gnome?)
#http://forum.amule.org/thread.php?threadid=9751
$labelAbout3->set_markup('<span>Una idea de <b>tx2z</b> en http://forum.amule.org</span>');
#Añado un mini resumen de la información disponible en amulesig.dat
$labelAbout6->set_markup(infoOnLine);
if ($config->{'signOn'}){
Glib::Timeout->add($config->{'signOnTime'}*1000, sub {
$labelAbout6->set_markup(infoOnLine);
$tray->send_message($config->{'signOnTime'}*1000, "[AnimAlf dice] No entiendo");});
}
# Propiedades de la ventana principal
$guiOpciones->set_title('Opciones aMulet.pl');
$guiOpciones->set_position('center');
#TODO: Intentar que actuase como una ventana modal, como el showMessage
# y el punto de la llamada esperase la respuesta ok-cancel
logsys ("msg", "Mostrando la ventana de opciones");
logsys ("warning", "*"x36) unless $widget;
logsys ("warning", "TODO: Que sea modal tipo showMessage") unless $widget;
logsys ("warning", "*"x36) unless $widget;
# Propiedades del notebook
$notebook->set_tab_pos('top');
$notebook->set_show_tabs (1);
$notebook->set_show_border(1);
$notebook->set_scrollable (0);
$notebook->set_tab_hborder(2);
$notebook->set_tab_vborder(2);
# alineando de algunas etiquetas
$labelTabRut4->set_alignment(1,0.5);
$labelTabRut5->set_alignment(1,0.5);
$labelTabRut6->set_alignment(1,0.5);
# Asignando la configuración.
$edit_home_aMule->set_text($config->{'aMuleDir'});
$edit_aMuleGui_path->set_text($config->{'aMuleGuiApp'});
$edit_wxcas_path->set_text($config->{'wxCasApp'});
$edit_alc_path->set_text($config->{'aLinkCreatorApp'});
$edit_icon_path->set_text($config->{'iconPath'});
$check_aMuled_on->set_active($config->{'aMuledOn'});
$select_wxcas->set_active($config->{'appOnClick'} eq 'wxCas');
$select_alc->set_active($config->{'appOnClick'} eq 'aLinkCreator');
$select_aMuleGui->set_active($config->{'appOnClick'} eq 'aMuleGui');
$select_wxcas->set_sensitive($config->{'wxCasOk'});
$select_alc->set_sensitive($config->{'aLinkCreatorOk'});
$select_aMuleGui->set_sensitive($config->{'aMuleGuiOk'});
# Lo mostramos todo
$guiOpciones->show_all;
# La asignación de señales
$btnOk->signal_connect("clicked", sub {
my ($tmpStr, $tmpStr1);
$tmpStr1 = 'wxCas' if $select_wxcas->get_active;
$tmpStr1 = 'aLinkCreator' if $select_alc->get_active;
$tmpStr1 = 'aMuleGui' if $select_aMuleGui->get_active;
$tmpStr .= $edit_home_aMule->get_text . ": No es un directorio\n"
if !(-d $edit_home_aMule->get_text);
$tmpStr .= $edit_aMuleGui_path->get_text . ": <b>No es un ejecutable</b> (o no existe)\n"
if !(-x $edit_aMuleGui_path->get_text);
$tmpStr .= $edit_wxcas_path->get_text . ": <b>No es un ejecutable</b> (o no existe)\n"
if !(-x $edit_wxcas_path->get_text);
$tmpStr .= $edit_alc_path->get_text . ": <b>No es un ejecutable</b> (o no existe)\n"
if !(-x $edit_alc_path->get_text);
$tmpStr .= $edit_icon_path->get_text . ": <b>No parece que exista</b>\n"
if !(-e $edit_icon_path->get_text);
if (defined $tmpStr){
$tmpStr = "<b>Se ha detectado lo siguiente:</b>\n\n$tmpStr\n\n" . flushChars("¿Desea continuar de todos modos?");
my $confirmacion= &showMessage( 'question', $tmpStr, 'yes-no');
return if ($confirmacion eq 'no');
}
$config->{'appOnClick'} = 'wxCas' if $select_wxcas->get_active;
$config->{'appOnClick'} = 'aLinkCreator' if $select_alc->get_active;
$config->{'appOnClick'} = 'aMuleGui' if $select_aMuleGui->get_active;
$config->{'aMuleDir'} = $edit_home_aMule->get_text;
$config->{'aMuleGuiApp'} = $edit_aMuleGui_path->get_text;
$config->{'wxCasApp'} = $edit_wxcas_path->get_text;
$config->{'aLinkCreatorApp'} = $edit_alc_path->get_text;
&showMessage( 'info', flushChars("El icono cambiará cuando reinicie la aplicación."), 'ok')
if $config->{'iconPath'} ne $edit_icon_path->get_text;
$config->{'iconPath'} = $edit_icon_path->get_text;
$config->{'aMuledOn'} = $check_aMuled_on->get_active;
&saveConfig; pathsVerify; popUpsAct; readSignatureConf;
$guiOpciones->destroy;
}
);
$btnCancel->signal_connect("clicked", sub { $guiOpciones->destroy; } );
$guiOpciones->signal_connect('destroy' => sub {$widget->set_sensitive(1) if defined $widget;});
$btnRutas1->signal_connect('clicked' => sub { dialogOpen($edit_home_aMule,
'Seleccione el directorio home de aMule', 'select-folder'); });
$btnRutas2->signal_connect('clicked' => sub { dialogOpen($edit_aMuleGui_path,
flushChars('Seleccione la aplicación aMuleGui'), 'open'); });
$btnRutas3->signal_connect('clicked' => sub { dialogOpen($edit_wxcas_path,
flushChars('Seleccione la aplicación wxCas'), 'open'); });
$btnRutas4->signal_connect('clicked' => sub { dialogOpen($edit_alc_path,
flushChars('Seleccione la aplicación aLinCreator'), 'open'); });
$btnRutas5->signal_connect('clicked' => sub { dialogOpen($edit_icon_path,
flushChars('Seleccione el icono que utilizará aMulet'), 'open'); });
}
# loadConfig carga la configuración o la crea si no existe
sub loadConfig {
if ( open( CONFIGFILE, "$ENV{HOME}/.aMule/amulet.rc" ) ) {
while (<CONFIGFILE>) {
if ( $_ =~ /(\w+)\s=\s(.+)/ ) { $config->{$1} = $2 }
}
close CONFIGFILE;
} else {
# es la primera vez.
mkdir "$ENV{HOME}/.aMule" unless (-d "$ENV{HOME}/.aMule");
$config = { # Por defecto
'aMuleDir' => "$ENV{'HOME'}/.aMule",
'aMuleGuiApp' => 'amulegui',
'wxCasApp' => 'wxcas',
'aLinkCreatorApp' => 'alc',
'iconPath' => '/usr/share/pixmaps/amule.xpm',
'appOnClick' => 'aMuleGui',
'aMuledOn' => 1
};
foreach my $app (@appList) {
$config->{$app . 'App'} = which($config->{$app . 'App'});
}
pathsVerify;
&saveConfig;
}
pathsVerify;
}
# saveConfig guarda la configuración en un archivo
sub saveConfig {
my @keyList = ('aMuleDir', 'aMuleGuiApp', 'wxCasApp',
'aLinkCreatorApp', 'iconPath', 'appOnClick', 'aMuledOn');
if ( open( CONFIGFILE, '>', "$ENV{HOME}/.aMule/amulet.rc" ) ) {
foreach my $key (@keyList) {
print CONFIGFILE "$key = $config->{$key}\n" if $config->{$key} ne '';
}
close CONFIGFILE;
}else {logSys("warning", "No se puede escribir en el archivo de configuración!");}
};
# showMessage Muestra una ventana con un mensaje, y espera respuesta.
sub showMessage {
#$icon info warning error question
#$type none ok close cancel yes-no ok-cancel
my ($icon,$text,$type) = @_;
my $dialog = Gtk2::MessageDialog->new_with_markup (undef,
[qw/modal destroy-with-parent/], $icon, $type, sprintf "$text");
my $retval = $dialog->run;
$dialog->destroy;
return $retval;
}
# which Devuelve el path completo a la aplicación.
sub which {
my $appFile = shift;
foreach (split(':', $ENV{PATH})) {
my $tmpStr = "$_/$appFile";
if (-x $tmpStr) {
$appFile = $tmpStr;
last;
}
}
return $appFile;
}
# dialogOpen ventana de selección de archivos o directorios y escribe
# el resultado en en el entry que debe ser el primer parámetro.
sub dialogOpen {
# $widget debe ser un entry
# $type open save select-folder create-folder
my($widget,$caption,$type) =@_;
my $chooserDialog = Gtk2::FileChooserDialog->new ($caption, undef, $type,
'gtk-cancel' => 'cancel', 'gtk-ok' => 'ok');
my $filename = $chooserDialog->get_filename if 'ok' eq $chooserDialog->run;
$widget->set_text ($filename) if defined $filename;
$chooserDialog->destroy;
return;
}
|
