#!/usr/bin/env perl # # $Id$ # # Copyright 2008 Norbert Preining, Reinhard Kotucha # This file is licensed under the GNU General Public License version 2 # or any later version. # # # MISSING SUPPORT FOR: # - TEXMFHOME ??? # # TODO: # - 'cancel' in the collections/scheme dialogs is not really a cancel because # the checkboxes are tied to the %vars hash, which make cancel == return!!! # - does the DoOneEvent *NEVER* hang??? our %vars; our $tlpdb; our @collections_std; our @collections_lang; our @collections_lang_doc; our $texlive_release; our $trynet; our $max_bins_on_CD; our $MENU_INSTALL = 0; our $MENU_ABORT = 1; our $MENU_QUIT = 2; our $MENU_ALREADYDONE = 3; my $return = $MENU_INSTALL; require Tk; require Tk::Dialog; my $mw; my $bintextbutton; my $schemebutton; my $collectionstext; my $texmflocaltext; my $texmfsysvartext; my $texdirtext; my $symlinktext; push @::start_install_hook, sub { update_statusbar("Starting Installation"); Tk::DoOneEvent(Tk::Event::DONT_WAIT); Tk::DoOneEvent(Tk::Event::DONT_WAIT); }; push @::start_postinst_hook, sub { update_statusbar("Starting Post Installation Jobs"); Tk::DoOneEvent(Tk::Event::DONT_WAIT); Tk::DoOneEvent(Tk::Event::DONT_WAIT); }; push @::end_install_hook, sub { update_statusbar("Installation finished"); Tk::DoOneEvent(Tk::Event::DONT_WAIT); Tk::DoOneEvent(Tk::Event::DONT_WAIT); }; push @::install_packages_hook, \&update_statusbar; # no idea how many of those are necessary, 1 is definitely not enough! push @::install_packages_hook, sub { Tk::DoOneEvent(Tk::Event::DONT_WAIT); }; push @::install_packages_hook, sub { Tk::DoOneEvent(Tk::Event::DONT_WAIT); }; push @::install_packages_hook, sub { Tk::DoOneEvent(Tk::Event::DONT_WAIT); }; push @::install_packages_hook, sub { Tk::DoOneEvent(Tk::Event::DONT_WAIT); }; push @::install_packages_hook, sub { Tk::DoOneEvent(Tk::Event::DONT_WAIT); }; push @::install_packages_hook, sub { Tk::DoOneEvent(Tk::Event::DONT_WAIT); }; push @::install_packages_hook, sub { Tk::DoOneEvent(Tk::Event::DONT_WAIT); }; push @::install_packages_hook, sub { Tk::DoOneEvent(Tk::Event::DONT_WAIT); }; push @::install_packages_hook, sub { Tk::DoOneEvent(Tk::Event::DONT_WAIT); }; push @::install_packages_hook, sub { Tk::DoOneEvent(Tk::Event::DONT_WAIT); }; push @::install_packages_hook, sub { Tk::DoOneEvent(Tk::Event::DONT_WAIT); }; push @::install_packages_hook, sub { Tk::DoOneEvent(Tk::Event::DONT_WAIT); }; push @::install_packages_hook, sub { Tk::DoOneEvent(Tk::Event::DONT_WAIT); }; push @::install_packages_hook, sub { Tk::DoOneEvent(Tk::Event::DONT_WAIT); }; push @::install_packages_hook, sub { Tk::DoOneEvent(Tk::Event::DONT_WAIT); }; push @::install_packages_hook, sub { Tk::DoOneEvent(Tk::Event::DONT_WAIT); }; sub update_statusbar { my $p = shift; $::statusbar->configure(-text => "$p"); } sub run_menu { calc_depends; $mw = MainWindow->new; my $f0 = $mw->Frame; my $fl = $f0->Frame; my $fr = $f0->Frame; $f0->pack; $fl->pack(-side => 'left'); $fr->pack(-side => 'right'); my $img = $fl->Pixmap(-file => "install-tl.xpm"); $fl->Label(-image => $img)->pack; $fr->Label(-text => 'TeX Live 2008 Installation')->pack; $bintextbutton = $fr->Button( -command => sub { menu_select_binsystems(); } ); $bintextbutton->pack; $schemebutton = $fr->Button( -command => sub { menu_select_scheme(); } ); $schemebutton->pack; $fr->Label(-text => 'Customizing installation scheme')->pack; $fr->Button( -text => "Standard Collections", -command => sub { menu_select_standard_collections(); } )->pack; $fr->Button( -text => "Language Collections", -command => sub { menu_select_lang_collections(); } )->pack; $collectionstext = $fr->Label(); $collectionstext->pack; #$fr->Button( # -text => "Directories' setup", # -command => sub { notimpl(); } #)->pack; $fr->Label(-text => "Directories' setup")->pack; $texdirtext = $fr->Button( -command => sub { menu_edit_vars_value("TEXDIR"); } ); $texmflocaltext = $fr->Button( -command => sub { menu_edit_vars_value("TEXMFLOCAL"); } ); $texmfsysvartext = $fr->Button( -command => sub { menu_edit_vars_value("TEXMFSYSVAR"); } ); $texdirtext->pack; $texmflocaltext->pack; $texmfsysvartext->pack; $fr->Checkbutton(-variable => \$vars{'option_letter'}, -text => "use letter size instead of A4 by default")->pack; $fr->Checkbutton(-variable => \$vars{'option_fmt'}, -text => "create all format files")->pack; $fr->Checkbutton(-variable => \$vars{'option_doc'}, -text => "install font/macro doc tree")->pack; $fr->Checkbutton(-variable => \$vars{'option_src'}, -text => "install font/macro source tree")->pack; if (unix()) { $symlinktext = $fr->Button(-command => sub { menu_select_symlink(); })->pack; } my $f3 = $fr->Frame; $f3->Button( -text => 'Install TeX Live', -command => sub { do_installation(); $return = $MENU_ALREADYDONE; $fr->Dialog(-text => 'Installation finished', -buttons => [qw/Finish/])->Show; $mw->destroy }, )->pack(-side => 'left'); $f3->Button( -text => 'Quit', -command => sub { exit 0; $return = $MENU_ABORT; $mw->destroy } )->pack(-side => 'right'); $f3->pack(-expand => 'x'); $::statusbar = $mw->Label(-text => 'Status output'); $::statusbar->pack; menu_update_texts(); Tk::MainLoop(); return($return); } sub notimpl { my $errorwin = $mw->Toplevel; $errorwin->Button(-text => "Not implemented yet!", -command => [ $errorwin => 'destroy' ])->pack; } sub menu_edit_vars_value { my $key = shift; my $sw = $mw->Toplevel; my $val = $vars{$key}; $sw->Label(-text => "Enter path for $key:")->pack; my $entry = $sw->Entry(-textvariable => $val, -width => 60); $entry->pack; my $f = $sw->Frame; $f->Button(-text => "Ok", -command => sub { $val = $entry->get; callback_edit_directories($key,$val) ; $sw->destroy })->pack(-side => 'left'); $f->Button(-text => "Cancel", -command => sub { $sw->destroy })->pack(-side => 'right'); $f->pack(-expand => 'x'); } sub menu_select_scheme { my $sw = $mw->Toplevel; my @schemes; foreach my $pkg ($tlpdb->list_packages) { my $tlpobj = $tlpdb->{'tlps'}{$pkg}; if ($tlpobj->category eq "Scheme") { push @schemes, $pkg; $vars{"$pkg"}=($vars{'selected_scheme'} eq $pkg)? 1:0; } } @schemes=sort @schemes; my $selected = $vars{'selected_scheme'}; $sw->Label(-text => 'Select Scheme')->pack; my $f2 = $sw->Frame; my $f2l = $f2->Frame; my $f2r = $f2->Frame; my $nrfh = $#schemes / 2; my $i = 0; foreach my $scheme (@schemes) { my $tlpobj = $tlpdb->get_package("$scheme"); if ($i < $nrfh) { $f2l->Radiobutton(-variable => \$selected, -value => $scheme, -text => $tlpobj->shortdesc)->pack(-anchor => 'w'); } else { $f2r->Radiobutton(-variable => \$selected, -value => $scheme, -text => $tlpobj->shortdesc)->pack(-anchor => 'w'); } $i++; } $f2l->pack(-side => 'left'); $f2r->pack(-side => 'right'); $f2->pack; my $f3 = $sw->Frame; $f3->Button(-text => "Return", -command => sub { callback_select_scheme($selected) ; $sw->destroy })->pack(-side => 'left'); $f3->Button(-text => "Cancel", -command => sub { $sw->destroy })->pack(-side => 'right'); $f3->pack(-expand => 'x'); } sub menu_select_standard_collections { my $sw = $mw->Toplevel; my $fb = $sw->Frame; my $fc = $sw->Frame; my $fd = $sw->Frame; my $f1 = $fb->Frame; my $f2 = $fb->Frame; my %lvars = %vars; $sw->Label(-text => 'Select the collections to be installed')->pack; my $halfcol = $#collections_std / 2; my $i = 0; foreach my $coll (sort @collections_std) { my $tlpobj = $tlpdb->get_package("$coll"); if ($i < $halfcol) { $f1->Checkbutton(-variable => \$lvars{$coll}, -text => $tlpobj->shortdesc)->pack(-anchor => 'w'); } else { $f2->Checkbutton(-variable => \$lvars{$coll}, -text => $tlpobj->shortdesc)->pack(-anchor => 'w'); } $i++; } $f1->pack(-side => 'left'); $f2->pack(-side => 'right'); $fb->pack; $fd->pack(-expand => 'x'); $fd->Button(-text => "Select all", -command => sub { select_collections(\%lvars, @collections_std) })->pack(-side => 'left'); $fd->Button(-text => "Deselect all", -command => sub { deselect_collections(\%lvars, @collections_std) })->pack(-side => 'right'); $fc->pack(-expand => 'x'); $fc->Button(-text => "Return", -command => sub { %vars = %lvars; callback_select_collection() ; $sw->destroy })->pack(-side => 'left'); $fc->Button(-text => "Cancel", -command => sub { $sw->destroy })->pack(-side => 'right'); } sub menu_select_lang_collections { my $sw = $mw->Toplevel; my $f1 = $sw->Frame; $f1->pack; my $f1lang = $f1->Frame; my $f1doc = $f1->Frame; $f1lang->pack(-side => 'left'); $f1doc->pack(-side => 'right'); my $f1langT = $f1lang->Frame; $f1langT->pack; my $f1langL = $f1lang->Frame; $f1langL->pack; $f1langT->Label(-text => 'Language Selection')->pack; my $f1langLa = $f1langL->Frame; $f1langLa->pack(-side => 'left'); my $f1langLb = $f1langL->Frame; $f1langLb->pack(-side => 'right'); my $langh = $#collections_lang / 2; my $i = 0; my %lvars = %vars; foreach my $coll (sort @collections_lang) { my $tlpobj = $tlpdb->get_package("$coll"); if ($i < $langh) { $f1langLa->Checkbutton(-variable => \$lvars{$coll}, -text => $tlpobj->shortdesc)->pack(-anchor => 'w'); } else { $f1langLb->Checkbutton(-variable => \$lvars{$coll}, -text => $tlpobj->shortdesc)->pack(-anchor => 'w'); } $i++; } my $f1langB = $f1lang->Frame; $f1langB->pack(-expand => 'x'); $f1langB->Button(-text => "Select all", -command => sub { select_collections(\%lvars, @collections_lang) })->pack(-side => 'left'); $f1langB->Button(-text => "Deselect all", -command => sub { deselect_collections(\%lvars, @collections_lang) })->pack(-side => 'right'); my $f1docT = $f1doc->Frame; $f1docT->pack; my $f1docL = $f1doc->Frame; $f1docL->pack; $f1docT->Label(-text => 'Doc/Language Selection')->pack; my $f1docLa = $f1docL->Frame; $f1docLa->pack(-side => 'left'); my $f1docLb = $f1docL->Frame; $f1docLb->pack(-side => 'right'); my $doch = $#collections_lang_doc / 2; $i = 0; foreach my $coll (sort @collections_lang_doc) { my $tlpobj = $tlpdb->get_package("$coll"); if ($i < $doch) { $f1docLa->Checkbutton(-variable => \$lvars{$coll}, -text => $tlpobj->shortdesc)->pack(-anchor => 'w'); } else { $f1docLb->Checkbutton(-variable => \$lvars{$coll}, -text => $tlpobj->shortdesc)->pack(-anchor => 'w'); } $i++; } my $f1docB = $f1doc->Frame; $f1docB->pack(-expand => 'x'); $f1docB->Button(-text => "Select all", -command => sub { select_collections(\%lvars, @collections_lang_doc) })->pack(-side => 'left'); $f1docB->Button(-text => "Deselect all", -command => sub { deselect_collections(\%lvars, @collections_lang_doc) })->pack(-side => 'right'); my $f2 = $sw->Frame; $f2->pack(-expand => 'x'); $f2->Button(-text => "Return", -command => sub { %vars = %lvars; callback_select_collection() ; $sw->destroy })->pack(-side => 'left'); $f2->Button(-text => "Cancel", -command => sub { $sw->destroy })->pack(-side => 'right'); } sub menu_select_symlink { our ($lbin,$lman,$linfo); our $osym = $vars{'option_symlinks'}; sub set_unset_buttons { $lbin = ($osym ? $vars{'sys_bin'} : ''); $linfo = ($osym ? $vars{'sys_info'} : ''); $lman = ($osym ? $vars{'sys_man'} : ''); } sub return_callback { if ($osym) { $vars{'sys_bin'} = $lbin; $vars{'sys_info'} = $linfo; $vars{'sys_man'} = $lman; } $vars{'option_symlinks'} = $osym; menu_update_texts(); } set_unset_buttons(); my $sw = $mw->Toplevel; $sw->Checkbutton(-variable => \$osym, -text => 'create symlinks in standard directories', -command => sub { set_unset_buttons(); } )->pack; my $fbin = $sw->Frame; $fbin->Label(-text => 'binaries to: ')->pack(-side => 'left'); my $binb = $fbin->Entry(-textvariable => \$lbin, -width => 30); $binb->pack(-side => 'right'); $fbin->pack(-expand => 'x'); my $fman = $sw->Frame; $fman->Label(-text => 'manpages to: ')->pack(-side => 'left'); my $manb = $fman->Entry(-textvariable => \$lman, -width => 30); $manb->pack(-side => 'right'); $fman->pack(-expand => 'x'); my $finfo = $sw->Frame; $finfo->Label(-text => 'info to: ')->pack(-side => 'left'); my $infob = $finfo->Entry(-textvariable => \$linfo, -width => 30); $infob->pack(-side => 'right'); $finfo->pack(-expand => 'x'); my $f2 = $sw->Frame; $f2->pack(-expand => 'x'); $f2->Button(-text => "Return", -command => sub { return_callback(); $sw->destroy })->pack(-side => 'left'); $f2->Button(-text => "Cancel", -command => sub { $sw->destroy })->pack(-side => 'right'); } sub menu_select_binsystems { our $f2r; our $f2; our @netarchs = (); sub update_net_archs() { my $oldnrnetarch = $#netarchs; $trynet = 1; set_platforms_supported(); $trynet=0; @netarchs = (); foreach my $key (keys %vars) { if ($key=~/netbin_(.*)/) { push @netarchs, $1; $from_net{"$1"}=1; } } menu_update_texts(); if ($#netarchs != $oldnrnetarch) { # we have to destroy the old $f2r frame and make a new one $f2r->destroy; do_net_frame(); } } sub do_net_frame { $f2r = $f2->Frame; if ($#netarchs >= 0) { $f2r->Label(-text => 'On Net')->pack; foreach my $sys (sort @netarchs) { $f2r->Checkbutton(-variable => \$vars{"netbin_$sys"}, -text => "$sys")->pack(-anchor => 'w'); } $f2r->pack(-side => 'right'); } $f2->pack; } my $sw = $mw->Toplevel; my @diskarchs = (); foreach my $key (keys %vars) { if ($key=~/diskbin_(.*)/) { push @diskarchs, $1; $from_net{"$1"}=0; } if ($key=~/netbin_(.*)/) { push @netarchs, $1; $from_net{"$1"}=1; } } $sw->Label(-text => 'Select arch/os')->pack; $f2 = $sw->Frame; my $f2l = $f2->Frame; $f2l->Label(-text => 'On Disk')->pack; foreach my $sys (sort @diskarchs) { $f2l->Checkbutton(-variable => \$vars{"diskbin_$sys"}, -text => platform_desc($sys))->pack(-anchor => 'w'); } $f2l->pack(-side => 'left'); do_net_frame(); my $f4 = $sw->Frame; $f4->pack; $f4->Button(-text => 'Click for net bins', -command => sub { update_net_archs(); })->pack; my $f3 = $sw->Frame; $f3->Button(-text => "Return", -command => sub { callback_select_systems() ; $sw->destroy })->pack(-side => 'left'); $f3->Button(-text => "Cancel", -command => sub { $sw->destroy })->pack(-side => 'right'); $f3->pack(-expand => 'x'); } sub menu_set_text { my $w = shift; my $t = shift; $w->configure(-text => $t); } sub menu_set_symlink_text { menu_set_text($symlinktext, "Install symlinks: " . (($vars{'option_symlinks'})?"Yes":"No")); } sub menu_set_schemebutton_text { menu_set_text($schemebutton, "Selected Scheme: $vars{'selected_scheme'}"); } sub menu_set_binbutton_text { menu_set_text($bintextbutton, "Binary Systems $vars{'n_systems_selected'} out of $vars{'n_systems_available'}"); } sub menu_set_collections_text { menu_set_text($collectionstext, "$vars{'n_collections_selected'} collections out of $vars{'n_collections_available'}, disk space required: $vars{'total_size'} MB"); } sub menu_set_pathes_text { menu_set_text($texdirtext, "TEXDIR (The main TeX directory): $vars{'TEXDIR'}"); menu_set_text($texmflocaltext, "TEXMFLOCAL (Directory for local styles etc): $vars{'TEXMFLOCAL'}"); menu_set_text($texmfsysvartext, "TEXMFSYSVAR (Directory for local config): $vars{'TEXMFSYSVAR'}"); } sub menu_update_texts { menu_set_pathes_text; menu_set_collections_text; menu_set_binbutton_text; menu_set_schemebutton_text; if (unix()) { menu_set_symlink_text; }; } sub callback_select_scheme { my $s = shift; select_scheme($s); menu_update_texts(); } sub callback_select_collection { calc_depends(); update_numbers(); menu_update_texts(); } sub callback_select_systems() { calc_depends(); update_numbers(); menu_update_texts(); } sub callback_edit_directories { my ($key,$val) = @_; $vars{$key} = $val; if ($vars{'TEXDIR'}=~/^(.*)\/$texlive_release$/) { $vars{'TEXMFLOCAL'}="$1/texmf-local"; $vars{'TEXMFSYSVAR'}="$1/$texlive_release/texmf-var"; } elsif ($vars{'TEXDIR'}=~/^(.*)$/) { $vars{'TEXMFLOCAL'}="$1/texmf-local"; $vars{'TEXMFSYSVAR'}="$1/texmf-var"; } menu_update_texts(); } sub callback_edit_var() { my ($key,$val) = @_; $vars{$key} = $val; menu_update_texts(); } sub dump_vars_stdout { foreach my $k (keys %vars) { print "DEBUG: vars{$k} = $vars{$k}\n"; } } sub select_collections { my $varref = shift; foreach (@_) { $varref->{$_} = 1; } } sub deselect_collections { my $varref = shift; foreach (@_) { $varref->{$_} = 0; } } 1; __END__ ### Local Variables: ### perl-indent-level: 2 ### tab-width: 2 ### indent-tabs-mode: nil ### End: # vim:set tabstop=2 expandtab: #