package install::steps_gtk; # $Id: steps_gtk.pm 266069 2010-02-09 19:47:35Z pterjan $ use diagnostics; use strict; use feature 'state'; use vars qw(@ISA); @ISA = qw(install::steps_interactive interactive::gtk); #-###################################################################################### #- misc imports #-###################################################################################### use install::pkgs; use install::steps_interactive; use interactive::gtk; use xf86misc::main; use common; use mygtk2; use ugtk2 qw(:helpers :wrappers :create); use devices; use modules; use install::gtk; use install::any; use mouse; use install::help::help; use log; #-###################################################################################### #- In/Out Steps Functions #-###################################################################################### sub new($$) { my ($type, $o) = @_; $ENV{DISPLAY} ||= $o->{display} || ":0"; my $wanted_DISPLAY = $::testing && -x '/usr/bin/Xnest' ? ':9' : $ENV{DISPLAY}; if (!$::local_install && ($::testing ? $ENV{DISPLAY} ne $wanted_DISPLAY : $ENV{DISPLAY} =~ /^:\d/)) { #- is the display local or distant? my $f = "/tmp/Xconf"; if (!$::testing) { devices::make("/dev/kbd"); } #- /tmp is mostly tmpfs, but not fully, since it doesn't allow: mount --bind /tmp/.X11-unix /mnt/tmp/.X11-unix mkdir '/tmp/.X11-unix'; run_program::run('mount', '-t', 'tmpfs', 'none', '/tmp/.X11-unix'); my $launchX = sub { my ($server, $Driver) = @_; mkdir '/var/log' if !-d '/var/log'; my @options = $wanted_DISPLAY; if ($server eq 'Xnest') { push @options, '-ac', '-geometry', $o->{vga} || ($o->{vga16} ? '640x480' : '800x600'); } else { install::gtk::createXconf($f, @{$o->{mouse}}{'Protocol', 'device'}, $o->{mouse}{wacom}[0], $Driver); push @options, '-allowMouseOpenFail', '-xf86config', $f if arch() !~ /^sparc/; push @options, 'vt7', '-dpi', '75'; push @options, '-nolisten', 'tcp'; #- old weird servers: Xsun push @options, '-fp', '/usr/share/fonts:unscaled' if $server =~ /Xsun/; } if (!fork()) { c::setsid(); exec $server, @options or c::_exit(1); } #- wait for the server to start foreach (1..5) { sleep 1; last if fuzzy_pidofs(qr/\b$server\b/); log::l("$server still not running, trying again"); } my $nb; my $start_time = time(); foreach (1..60) { log::l("waiting for the server to start ($_ $nb)"); log::l("Server died"), return 0 if !fuzzy_pidofs(qr/\b$server\b/); $nb++ if xf86misc::main::Xtest($wanted_DISPLAY); if ($nb > 2) { #- one succeeded test is not enough :-( log::l("AFAIK X server is up"); return 1; } time() - $start_time < 60 or last; time() - $start_time > 8 and print N("Xorg server is slow to start. Please wait..."), "\n"; sleep 1; } log::l("Timeout!!"); 0; }; my @servers = qw(Driver:fbdev Driver:vesa); #-) if ($::testing) { @servers = 'Xnest'; } elsif (arch() =~ /ia64/) { require Xconfig::card; my ($card) = Xconfig::card::probe(); @servers = map { if_($_, "Driver:$_") } $card && $card->{Driver}, 'fbdev'; } elsif (arch() =~ /i.86/) { require Xconfig::card; my ($card) = Xconfig::card::probe(); if ($card && $card->{card_name} eq 'i810') { # early i810 do not support VESA: log::l("graphical installer not supported on early i810"); undef @servers; } } foreach (@servers) { log::l("Trying with server $_"); my ($prog, $Driver) = /Driver:(.*)/ ? ('Xorg', $1) : /Xsun|Xnest|^X_move$/ ? $_ : "XF86_$_"; if (/FB/i) { !$o->{vga16} && $o->{allowFB} or next; $o->{allowFB} = &$launchX($prog, $Driver) #- keep in mind FB is used. and goto OK; } else { $o->{vga16} = 1 if /VGA16/; &$launchX($prog, $Driver) and goto OK; } } return undef; } OK: $ENV{DISPLAY} = $wanted_DISPLAY; require detect_devices; if (detect_devices::is_xbox()) { modules::load('xpad'); run_program::run('xset', 'm', '1/8', '1'); } any::disable_x_screensaver(); run_program::raw({ detach => 1 }, 'drakx-matchbox-window-manager'); install::gtk::init_gtk($o); install::gtk::init_sizes($o); install::gtk::install_theme($o); install::gtk::create_steps_window($o); _may_configure_framebuffer_640x480($o); $ugtk2::grab = 1; $o = (bless {}, ref($type) || $type)->SUPER::new($o); $o->interactive::gtk::new; $o; } #- if we success to start X in 640x480 using driver "vesa", #- we configure to use fb on installed system (to ensure splashy works) #- (useful on 800x480 netbooks) sub _may_configure_framebuffer_640x480 { my ($o) = @_; if ($::rootwidth == 640 && !$o->{allowFB}) { $o->{vga} = 785; $o->{allowFB} = 1; } } sub enteringStep { my ($o, $step) = @_; printf "Entering step `%s'\n", common::remove_translate_context($o->{steps}{$step}{text}); if (my $banner_title = $o->{steps}{$step}{banner_title}) { set_default_step_items($banner_title); } $o->SUPER::enteringStep($step); install::gtk::update_steps_position($o); } sub leavingStep { my ($o, $step) = @_; $o->SUPER::leavingStep($step); } sub charsetChanged { my ($o) = @_; Gtk2->set_locale; install::gtk::load_font($o); install::gtk::create_steps_window($o); } sub interactive_help_has_id { my ($_o, $id) = @_; exists $install::help::help::{$id}; } sub interactive_help_get_id { my ($_o, @l) = @_; @l = map { join("\n\n", map { s/\n/ /mg; $_ } split("\n\n", translate($install::help::help::{$_}->()))); } grep { exists $install::help::help::{$_} } @l; join("\n\n\n", @l); } #-###################################################################################### #- Steps Functions #-###################################################################################### sub selectLanguage { my ($o) = @_; $o->SUPER::selectLanguage; $o->ask_warn('', formatAlaTeX(N("Your system is low on resources. You may have some problem installing %s. If that occurs, you can try a text install instead. For this, press `F1' when booting on CDROM, then enter `text'."))) if availableRamMB() < 70; # 70MB } #------------------------------------------------------------------------------ sub selectMouse { my ($o, $force) = @_; my %old = %{$o->{mouse}}; $o->SUPER::selectMouse($force) or return; my $mouse = $o->{mouse}; $mouse->{type} eq 'none' || $old{type} eq $mouse->{type} && $old{name} eq $mouse->{name} && $old{device} eq $mouse->{device} and return; while (1) { my $x_protocol_changed = mouse::change_mouse_live($mouse, \%old); mouse::test_mouse_install($mouse, $x_protocol_changed) and return; %old = %$mouse; $o->SUPER::selectMouse; $mouse = $o->{mouse}; } } sub reallyChooseDesktop { my ($o, $title, $message, $choices, $choice) = @_; my $w = ugtk2->new($title); my %tips = ( KDE => N("Install %s KDE Desktop"), GNOME => N("Install %s GNOME Desktop"), Custom => N("Custom install"), ); my $prev; my @l = map { my $val = $_; $prev = gtknew('RadioButton', child => gtknew('Label', text => $val->[1]), tip => $tips{$val->[0]}, toggled => sub { $choice = $val if $_[0]->get_active }, active => $choice == $val, $prev ? (group => $prev->get_group) : ()); $prev->signal_connect(key_press_event => sub { my (undef, $event) = @_; if (!$event || ($event->keyval & 0x7f) == 0xd) { Gtk2->main_quit; } }); my $img = gtksignal_connect( gtkadd(Gtk2::EventBox->new, gtknew('Image', file => "desktop-$val->[0]")), 'button-press-event' => sub { my %title = ( KDE => N("KDE Desktop"), GNOME => N("GNOME Desktop"), Custom => N("Custom Desktop"), ); my $wp = ugtk2->new($title{$val->[0]}, transient => $w->{real_window}, modal => 1); gtkadd($wp->{rwindow}, gtkpack_(Gtk2::VBox->new, 0, gtknew('Title2', label => N("Here's a preview of the '%s' desktop.", $val->[1]), # workaround infamous 6 years old gnome bug #101968: width => mygtk2::get_label_width(), ), 1, gtknew('Image', file => "desktop-$val->[0]-big"), 0, Gtk2::HSeparator->new, 0, gtkpack(create_hbox('end'), gtknew('Button', text => N("Close"), clicked => sub { Gtk2->main_quit }) ), ), ); $wp->{real_window}->set_size_request(-1, -1); $wp->{real_window}->grab_focus; $wp->{real_window}->grab_focus; $wp->{real_window}->show_all; $wp->main; }); gtknew('VBox', border_width => 15, spacing => 10, children_tight => [ $img, $prev, ]); } @$choices; ugtk2::gtkadd($w->{window}, gtknew('VBox', children => [ 0, gtknew('Title2', # workaround infamous 6 years old gnome bug #101968: width => mygtk2::get_label_width(), label => $message . ' ' . N("Click on images in order to see a bigger preview")), 1, gtknew('HButtonBox', children_loose => \@l), 0, $w->create_okcancel(N("Next"), undef, '', [ gtknew('Install_Button', text => N("Help"), clicked => sub { interactive::gtk::display_help( $o, { interactive_help_id => 'choosePackages#choose-graphical-env' }, $w); }), undef, 1 ]) ])); $w->main; $choice; } sub reallyChooseGroups { my ($o, $size_to_display, $individual, $_compssUsers) = @_; my $w = ugtk2->new(N("Package Group Selection")); my $w_size = gtknew('Label_Left', text => &$size_to_display, padding => [ 0, 0 ]); my $entry = sub { my ($e) = @_; gtknew('CheckButton', text => translate($e->{label}), tip => translate($e->{descr}), active_ref => \$e->{selected}, toggled => sub { gtkset($w_size, text => &$size_to_display); }); }; #- when restarting this step, it might be necessary to reload the compssUsers.pl (bug 11558). kludgy. if (!ref $o->{gtk_display_compssUsers}) { install::any::load_rate_files($o) } ugtk2::gtkadd($w->{window}, gtknew('VBox', children => [ 1, $o->{gtk_display_compssUsers}->($entry), 1, '', 0, if_($individual, gtknew('CheckButton', text => N("Individual package selection"), active_ref => $individual), ), 0, $w_size, 0, Gtk2::HSeparator->new, 0, gtknew('HButtonBox', layout => 'edge', children_tight => [ gtknew('Install_Button', text => N("Help"), clicked => sub { interactive::gtk::display_help($o, { interactive_help_id => 'choosePackages#choosePackagesGroups' }, $w) }), gtknew('Button', text => N("Next"), clicked => sub { Gtk2->main_quit }), ]), ]), ); $w->main; 1; } sub choosePackagesTree { my ($o, $packages) = @_; my $available = install::any::getAvailableSpace($o); my $availableCorrected = install::pkgs::invCorrectSize($available / sqr(1024)) * sqr(1024); my $common; $common = { get_status => sub { my $size = install::pkgs::selectedSize($packages); N("Total size: %d / %d MB", install::pkgs::correctSize($size / sqr(1024)), $available / sqr(1024)); }, node_state => sub { my $p = install::pkgs::packageByName($packages, $_[0]) or return; !install::pkgs::packageMedium($packages, $p)->{ignore} or return; $p->arch eq 'src' and return; $p->flag_base and return 'base'; $p->flag_installed && !$p->flag_upgrade and return 'installed'; $p->flag_selected and return 'selected'; return 'unselected'; }, build_tree => sub { my ($add_node, $flat) = @_; if ($flat) { foreach (sort map { $_->name } grep { $_ && $_->arch ne 'src' } @{$packages->{depslist}}) { $add_node->($_, undef); } } else { foreach my $root (@{$o->{compssUsers}}) { my (@firstchoice, @others); my %fl = map { ("CAT_$_" => 1) } @{$root->{flags}}; foreach my $p (@{$packages->{depslist}}) { my @flags = $p->rflags; next if !($p->rate && any { any { !/^!/ && $fl{$_} } split('\|\|') } @flags); $p->rate >= 3 ? push(@firstchoice, $p->name) : push(@others, $p->name); } my $root2 = translate($root->{path}) . '|' . translate($root->{label}); $add_node->($_, $root2) foreach sort @firstchoice; $add_node->($_, $root2 . '|' . N("Other")) foreach sort @others; } } }, get_info => sub { my $p = install::pkgs::packageByName($packages, $_[0]) or return ''; my $imp = translate($install::pkgs::compssListDesc{$p->flag_base ? 5 : $p->rate}); my $tag = { 'foreground' => 'royalblue3' }; $@ ? N("Bad package") : [ [ N("Name: "), $tag ], [ $p->name . "\n" ], [ N("Version: "), $tag ], [ $p->version . '-' . $p->release . "\n" ], [ N("Size: "), $tag ], [ N("%d KB\n", $p->size / 1024) ], if_($imp, [ N("Importance: "), $tag ], [ "$imp\n" ]), [ "\n" ], [ formatLines($p->description) ] ]; }, toggle_nodes => sub { my $set_state = shift @_; my $isSelection = 0; my %l = map { my $p = install::pkgs::packageByName($packages, $_); $isSelection ||= !$p->flag_selected; $p->id => 1 } @_; my $state = $packages->{state} ||= {}; $packages->{rpmdb} ||= install::pkgs::rpmDbOpen(); #- WORKAROUND my @l = $isSelection ? $packages->resolve_requested($packages->{rpmdb}, $state, \%l, callback_choices => \&install::pkgs::packageCallbackChoices) : $packages->disable_selected($packages->{rpmdb}, $state, map { $packages->{depslist}[$_] } keys %l); my $size = install::pkgs::selectedSize($packages); my $error; if (!@l) { #- no package can be selected or unselected. my @ask_unselect = grep { $state->{rejected}{$_}{backtrack} && exists $l{$packages->search($_, strict_fullname => 1)->id} } keys %{$state->{rejected} || {}}; #- extend to closure (to given more detailed and not absurd reason). my %ask_unselect; while (@ask_unselect > keys %ask_unselect) { @ask_unselect{@ask_unselect} = (); foreach (keys %ask_unselect) { foreach (keys %{$state->{rejected}{$_}{backtrack}{closure} || {}}) { next if exists $ask_unselect{$_}; push @ask_unselect, $_; } } } $error = [ N("You can not select/unselect this package"), formatList(20, map { my $rb = $state->{rejected}{$_}{backtrack}; my @froms = keys %{$rb->{closure} || {}}; my @unsatisfied = @{$rb->{unsatisfied} || []}; my $s = join ", ", ((map { N("due to missing %s", $_) } @froms), (map { N("due to unsatisfied %s", $_) } @unsatisfied), $rb->{promote} && !$rb->{keep} ? N("trying to promote %s", join(", ", @{$rb->{promote}})) : @{[]}, $rb->{keep} ? N("in order to keep %s", join(", ", @{$rb->{keep}})) : @{[]}, ); $_ . ($s ? " ($s)" : ''); } sort @ask_unselect) ]; } elsif (install::pkgs::correctSize($size / sqr(1024)) > $available / sqr(1024)) { $error = N("You can not select this package as there is not enough space left to install it"); } elsif (@l > @_ && $common->{state}{auto_deps}) { $o->ask_okcancel(N("Confirmation"), [ $isSelection ? N("The following packages are going to be installed") : N("The following packages are going to be removed"), formatList(20, sort(map { $_->name } @l)) ], 1) or $error = ''; #- defined } if (defined $error) { $o->ask_warn('', $error) if $error; #- disable selection (or unselection). $packages->{rpmdb} ||= install::pkgs::rpmDbOpen(); #- WORKAROUND $isSelection ? $packages->disable_selected($packages->{rpmdb}, $state, @l) : $packages->resolve_requested($packages->{rpmdb}, $state, { map { $_->id => 1 } @l }); } else { #- keep the changes, update visible state. foreach (@l) { $set_state->($_->name, $_->flag_selected ? 'selected' : 'unselected'); } } }, grep_allowed_to_toggle => sub { grep { my $p = install::pkgs::packageByName($packages, $_); $p && !$p->flag_base } @_; }, grep_unselected => sub { grep { !install::pkgs::packageByName($packages, $_)->flag_selected } @_; }, check_interactive_to_toggle => sub { my $p = install::pkgs::packageByName($packages, $_[0]) or return; if ($p->flag_base) { $o->ask_warn('', N("This is a mandatory package, it can not be unselected")); } elsif ($p->flag_installed && !$p->flag_upgrade) { $o->ask_warn('', N("You can not unselect this package. It is already installed")); } elsif ($p->flag_selected && $p->flag_installed) { $o->ask_warn('', N("You can not unselect this package. It must be upgraded")); } else { return 1 } return; }, auto_deps => N("Show automatically selected packages"), interactive_help => sub { interactive::gtk::display_help($o, { interactive_help_id => 'choosePackages#choosePackagesTree' }, my $w) }, ok => N("Install"), cancel => N("Previous"), icons => [ { icon => 'floppy', help => N("Load/Save selection"), wait_message => N("Updating package selection"), code => sub { $o->loadSavePackagesOnFloppy($packages); 1 }, }, if_(0, { icon => 'feather', help => N("Minimal install"), code => sub { install::any::unselectMostPackages($o); install::pkgs::setSelectedFromCompssList($packages, { SYSTEM => 1 }, $o->{compssListLevel}, $availableCorrected); 1; } }), ], state => { auto_deps => 1, }, }; $o->ask_browse_tree_info(N("Software Management"), N("Choose the packages you want to install"), $common); } #------------------------------------------------------------------------------ sub beforeInstallPackages { my ($o) = @_; $o->SUPER::beforeInstallPackages; install::any::copy_advertising($o); } #------------------------------------------------------------------------------ sub installPackages { my ($o) = @_; my ($current_total_size, $last_size, $nb, $total_size, $last_dtime, $_trans_progress_total); local $::noborderWhenEmbedded = 1; my $w = ugtk2->new(N("Installing")); state $show_advertising; my $show_release_notes; my $pkg_log_widget = gtknew('TextView', editable => 0); my ($advertising_image, $change_time, $i); my $advertize = sub { my ($update) = @_; @install::any::advertising_images && $show_advertising && $update or return; $change_time = time(); my $f = $install::any::advertising_images[$i++ % @install::any::advertising_images]; log::l("advertising $f"); eval { gtkval_modify(\$advertising_image, $f) }; if (my $err = $@) { log::l("cannot load advertising image:\n" . formatError($err)); } if (my $banner = $w->{window}{banner}) { my ($title); my $pl = $f; $pl =~ s/\.png$/.pl/; eval(cat_($pl)) if -e $pl; $banner->{text} = $title; Gtk2::Banner::update_text($banner); } }; my $cancel = gtknew('Button', text => N("Cancel"), clicked => sub { $install::pkgs::cancel_install = 1 }); my $details = gtknew('Button', text_ref => \$show_advertising, format => sub { $show_advertising ? N("Details") : N("No details") }, clicked => sub { gtkval_modify(\$show_advertising, !$show_advertising); $pkg_log_widget->{to_bottom}->('force'); }); my $release_notes = any::get_release_notes($o); my $rel_notes = gtknew('Button', text => N("Release Notes"), clicked => sub { $show_release_notes = 1 }); ugtk2::gtkadd($w->{window}, my $box = gtknew('VBox', children_tight => [ gtknew('Image_using_pixmap', file_ref => \$advertising_image, show_ref => \$show_advertising), ])); $box->pack_end(gtkshow(gtknew('VBox', border_width => 7, spacing => 3, children_loose => [ gtknew('ScrolledWindow', child => $pkg_log_widget, hide_ref => \$show_advertising, height => 250, to_bottom => 1), gtknew('ProgressBar', fraction_ref => \ (my $pkg_progress), hide_ref => \$show_advertising), gtknew('HButtonBox', layout => 'start', children_loose => [ N("Time remaining:"), gtknew('Label', text_ref => \ (my $msg_time_remaining = N("(estimating...)"))), ]), gtknew('VBox', children_centered => [ gtknew('ProgressBar', fraction_ref => \ (my $progress_total), height => 25) ]), gtknew('HSeparator'), gtknew('HButtonBox', spacing => 0, layout => 'edge', children_loose => [ if_($release_notes, $rel_notes), gtknew('HButtonBox', spacing => 5, layout => 'end', children_loose => [ $cancel, $details ]), ]), ])), 0, 1, 0); #- for the hide_ref & show_ref to work, we must set $show_advertising after packing gtkval_modify(\$show_advertising, defined $show_advertising ? $show_advertising : to_bool(@install::any::advertising_images)); $details->hide if !@install::any::advertising_images; $w->sync; foreach ($cancel, $details) { gtkset_mousecursor_normal($_->window); } $advertize->(0); local *install::steps::installCallback = sub { my ($packages, $type, $id, $subtype, $amount, $total) = @_; if ($type eq 'user' && $subtype eq 'install') { #- $amount and $total are used to return number of package and total size. $nb = $amount; $total_size = $total; $current_total_size = 0; $o->{install_start_time} = 0; mygtk2::gtkadd($pkg_log_widget, text => P("%d package", "%d packages", $nb, $nb)); $w->flush; } elsif ($type eq 'open') { gtkval_modify(\$pkg_progress, 0); my $p = $packages->{depslist}[$id]; mygtk2::gtkadd($pkg_log_widget, text => sprintf("\n%s: %s", $p->name, translate($p->summary))); $current_total_size += $last_size; $last_size = $p->size; $advertize->(1) if $show_advertising && $total_size > 20_000_000 && time() - $change_time > 20; # display release notes if requested, when not chrooted: if ($show_release_notes) { undef $show_release_notes; any::run_display_release_notes($release_notes); $w->flush; } $w->flush; } elsif ($type eq 'inst' && $subtype eq 'progress') { $o->{install_start_time} = time() unless $o->{install_start_time}; gtkval_modify(\$pkg_progress, $total ? $amount / $total : 0); my $dtime = time() - $o->{install_start_time}; my $ratio = $total_size == 0 ? 0 : install::pkgs::size2time($current_total_size + $amount, $total_size) / install::pkgs::size2time($total_size, $total_size); $ratio >= 1 and $ratio = 1; my $total_time = $ratio ? $dtime / $ratio : time(); gtkval_modify(\$progress_total, $ratio); if ($dtime != $last_dtime && $current_total_size > 80_000_000) { gtkval_modify(\$msg_time_remaining, formatTime(10 * round(max($total_time - $dtime, 0) / 10) + 10)); $last_dtime = $dtime; } $w->flush; } }; my $install_result; catch_cdie { $install_result = $o->install::steps::installPackages('interactive') } sub { my $rc = install::steps_interactive::installPackages__handle_error($o, $_[0]); $rc or $w->destroy; $rc; }; if ($install::pkgs::cancel_install) { $install::pkgs::cancel_install = 0; die 'already displayed'; } $w->destroy; $install_result; } sub summary_prompt { my ($o, $l, $check_complete) = @_; my $w = ugtk2->new(N("Summary")); my $set_entry_labels; my (@table, @widget_list); my ($group, $count); foreach my $e (@$l) { if ($group ne $e->{group}) { push @widget_list, [ @table ] if @table; @table = (); push @widget_list, gtknew('HSeparator', height => 8) if $count; $count++; $group = $e->{group}; push @table, [ gtknew('HBox', children_tight => [ gtknew('Title1', label => mygtk2::asteriskize(escape_text_for_TextView_markup_format($group))) ]), '' ]; } $e->{widget} = gtknew('Label_Right', width => $::real_windowwidth * 0.72, alignment => [ 1, 1 ]); push @table, [], [ gtknew('HBox', children_tight => [ $e->{widget}, gtknew('Alignment', width => 10) ]), gtknew('Button', text => N("Configure"), clicked => sub { $w->{rwindow}->hide; my ($old_icon, $old_title) = get_default_step_items(); set_default_step_items($e->{banner_title} || $old_title); $e->{clicked}(); set_default_step_items($old_title); $w->{rwindow}->show; $set_entry_labels->(); }) ]; } # add latest group: push @widget_list, [ @table ] if @table; $set_entry_labels = sub { foreach (@$l) { my $t; if ($_->{val}) { $t = $_->{val}() || '' . N("not configured") . ''; $t =~ s/&/&/g; } gtkset($_->{widget}, text_markup => $_->{label} . ($t ? " - $t" : '')); } }; $set_entry_labels->(); my $help_sub = sub { interactive::gtk::display_help($o, { interactive_help_id => 'misc-params' }, $w) }; ugtk2::gtkadd($w->{window}, gtknew('VBox', spacing => 5, children => [ 1, gtknew('ScrolledWindow', h_policy => 'never', child => gtknew('TextView', text => [ [ gtknew('VBox', children_tight => [ map { ref($_) eq 'ARRAY' ? gtknew('Table', mcc => 1, row_spacings => 2, children => $_) : $_; } @widget_list ]) ] ])), 0, $w->create_okcancel(undef, '', '', if_($help_sub, [ gtknew('Install_Button', text => N("Help"), clicked => $help_sub), undef, 1 ])) ])); $w->{real_window}->show_all; # else widgets embedded in textview are hidden $w->main($check_complete); } #- group by CD sub ask_deselect_media__copy_on_disk { my ($o, $hdlists, $o_copy_rpms_on_disk) = @_; my @names = uniq(map { $_->{name} } @$hdlists); my %selection = map { $_->{name} => !$_->{ignore} } @$hdlists; if (@names > 1 || $o_copy_rpms_on_disk) { my $w = ugtk2->new(N("Media Selection")); $w->sync; ugtk2::gtkadd( $w->{window}, gtknew('VBox', children => [ @names > 1 ? ( 0, gtknew('Label_Left', padding => [ 0, 0 ], # workaround infamous 6 years old gnome bug #101968: width => mygtk2::get_label_width(), text => formatAlaTeX(N("The following installation media have been found. If you want to skip some of them, you can unselect them now."))), 1, gtknew('ScrolledWindow', child => gtknew('VBox', children => [ map { my $b = gtknew('CheckButton', text => $_, active_ref => \$selection{$_}); $b->set_sensitive(0) if $_ eq $names[0]; (0, $b); } @names ])), if_(@names <= 8, 1, ''), 0, gtknew('HSeparator'), ) : (), if_($o_copy_rpms_on_disk, 0, gtknew('Label_Left', padding => [ 0, 0 ], # workaround infamous 6 years old gnome bug #101968: width => mygtk2::get_label_width(), text => N("You have the option to copy the contents of the CDs onto the hard drive before installation. It will then continue from the hard drive and the packages will remain available once the system is fully installed.")), 0, gtknew('CheckButton', text => N("Copy whole CDs"), active_ref => $o_copy_rpms_on_disk), 1, gtknew('Alignment'), 0, gtknew('HSeparator'), ), 0, gtknew('HButtonBox', layout => 'edge', children_tight => [ gtknew('Install_Button', text => N("Help"), clicked => sub { interactive::gtk::display_help($o, { interactive_help_id => 'choosePackages' }, $w) }), gtknew('Button', text => N("Next"), clicked => sub { Gtk2->main_quit }), ]), ]), ); $w->main; } $_->{ignore} = !$selection{$_->{name}} foreach @$hdlists; log::l("keeping media " . join ',', map { $_->{rpmsdir} } grep { !$_->{ignore} } @$hdlists); } 1; 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870
package help;
use common;

1;

# IMPORTANT: Don't edit this File - It is automatically generated 
#            from the manuals !!! 
#            Write a mail to <documentation@mandrakesoft.com> if
#            you want it changed.
sub acceptLicense() {
    N("Before continuing, you should carefully read the terms of the license. It
covers the entire Mandrakelinux distribution. If you agree with all the
terms it contains, check the \"%s\" box. If not, clicking on the \"%s\"
button will reboot your computer.", N("Accept"), N("Quit"));
}
sub addUser() {
    N("GNU/Linux is a multi-user system which means each user can have his or her
own preferences, own files and so on. But unlike \"root\", who is the
system administrator, the users you add at this point won't be authorized
to change anything except their own files and their own configurations,
protecting the system from unintentional or malicious changes which could
impact on the system as a whole. You'll have to create at least one regular
user for yourself -- this is the account which you should use for routine,
day-to-day usage. Although it's very easy to log in as \"root\" to do
anything and everything, it may also be very dangerous! A very simple
mistake could mean that your system won't work any more. If you make a
serious mistake as a regular user, the worst that can happen is that you'll
lose some information, but you won't affect the entire system.

The first field asks you for a real name. Of course, this is not mandatory
-- you can actually enter whatever you like. DrakX will use the first word
you type in this field and copy it to the \"%s\" one, which is the name
this user will enter to log onto the system. If you like, you may override
the default and change the user name. The next step is to enter a password.
From a security point of view, a non-privileged (regular) user password is
not as crucial as the \"root\" password, but that's no reason to neglect it
by making it blank or too simple: after all, your files could be the ones
at risk.

Once you click on \"%s\", you can add other users. Add a user for each one
of your friends, your father, your sister, etc. Click \"%s\" when you're
finished adding users.

Clicking the \"%s\" button allows you to change the default \"shell\" for
that user (bash by default).

When you're finished adding users, you'll be asked to choose a user who
will be automatically logged into the system when the computer boots up. If
you're interested in that feature (and don't care much about local
security), choose the desired user and window manager, then click on
\"%s\". If you're not interested in this feature, uncheck the \"%s\" box.", N("User name"), N("Accept user"), N("Next"), N("Advanced"), N("Next"), N("Do you want to use this feature?"));
}
sub ask_mntpoint_s() {
    N("Listed here are the existing Linux partitions detected on your hard drive.
You can keep the choices made by the wizard, since they are good for most
common installations. If you make any changes, you must at least define a
root partition (\"/\"). Do not choose too small a partition or you will not
be able to install enough software. If you want to store your data on a
separate partition, you will also need to create a \"/home\" partition
(only possible if you have more than one Linux partition available).

Each partition is listed as follows: \"Name\", \"Capacity\".

\"Name\" is structured: \"hard drive type\", \"hard drive number\",
\"partition number\" (for example, \"hda1\").

\"Hard drive type\" is \"hd\" if your hard drive is an IDE hard drive and
\"sd\" if it is a SCSI hard drive.

\"Hard drive number\" is always a letter after \"hd\" or \"sd\". For IDE
hard drives:

 * \"a\" means \"master hard drive on the primary IDE controller\";

 * \"b\" means \"slave hard drive on the primary IDE controller\";

 * \"c\" means \"master hard drive on the secondary IDE controller\";

 * \"d\" means \"slave hard drive on the secondary IDE controller\".

With SCSI hard drives, an \"a\" means \"lowest SCSI ID\", a \"b\" means
\"second lowest SCSI ID\", etc.");
}
sub chooseCd() {
    N("The Mandrakelinux installation is distributed on several CD-ROMs. If a
selected package is located on another CD-ROM, DrakX will eject the current
CD and ask you to insert the required one. If you do not have the requested
CD at hand, just click on \"%s\", the corresponding packages will not be
installed.", N("Cancel"));
}
sub choosePackages() {
    N("It's now time to specify which programs you wish to install on your system.
There are thousands of packages available for Mandrakelinux, and to make it
simpler to manage, they have been placed into groups of similar
applications.

Mandrakelinux sorts package groups in four categories. You can mix and
match applications from the various categories, so a ``Workstation''
installation can still have applications from the ``Server'' category
installed.

 * \"%s\": if you plan to use your machine as a workstation, select one or
more of the groups in the workstation category.

 * \"%s\": if you plan on using your machine for programming, select the
appropriate groups from that category. The special \"LSB\" group will
configure your system so that it complies as much as possible with the
Linux Standard Base specifications.

   Selecting the \"LSB\" group will also install the \"2.4\" kernel series,
instead of the default \"2.6\" one. This is to ensure 100%%-LSB compliance
of the system. However, if you do not select the \"LSB\" group you will
still have a system which is nearly 100%% LSB-compliant.

 * \"%s\": if your machine is intended to be a server, select which of the
more common services you wish to install on your machine.

 * \"%s\": this is where you will choose your preferred graphical
environment. At least one must be selected if you want to have a graphical
interface available.

Moving the mouse cursor over a group name will display a short explanatory
text about that group.

You can check the \"%s\" box, which is useful if you're familiar with the
packages being offered or if you want to have total control over what will
be installed.

If you start the installation in \"%s\" mode, you can deselect all groups
and prevent the installation of any new packages. This is useful for
repairing or updating an existing system.

If you deselect all groups when performing a regular installation (as
opposed to an upgrade), a dialog will pop up suggesting different options
for a minimal installation:

 * \"%s\": install the minimum number of packages possible to have a
working graphical desktop.

 * \"%s\": installs the base system plus basic utilities and their
documentation. This installation is suitable for setting up a server.

 * \"%s\": will install the absolute minimum number of packages necessary
to get a working Linux system. With this installation you will only have a
command-line interface. The total size of this installation is about 65
megabytes.", N("Workstation"), N("Development"), N("Server"), N("Graphical Environment"), N("Individual package selection"), N("Upgrade"), N("With X"), N("With basic documentation"), N("Truly minimal install"));
}
sub choosePackagesTree() {
    N("If you choose to install packages individually, the installer will present
a tree containing all packages classified by groups and subgroups. While
browsing the tree, you can select entire groups, subgroups, or individual
packages.

Whenever you select a package on the tree, a description will appear on the
right to let you know the purpose of that package.

!! If a server package has been selected, either because you specifically
chose the individual package or because it was part of a group of packages,
you'll be asked to confirm that you really want those servers to be
installed. By default Mandrakelinux will automatically start any installed
services at boot time. Even if they are safe and have no known issues at
the time the distribution was shipped, it is entirely possible that
security holes were discovered after this version of Mandrakelinux was
finalized. If you don't know what a particular service is supposed to do or
why it's being installed, then click \"%s\". Clicking \"%s\" will install
the listed services and they will be started automatically at boot time. !!

The \"%s\" option is used to disable the warning dialog which appears
whenever the installer automatically selects a package to resolve a
dependency issue. Some packages depend on others and the installation of
one particular package may require the installation of another package. The
installer can determine which packages are required to satisfy a dependency
to successfully complete the installation.

The tiny floppy disk icon at the bottom of the list allows you to load a
package list created during a previous installation. This is useful if you
have a number of machines that you wish to configure identically. Clicking
on this icon will ask you to insert the floppy disk created at the end of
another installation. See the second tip of the last step on how to create
such a floppy.", N("No"), N("Yes"), N("Automatic dependencies"));
}
sub configurePrinter() {
    N("\"%s\": clicking on the \"%s\" button will open the printer configuration
wizard. Consult the corresponding chapter of the ``Starter Guide'' for more
information on how to set up a new printer. The interface presented in our
manual is similar to the one used during installation.", N("Printer"), N("Configure"));
}
sub configureServices() {
    N("This dialog is used to select which services you wish to start at boot
time.

DrakX will list all services available on the current installation. Review
each one of them carefully and uncheck those which aren't needed at boot
time.

A short explanatory text will be displayed about a service when it is
selected. However, if you're not sure whether a service is useful or not,
it is safer to leave the default behavior.

!! At this stage, be very careful if you intend to use your machine as a
server: you probably don't want to start any services which you don't need.
Please remember that some services can be dangerous if they're enabled on a
server. In general, select only those services you really need. !!");
}
sub configureTimezoneGMT() {
    N("GNU/Linux manages time in GMT (Greenwich Mean Time) and translates it to
local time according to the time zone you selected. If the clock on your
motherboard is set to local time, you may deactivate this by unselecting
\"%s\", which will let GNU/Linux know that the system clock and the
hardware clock are in the same time zone. This is useful when the machine
also hosts another operating system.

The \"%s\" option will automatically regulate the system clock by
connecting to a remote time server on the Internet. For this feature to
work, you must have a working Internet connection. We recommend that you
choose a time server located near you. This option actually installs a time
server which can be used by other machines on your local network as well.", N("Hardware clock set to GMT"), N("Automatic time synchronization"));
}
sub configureX_card_list() {
    N("Graphic Card

   The installer will normally automatically detect and configure the
graphic card installed on your machine. If this is not correct, you can
choose from this list the card you actually have installed.

   In the situation where different servers are available for your card,
with or without 3D acceleration, you're asked to choose the server which
best suits your needs.");
}
sub configureX_chooser() {
    N("X (for X Window System) is the heart of the GNU/Linux graphical interface
on which all the graphical environments (KDE, GNOME, AfterStep,
WindowMaker, etc.) bundled with Mandrakelinux rely upon.

You'll see a list of different parameters to change to get an optimal
graphical display.

Graphic Card

   The installer will normally automatically detect and configure the
graphic card installed on your machine. If this is not correct, you can
choose from this list the card you actually have installed.

   In the situation where different servers are available for your card,
with or without 3D acceleration, you're asked to choose the server which
best suits your needs.



Monitor

   Normally the installer will automatically detect and configure the
monitor connected to your machine. If it is not correct, you can choose
from this list the monitor which is connected to your computer.



Resolution

   Here you can choose the resolutions and color depths available for your
graphics hardware. Choose the one which best suits your needs (you will be
able to make changes after the installation). A sample of the chosen
configuration is shown in the monitor picture.



Test

   Depending on your hardware, this entry might not appear.

   The system will try to open a graphical screen at the desired
resolution. If you see the test message during the test and answer \"%s\",
then DrakX will proceed to the next step. If you do not see it, then it
means that some part of the auto-detected configuration was incorrect and
the test will automatically end after 12 seconds and return you to the
menu. Change settings until you get a correct graphical display.



Options

   This steps allows you to choose whether you want your machine to
automatically switch to a graphical interface at boot. Obviously, you may
want to check \"%s\" if your machine is to act as a server, or if you were
not successful in getting the display configured.", N("Yes"), N("No"));
}
sub configureX_monitor() {
    N("Monitor

   Normally the installer will automatically detect and configure the
monitor connected to your machine. If it is not correct, you can choose
from this list the monitor which is connected to your computer.");
}
sub configureX_resolution() {
    N("Resolution

   Here you can choose the resolutions and color depths available for your
graphics hardware. Choose the one which best suits your needs (you will be
able to make changes after the installation). A sample of the chosen
configuration is shown in the monitor picture.");
}
sub configureX_xfree_and_glx() {
    N("In the situation where different servers are available for your card, with
or without 3D acceleration, you're asked to choose the server which best
suits your needs.");
}
sub configureXxdm() {
    N("Options

   This steps allows you to choose whether you want your machine to
automatically switch to a graphical interface at boot. Obviously, you may
want to check \"%s\" if your machine is to act as a server, or if you were
not successful in getting the display configured.", N("No"));
}
sub doPartitionDisks() {
    N("You now need to decide where you want to install the Mandrakelinux
operating system on your hard drive. If your hard drive is empty or if an
existing operating system is using all the available space you will have to
partition the drive. Basically, partitioning a hard drive means to
logically divide it to create the space needed to install your new
Mandrakelinux system.

Because the process of partitioning a hard drive is usually irreversible
and can lead to data losses, partitioning can be intimidating and stressful
for the inexperienced user. Fortunately, DrakX includes a wizard which
simplifies this process. Before continuing with this step, read through the
rest of this section and above all, take your time.

Depending on the configuration of your hard drive, several options are
available:

 * \"%s\". This option will perform an automatic partitioning of your blank
drive(s). If you use this option there will be no further prompts.

 * \"%s\". The wizard has detected one or more existing Linux partitions on
your hard drive. If you want to use them, choose this option. You will then
be asked to choose the mount points associated with each of the partitions.
The legacy mount points are selected by default, and for the most part it's
a good idea to keep them.

 * \"%s\". If Microsoft Windows is installed on your hard drive and takes
all the space available on it, you will have to create free space for
GNU/Linux. To do so, you can delete your Microsoft Windows partition and
data (see ``Erase entire disk'' solution) or resize your Microsoft Windows
FAT or NTFS partition. Resizing can be performed without the loss of any
data, provided you've previously defragmented the Windows partition.
Backing up your data is strongly recommended. Using this option is
recommended if you want to use both Mandrakelinux and Microsoft Windows on
the same computer.

   Before choosing this option, please understand that after this
procedure, the size of your Microsoft Windows partition will be smaller
than when you started. You'll have less free space under Microsoft Windows
to store your data or to install new software.

 * \"%s\". If you want to delete all data and all partitions present on
your hard drive and replace them with your new Mandrakelinux system, choose
this option. Be careful, because you won't be able to undo this operation
after you confirm.

   !! If you choose this option, all data on your disk will be deleted. !!

 * \"%s\". This option appears when the hard drive is entirely taken by
Microsoft Windows. Choosing this option will simply erase everything on the
drive and begin fresh, partitioning everything from scratch.

   !! If you choose this option, all data on your disk will be lost. !!

 * \"%s\". Choose this option if you want to manually partition your hard
drive. Be careful -- it is a powerful but dangerous choice and you can very
easily lose all your data. That's why this option is really only
recommended if you have done something like this before and have some
experience. For more instructions on how to use the DiskDrake utility,
refer to the ``Managing Your Partitions'' section in the ``Starter Guide''.", N("Use free space"), N("Use existing partition"), N("Use the free space on the Windows partition"), N("Erase entire disk"), N("Remove Windows"), N("Custom disk partitioning"));
}
sub exitInstall() {
    N("There you are. Installation is now complete and your GNU/Linux system is
ready to be used. Just click on \"%s\" to reboot the system. Don't forget
to remove the installation media (CD-ROM or floppy). The first thing you
should see after your computer has finished doing its hardware tests is the
boot-loader menu, giving you the choice of which operating system to start.

The \"%s\" button shows two more buttons to:

 * \"%s\": enables you to create an installation floppy disk which will
automatically perform a whole installation without the help of an operator,
similar to the installation you've just configured.

   Note that two different options are available after clicking on that
button:

    * \"%s\". This is a partially automated installation. The partitioning
step is the only interactive procedure.

    * \"%s\". Fully automated installation: the hard disk is completely
rewritten, all data is lost.

   This feature is very handy when installing on a number of similar
machines. See the Auto install section on our web site for more
information.

 * \"%s\"(*): saves a list of the packages selected in this installation.
To use this selection with another installation, insert the floppy and
start the installation. At the prompt, press the [F1] key, type >>linux
defcfg=\"floppy\"<< and press the [Enter] key.

(*) You need a FAT-formatted floppy. To create one under GNU/Linux, type
\"mformat a:\", or \"fdformat /dev/fd0\" followed by \"mkfs.vfat
/dev/fd0\".", N("Reboot"), N("Advanced"), N("Generate auto-install floppy"), N("Replay"), N("Automated"), N("Save packages selection"));
}
sub formatPartitions() {
    N("If you chose to reuse some legacy GNU/Linux partitions, you may wish to
reformat some of them and erase any data they contain. To do so, please
select those partitions as well.

Please note that it's not necessary to reformat all pre-existing
partitions. You must reformat the partitions containing the operating
system (such as \"/\", \"/usr\" or \"/var\") but you don't have to reformat
partitions containing data that you wish to keep (typically \"/home\").

Please be careful when selecting partitions. After the formatting is
completed, all data on the selected partitions will be deleted and you
won't be able to recover it.

Click on \"%s\" when you're ready to format the partitions.

Click on \"%s\" if you want to choose another partition for your new
Mandrakelinux operating system installation.

Click on \"%s\" if you wish to select partitions which will be checked for
bad blocks on the disk.", N("Next"), N("Previous"), N("Advanced"));
}
sub installUpdates() {
    N("By the time you install Mandrakelinux, it's likely that some packages will
have been updated since the initial release. Bugs may have been fixed,
security issues resolved. To allow you to benefit from these updates,
you're now able to download them from the Internet. Check \"%s\" if you
have a working Internet connection, or \"%s\" if you prefer to install
updated packages later.

Choosing \"%s\" will display a list of web locations from which updates can
be retrieved. You should choose one near to you. A package-selection tree
will appear: review the selection, and press \"%s\" to retrieve and install
the selected package(s), or \"%s\" to abort.", N("Yes"), N("No"), N("Yes"), N("Install"), N("Cancel"));
}
sub miscellaneous() {
    N("At this point, DrakX will allow you to choose the security level you desire
for your machine. As a rule of thumb, the security level should be set
higher if the machine is to contain crucial data, or if it's to be directly
exposed to the Internet. The trade-off that a higher security level is
generally obtained at the expense of ease of use.

If you don't know what to choose, keep the default option. You'll be able
to change it later with the draksec tool, which is part of Mandrakelinux
Control Center.

Fill the \"%s\" field with the e-mail address of the person responsible for
security. Security messages will be sent to that address.", N("Security Administrator"));
}
sub partition_with_diskdrake() {
    N("At this point, you need to choose which partition(s) will be used for the
installation of your Mandrakelinux system. If partitions have already been
defined, either from a previous installation of GNU/Linux or by another
partitioning tool, you can use existing partitions. Otherwise, hard drive
partitions must be defined.

To create partitions, you must first select a hard drive. You can select
the disk for partitioning by clicking on ``hda'' for the first IDE drive,
``hdb'' for the second, ``sda'' for the first SCSI drive and so on.

To partition the selected hard drive, you can use these options:

 * \"%s\": this option deletes all partitions on the selected hard drive

 * \"%s\": this option enables you to automatically create ext3 and swap
partitions in the free space of your hard drive

\"%s\": gives access to additional features:

 * \"%s\": saves the partition table to a floppy. Useful for later
partition-table recovery if necessary. It is strongly recommended that you
perform this step.

 * \"%s\": allows you to restore a previously saved partition table from a
floppy disk.

 * \"%s\": if your partition table is damaged, you can try to recover it
using this option. Please be careful and remember that it doesn't always
work.

 * \"%s\": discards all changes and reloads the partition table that was
originally on the hard drive.

 * \"%s\": un-checking this option will force users to manually mount and
unmount removable media such as floppies and CD-ROMs.

 * \"%s\": use this option if you wish to use a wizard to partition your
hard drive. This is recommended if you do not have a good understanding of
partitioning.

 * \"%s\": use this option to cancel your changes.

 * \"%s\": allows additional actions on partitions (type, options, format)
and gives more information about the hard drive.

 * \"%s\": when you are finished partitioning your hard drive, this will
save your changes back to disk.

When defining the size of a partition, you can finely set the partition
size by using the Arrow keys of your keyboard.

Note: you can reach any option using the keyboard. Navigate through the
partitions using [Tab] and the [Up/Down] arrows.

When a partition is selected, you can use:

 * Ctrl-c to create a new partition (when an empty partition is selected)

 * Ctrl-d to delete a partition

 * Ctrl-m to set the mount point

To get information about the different file system types available, please
read the ext2FS chapter from the ``Reference Manual''.

If you are installing on a PPC machine, you will want to create a small HFS
``bootstrap'' partition of at least 1MB which will be used by the yaboot
bootloader. If you opt to make the partition a bit larger, say 50MB, you
may find it a useful place to store a spare kernel and ramdisk images for
emergency boot situations.", N("Clear all"), N("Auto allocate"), N("More"), N("Save partition table"), N("Restore partition table"), N("Rescue partition table"), N("Reload partition table"), N("Removable media auto-mounting"), N("Wizard"), N("Undo"), N("Toggle between normal/expert mode"), N("Done"));
}
sub resizeFATChoose() {
    N("More than one Microsoft partition has been detected on your hard drive.
Please choose the one which you want to resize in order to install your new
Mandrakelinux operating system.

Each partition is listed as follows: \"Linux name\", \"Windows name\"
\"Capacity\".

\"Linux name\" is structured: \"hard drive type\", \"hard drive number\",
\"partition number\" (for example, \"hda1\").

\"Hard drive type\" is \"hd\" if your hard dive is an IDE hard drive and