home *** CD-ROM | disk | FTP | other *** search
/ Inter.Net 55-2 / Inter.Net 55-2.iso / Mandrake / mdkinst / usr / bin / perl-install / install_steps_gtk.pm < prev    next >
Encoding:
Perl POD Document  |  2000-01-12  |  20.3 KB  |  877 lines

  1. package install_steps_gtk;
  2.  
  3.  
  4.  
  5.  
  6.  
  7. @ISA = qw(install_steps_interactive interactive_gtk);
  8.  
  9.  
  10.  
  11.  
  12. use common qw(:common :file :functional :system);
  13. use partition_table qw(:types);
  14. use my_gtk qw(:helpers :wrappers);
  15. use Gtk;
  16. #use Gtk::XmHTML;
  17. use devices;
  18. use fsedit;
  19. use modules;
  20. use install_steps;
  21. use install_steps_interactive;
  22. use interactive_gtk;
  23. use install_any;
  24. use diskdrake;
  25. use log;
  26. use help;
  27. use lang;
  28.  
  29.  
  30.  
  31.  
  32. my $w_help;
  33. my $itemsNB = 1;
  34. my (@background1, @background2);
  35. my ($width,       $height)       = (640,   480);
  36. my ($stepswidth,  $stepsheight)  = (140,   $height);
  37. my ($logowidth,   $logoheight)   = ($width - $stepswidth, 40);
  38. my ($helpwidth,   $helpheight)   = ($width - $stepswidth, 100);
  39. my ($windowwidth, $windowheight) = ($width - $stepswidth, $height - $helpheight - $logoheight);
  40.  
  41. my @themes_vga16 = qw(blue blackwhite savane);
  42. my @themes = qw(DarkMarble marble3d blueHeart);
  43.  
  44. my @circle_head = (
  45.     "19 17 4 1"
  46. );
  47.  
  48. my @circle_body = (
  49. " c None",
  50. "+ c #FFFFFF",
  51. "        =====      ",
  52. "      =========    ",
  53. "     =+++=======   ",
  54. "    =++==========  ",
  55. "   ==+============ ",
  56. "   +++============ ",
  57. "  ================o",
  58. "  ================o",
  59. "  ================o",
  60. "  ===============oo",
  61. "  ===============oo",
  62. "   =============oo ",
  63. "   ============ooo ",
  64. "    o=========ooo  ",
  65. "     oo=====oooo   ",
  66. "      ooooooooo    ",
  67. "        ooooo      ",
  68. );
  69.  
  70.  
  71.  
  72.  
  73.  
  74.  
  75.  
  76.  
  77.  
  78.  
  79.  
  80.  
  81.  
  82.  
  83.  
  84.  
  85.  
  86.  
  87.  
  88.  
  89.  
  90.  
  91.  
  92.  
  93.  
  94.  
  95.  
  96.  
  97.  
  98.  
  99.  
  100.  
  101.  
  102.  
  103.  
  104.  
  105.  
  106.  
  107.  
  108.  
  109.  
  110.  
  111.  
  112.  
  113.  
  114.  
  115.  
  116.  
  117.  
  118.  
  119.  
  120.  
  121.  
  122.  
  123.  
  124.  
  125.  
  126.  
  127.  
  128.  
  129.  
  130.  
  131.  
  132.  
  133.  
  134.  
  135.  
  136.  
  137.  
  138.  
  139.  
  140.  
  141.  
  142.  
  143.  
  144.  
  145.  
  146.  
  147.  
  148.  
  149.  
  150.  
  151.  
  152.  
  153.  
  154.  
  155.  
  156.  
  157.  
  158. my    @red_circle = (@circle_head, "= c #FF0000", "o c #AA5500", @circle_body);
  159. my @orange_circle = (@circle_head, "= c #FFAA00", "o c #AA5500", @circle_body);
  160. my  @green_circle = (@circle_head, "= c #00FF00", "o c #00AA00", @circle_body);
  161.  
  162.  
  163.  
  164.  
  165. sub new($$) {
  166.     my ($type, $o) = @_;
  167.  
  168.     my $old = $SIG{__DIE__};
  169.     $SIG{__DIE__} = sub { $_[0] !~ /my_gtk\.pm/ and goto $old };
  170.  
  171.     $ENV{DISPLAY} = $o->{display} || ":0";
  172.     unless ($::testing) {
  173.     $my_gtk::force_focus = $ENV{DISPLAY} eq ":0";
  174.  
  175.     my $f = "/tmp/Xconf";
  176.     createXconf($f, @{$o->{mouse}}{"XMOUSETYPE", "device"}, $o->{wacom});
  177.  
  178.     if ($ENV{DISPLAY} eq ":0") {
  179.         my $launchX = sub {
  180.         my $ok = 1;
  181.         local $SIG{CHLD} = sub { $ok = 0 };
  182.         unless (fork) {
  183.             exec $_[0], "-kb", "-dpms","-s" ,"240", "-allowMouseOpenFail", "-xf86config", $f or exit 1;
  184.         }
  185.         foreach (1..15) {
  186.             sleep 1;
  187.             return 0 if !$ok;
  188.             return 1 if c::Xtest($ENV{DISPLAY});
  189.         }
  190.         0;
  191.         };
  192.  
  193.          if (!$o->{vga16} && listlength(cat_("/proc/fb"))) {
  194.          &$launchX("XF86_FBDev");
  195.          $o->{allowFB} = 1; 
  196.          } else {
  197.         my $dir = "/usr/X11R6/bin";
  198.         unless (-x "$dir/XF86_VGA16") {
  199.             unlink "$dir/XF86_FBDev";
  200.             local *F; open F, ">$dir/XF86_VGA16" or die '';
  201.             local $/ = \ (16 * 1024);
  202.             my $f = install_any::getFile("$dir/XF86_VGA16") or die '';
  203.             syswrite F, $_ foreach <$f>;
  204.             chmod 0755, "$dir/XF86_VGA16";
  205.         }
  206.             &$launchX("XF86_VGA16");
  207.         }
  208.     }
  209.     }
  210.     @themes = @themes_vga16 if $o->{simple_themes} || !$o->{display} && !($o->{allowFB} ||= $::testing);
  211.  
  212.     install_theme($o);
  213.     create_logo_window($o);
  214.  
  215.     $my_gtk::force_center = [ $width - $windowwidth, $logoheight, $windowwidth, $windowheight ];
  216.  
  217.     (bless {}, ref $type || $type)->SUPER::new($o);
  218. }
  219.  
  220. sub enteringStep {
  221.     my ($o, $step) = @_;
  222.  
  223.     $o->SUPER::enteringStep($step);
  224.     create_steps_window($o);
  225.     create_help_window($o);
  226. }
  227. sub leavingStep {
  228.     my ($o, $step) = @_;
  229.     $o->SUPER::leavingStep($step);
  230. }
  231.  
  232.  
  233.  
  234.  
  235.  
  236.  
  237. sub selectLanguage {
  238.     my ($o) = @_;
  239.     $o->SUPER::selectLanguage;
  240.     Gtk->set_locale;
  241.     install_theme($o);
  242. }
  243.  
  244.  
  245. sub doPartitionDisks($$) {
  246.     my ($o, $hds, $raid) = @_;
  247.  
  248.     if (!$::isStandalone && fsedit::is_one_big_fat($hds)) {
  249.     
  250.     my $min_linux = 600 << 11;
  251.     my $max_linux = 1500 << 11;
  252.     my $min_freewin = 300 << 11;
  253.  
  254.     my ($part) = fsedit::get_fstab(@{$o->{hds}});
  255.     my $w = $o->wait_message(_("Resizing"), _("Computing fat filesystem bounds"));
  256.     my $resize_fat = eval { resize_fat::main->new($part->{device}, devices::make($part->{device})) };
  257.     my $min_win = $resize_fat->min_size;
  258.     if (!$@ && $part->{size} > $min_linux + $min_freewin + $min_win && $o->ask_okcancel('',
  259. _("WARNING!
  260.  
  261. DrakX now needs to resize your Windows partition. Be careful: this operation is
  262. dangerous. If you have not already done so, you should first exit the
  263. installation, run scandisk under Windows (and optionally run defrag), then
  264. restart the installation. You should also backup your data.
  265. When sure, press Ok."))) {
  266.         my $hd = $hds->[0];
  267.         my $oldsize = $part->{size};
  268.         $hd->{isDirty} = $hd->{needKernelReread} = 1;
  269.         $part->{size} -= min($max_linux, $part->{size} - $min_win);
  270.         partition_table::adjustEnd($hd, $part);
  271.         partition_table::adjust_local_extended($hd, $part);
  272.         partition_table::adjust_main_extended($hd);
  273.  
  274.         local *log::l = sub { $w->set(join(' ', @_)) };
  275.         eval { $resize_fat->resize($part->{size}) };
  276.         if ($@) {
  277.         $part->{size} = $oldsize;
  278.         $o->ask_warn('', _("Automatic resizing failed"));
  279.         } else {
  280.         $part->{isFormatted} = 1;
  281.         eval { fsedit::auto_allocate($hds, $o->{partitions}) };
  282.         if (!$@) {
  283.             partition_table::write($hd) unless $::testing;
  284.             return;
  285.         }
  286.         }
  287.     }
  288.     }
  289.  
  290.     while (1) {
  291.     diskdrake::main($hds, $raid, interactive_gtk->new, $o->{partitions});
  292.     if (!grep { isSwap($_) } fsedit::get_fstab(@{$o->{hds}})) {
  293.         if ($::beginner) {
  294.         $o->ask_warn('', _("You must have a swap partition"));
  295.         } elsif (!$::expert) {
  296.         $o->ask_okcancel('', _("You don't have a swap partition\n\nContinue anyway?")) and last;
  297.         } else { last }
  298.     } else { last }
  299.     }
  300. }
  301.  
  302.  
  303. sub chooseSizeToInstall {
  304.     my ($o, $packages, $min_size, $max_size) = @_;
  305.     my ($min, $max) = map { pkgs::correctSize($_ / sqr(1024)) } $min_size, $max_size;
  306.     log::l("choosing size to install between $min and $max (really between $min_size and $max_size)");
  307.     my $w = my_gtk->new('');
  308.     my $adj = create_adjustment($max, $min, $max);
  309.     my $spin = gtkset_usize(new Gtk::SpinButton($adj, 0, 0), 100, 0);
  310.  
  311.     gtkadd($w->{window},
  312.       gtkpack(new Gtk::VBox(0,20),
  313. _("Now that you've selected desired groups, please choose 
  314. how many packages you want, ranging from minimal to full 
  315. installation of each selected groups.") .
  316.           ($::expert ? "\n" . _("You will be able to choose more precisely in next step") : ''),
  317.          create_packtable({ col_spacings => 10 },
  318.                   [ _("Choose the size you want to install"), $spin, _("MB"), ],
  319.                   [ undef, new Gtk::HScrollbar($adj) ],
  320.                    ),
  321.          create_okcancel($w)
  322.         )
  323.      );
  324.     $spin->signal_connect(activate => sub { $w->{retval} = 1; Gtk->main_quit });
  325.     $spin->grab_focus();
  326.     $w->main and pkgs::invCorrectSize($spin->get_value_as_int) * sqr(1024);
  327. }
  328. sub choosePackagesTree {
  329.     my ($o, $packages, $compss) = @_;
  330.     my $availableSpace = int(install_any::getAvailableSpace($o) / sqr(1024));
  331.     my $w = my_gtk->new('');
  332.     add2hash_($o->{packages_}, { show_level => 0 }); 
  333.  
  334.     my ($current, $ignore, $showall, $selectall, $w_size, $info_widget, $showall_button, $selectall_button, $go, %items) = 0, 0, 0, 0;
  335.     my $details = new Gtk::VBox(0,0);
  336.     $compss->{tree} = new Gtk::Tree();
  337.     $compss->{tree}->set_selection_mode('multiple');
  338.  
  339.     my $clean; $clean = sub {
  340.     my ($p) = @_;
  341.     foreach (values %{$p->{childs}}) {
  342.         &$clean($_) if $_->{childs};
  343.         delete $_->{itemNB};
  344.         delete $_->{tree};
  345.         delete $_->{packages_item};
  346.     }
  347.     }; &$clean($compss);
  348.  
  349.     my $update = sub {
  350.     my $size = 0;
  351.     $ignore = 1;
  352.     foreach (grep { $_->[0] } values %items) {
  353.         $compss->{tree}->unselect_child($_->[0]);
  354.         $compss->{tree}->select_child($_->[0]) if $_->[1]{selected};
  355.     }
  356.     $ignore = 0;
  357.     
  358.     foreach (values %$packages) {
  359.         $size += $_->{size} - ($_->{installedCumulSize} || 0) if $_->{selected}; 
  360.     }
  361.  
  362.     $w_size->set(_("Total size: ") . int (pkgs::correctSize($size / sqr(1024))) . " / $availableSpace " . _("MB") );
  363.     };
  364.     my $new_item = sub {
  365.     my ($p, $name, $parent) = @_;
  366.     my $w = create_treeitem($name);
  367.     $items{++$itemsNB} = [ $w, $p ];
  368.     undef $parent->{packages_item}{$itemsNB} if $parent;
  369.     $w->show;
  370.     $w->set_sensitive(!$p->{base} && !$p->{installed});
  371.     $w->signal_connect(focus_in_event => sub {
  372.         my $p = eval { pkgs::getHeader($p) };
  373.         gtktext_insert($info_widget, $@ ? _("Bad package") :
  374.                _("Version: %s\n", c::headerGetEntry($p, 'version') . '-' . c::headerGetEntry($p, 'release')) .
  375.                _("Size: %d KB\n", c::headerGetEntry($p, 'size') / 1024) .
  376.  
  377.                formatLines(c::headerGetEntry($p, 'description')));
  378.     }) unless $p->{childs};
  379.     $itemsNB;
  380.     };
  381.  
  382.     $compss->{tree}->signal_connect(selection_changed => sub {
  383.     $ignore and return;
  384.  
  385.     my %s; @s{$_[0]->selection} = ();
  386.     my @changed;
  387.     
  388.     
  389.     foreach (values %items) {
  390.         push @changed, $_->[1] if ($_->[1]{selected} xor exists $s{$_->[0]});
  391.     }
  392.     
  393.     foreach (@changed) {
  394.         if ($_->{childs}) {
  395.         my $s = invbool \$_->{selected};
  396.         my $f; $f = sub {
  397.             my ($p) = @_;
  398.             $p->{itemNB} or return;
  399.             if ($p->{packages}) {
  400.             foreach (keys %{$p->{packages_item} || {}}) {
  401.                 my ($a, $b) = @{$items{$_}};
  402.                 $a and pkgs::set($packages, $b, $s);
  403.             }
  404.             } else {
  405.             foreach (values %{$p->{childs}}) {
  406.                 $_->{selected} = $s;
  407.                 &$f($_);
  408.             }
  409.             }
  410.         }; &$f($_);
  411.  
  412.  
  413.  
  414.  
  415.         } else {
  416.         pkgs::toggle($packages, $_);        
  417.         }
  418.     }
  419.     &$update();
  420.     });
  421.  
  422.  
  423.  
  424.  
  425.  
  426.  
  427.  
  428.  
  429.  
  430.  
  431.  
  432.  
  433.  
  434.     my $show_add = sub {
  435.     my ($ind, $level) = @{$o->{packages_}}{"ind", "show_level"};
  436.     $level = max(0, min(90, ($level + $_[0])));
  437.     $o->{packages_}{show_level} = $level;
  438.  
  439.     my $update_tree = sub {
  440.         my $P = shift;
  441.         my $i = 0; foreach (@_) {
  442.         my ($flag, $itemNB, $q) = @$_;
  443.         my $item = $items{$flag || $itemNB}[0] if $flag || $itemNB;
  444.         if ($flag) {
  445.             $P->{tree}->insert($item, $i) if $flag ne "1";
  446.             $item->set_subtree($q->{tree}) if $flag ne "1" && $q->{tree};
  447.             $i++;
  448.         } elsif ($itemNB) {
  449.             delete $items{$itemNB};
  450.             delete $P->{packages_item}{$itemNB};
  451.             $P->{tree}->remove_item($item) if $P->{tree};
  452.         }
  453.         }
  454.     };
  455.     my $f; $f = sub {
  456.         my ($p) = @_;
  457.         if ($p->{packages}) {
  458.         my %l; $l{$items{$_}[1]} = $_ foreach keys %{$p->{packages_item}};
  459.         map {
  460.             [ $_->{values}[$ind] >= $level ?
  461.               ($l{$_} ? 1 : &$new_item($_, $_->{name}, $p)) : '', $l{$_}, $_ ];
  462.         } sort { 
  463.             $a->{name} cmp $b->{name} } @{$p->{packages}};
  464.         } else {
  465.         map {
  466.             my $P = $p->{childs}{$_};
  467.             my @L; @L = &$f($P) if !$P->{values} || $P->{values}[$ind] > ($::expert ? -1 : 0);
  468.             if (grep { $_->[0] } @L) {
  469.             my $r = $P->{tree} ? 1 : do {
  470.                 my $t = $P->{tree} = new Gtk::Tree(); $t->show;
  471.                 $P->{itemNB} = &$new_item($P, $_);
  472.             };
  473.             &$update_tree($P, @L);
  474.             [ $r, $P->{itemNB}, $P ];
  475.             } else {
  476.             &$update_tree($P, @L);
  477.             delete $P->{tree};
  478.             [ '', delete $P->{itemNB}, $P ];
  479.             }
  480.         } sort keys %{$p->{childs} || {}};
  481.         }
  482.     };
  483.     $ignore = 1;
  484.     &$update_tree($compss, &$f($compss));
  485.     &$update;
  486.     $ignore = 0;
  487.     };
  488.  
  489.     gtkadd($w->{window}, gtkpack_(new Gtk::VBox(0,5),
  490.                   0, _("Choose the packages you want to install"),
  491.                   1, gtkpack(new Gtk::HBox(0,0),
  492.                          createScrolledWindow($compss->{tree}),
  493.                          gtkadd(gtkset_usize(new Gtk::Frame(_("Info")), 150, 0),
  494.                             createScrolledWindow($info_widget = new Gtk::Text),
  495.                            ),
  496.                          ),
  497.                  0, gtkpack_(new Gtk::HBox(0,0), 0, $w_size = new Gtk::Label('')),
  498.                  0, gtkpack(new Gtk::HBox(0,10),
  499.                         map { $go ||= $_; $_ }
  500.                         map { gtksignal_connect(new Gtk::Button($_->[0]), "clicked" => $_->[1]) }
  501.                         [ _("Install") => sub { $w->{retval} = 1; Gtk->main_quit } ],
  502.                         
  503.                         
  504.                        )
  505.     ));
  506.     $w->{window}->set_usize(map { $_ - 2 * $my_gtk::border - 4 } $windowwidth, $windowheight);
  507.     $w->show;
  508.     &$show_add(0);
  509.     &$update();
  510.     $go->grab_focus;
  511.     $w->main;
  512. }
  513.  
  514.  
  515. sub installPackages {
  516.     my ($o, $packages) = @_;
  517.  
  518.     my ($current_total_size, $last_size, $nb, $total_size, $start_time, $last_dtime, $trans_progress_total);
  519.  
  520.     my $w = my_gtk->new(_("Installing"), grab => 1);
  521.     $w->{window}->set_usize($windowwidth * 0.8, $windowheight * 0.5);
  522.     my $text = new Gtk::Label;
  523.     my ($msg, $msg_time_remaining, $msg_time_total) = map { new Gtk::Label($_) } '', (_("Estimating")) x 2;
  524.     my ($progress, $progress_total) = map { new Gtk::ProgressBar } (1..2);
  525.     gtkadd($w->{window}, gtkadd(new Gtk::EventBox,
  526.                 gtkpack(new Gtk::VBox(0,10),
  527.                    _("Please wait, "), $msg, $progress,
  528.                    create_packtable({},
  529.                         [_("Time remaining "), $msg_time_remaining],
  530.                         [_("Total time "), $msg_time_total],
  531.                         ),
  532.                    $text,
  533.                    $progress_total,
  534.                   )));
  535.     $msg->set(_("Preparing installation"));
  536.     $w->sync;
  537.  
  538.     my $old = \&pkgs::installCallback;
  539.     local *pkgs::installCallback = sub {
  540.     my $m = shift;
  541.     if ($m =~ /^Starting installation/) {
  542.         $nb = $_[0];
  543.         $total_size = $_[1]; $current_total_size = 0;
  544.         $start_time = time();
  545.         $msg->set(_("%d packages", $nb) . _(", %U MB", pkgs::correctSize($total_size / sqr(1024))));
  546.         $w->flush;
  547.     } elsif ($m =~ /^Starting installing package/) {
  548.         $progress->update(0);
  549.         my $name = $_[0];
  550.         $msg->set(_("Installing package %s", $name));
  551.         $current_total_size += $last_size;
  552.         $last_size = c::headerGetEntry($o->{packages}{$name}{header}, 'size');
  553.         $text->set((split /\n/, c::headerGetEntry($o->{packages}{$name}{header}, 'summary'))[0] || '');
  554.         $w->flush;
  555.     } elsif ($m =~ /^Progressing installing package/) {
  556.         $progress->update($_[2] ? $_[1] / $_[2] : 0);
  557.  
  558.         my $dtime = time() - $start_time;
  559.         my $ratio = $total_size ? ($_[1] + $current_total_size) / $total_size : 0;
  560.         my $total_time = $ratio ? $dtime / $ratio : time();
  561.  
  562.         $progress_total->update($ratio);
  563.         if ($dtime != $last_dtime && $current_total_size > 2 * 1024 * 1024) {
  564.         $msg_time_total->set(formatTime(10 * round($total_time / 10)));
  565.         $msg_time_remaining->set(formatTime(10 * round(max($total_time - $dtime, 0) / 10)));
  566.         $last_dtime = $dtime;
  567.         }
  568.         $w->flush;
  569.     } else { unshift @_, $m; goto $old }
  570.     };
  571.     catch_cdie { $o->install_steps::installPackages($packages); }
  572.       sub {
  573.       if ($@ =~ /^error ordering package list: (.*)/) {
  574.           $o->ask_yesorno('', [
  575. _("There was an error ordering packages:"), $1, _("Go on anyway?") ], 1) and return 1;
  576.           ${$_[0]} = "already displayed";
  577.       }
  578.       0;
  579.       };
  580.     $w->destroy;
  581. }
  582.  
  583.  
  584. sub load_rc($) {
  585.     if (my ($f) = grep { -r $_ } map { "$_/$_[0].rc" } (".", "/usr/share", dirname(__FILE__))) {
  586.     Gtk::Rc->parse($f);
  587.     foreach (cat_($f)) {
  588.         if (/style\s+"background"/ .. /^\s*$/) {
  589.         @background1 = map { $_ * 256 * 256 } split ',', $1 if /NORMAL.*\{(.*)\}/;
  590.         @background2 = map { $_ * 256 * 256 } split ',', $1 if /PRELIGHT.*\{(.*)\}/;
  591.         }
  592.     }
  593.     }
  594. }
  595.  
  596. sub install_theme {
  597.     my ($o, $theme) = @_;    
  598.     $o->{theme} = $theme || $o->{theme} || $themes[0];
  599.  
  600.     gtkset_mousecursor(68);
  601.  
  602.     load_rc($_) foreach "themes-$o->{theme}", "install", "themes";
  603.  
  604.     if (my ($font, $font2) = lang::get_x_fontset($o->{lang})) {
  605.     $font2 ||= $font;
  606.     Gtk::Rc->parse_string(qq(
  607. style "default-font" 
  608. {
  609.    fontset = "$font"
  610. }
  611. style "steps"
  612. {
  613.    fontset = "$font2"
  614. }
  615. widget "*" style "default-font"
  616. widget "*Steps*" style "steps"
  617.  
  618. ));
  619.    }
  620.     gtkset_background(@background1);# unless $::testing;
  621.  
  622.     create_logo_window($o);
  623.     create_help_window($o);
  624. }
  625.  
  626.  
  627. sub create_help_window {
  628.     my ($o) = @_;
  629.  
  630. #    $o->{help_window}->destroy if $o->{help_window};
  631.  
  632.     my $w;
  633.     if ($w = $o->{help_window}) {
  634.     $_->destroy foreach $w->{window}->children;
  635.     } else {
  636.     $w = bless {}, 'my_gtk';
  637.     $w->{rwindow} = $w->{window} = new Gtk::Window;
  638.     $w->{rwindow}->set_uposition($width - $helpwidth, $height - $helpheight);
  639.     $w->{rwindow}->set_usize($helpwidth, $helpheight);
  640.     $w->sync;
  641.     }
  642.  
  643.  
  644.  
  645.  
  646.  
  647.  
  648.  
  649.  
  650.  
  651.  
  652.  
  653.  
  654.  
  655.  
  656.  
  657.  
  658.  
  659.  
  660.  
  661.  
  662. #    Gtk::XmHTML->init;
  663.     gtkadd($w->{window},
  664.        gtkpack_(new Gtk::HBox(0,-2),
  665.  
  666.  
  667.             1, createScrolledWindow($w_help = new Gtk::Text)));
  668.  
  669.     gtktext_insert($w_help, $o->{step} ? formatAlaTeX(translate($help::steps{$o->{step}})) : '');
  670.  
  671.     $w->show;
  672.     $o->{help_window} = $w;
  673. }
  674.  
  675. sub set_help { 
  676.     shift;
  677.     gtktext_insert($w_help, 
  678.            formatAlaTeX(join "\n", 
  679.                 map { translate($help::steps{$_}) } @_));
  680.     1;
  681. }
  682.  
  683.  
  684. sub create_steps_window {
  685.     my ($o) = @_;
  686.  
  687.     $o->{steps_window}->destroy if $o->{steps_window};
  688.     my %reachableSteps if 0;
  689.     %reachableSteps = ();
  690.  
  691.     my $w = bless {}, 'my_gtk';
  692.     $w->{rwindow} = $w->{window} = new Gtk::Window;
  693.     $w->{rwindow}->set_uposition(0, 0);
  694.     $w->{rwindow}->set_usize($stepswidth, $stepsheight);
  695.     $w->{rwindow}->set_name("Steps");
  696.     $w->{rwindow}->set_events('button_press_mask');
  697.     $w->{rwindow}->signal_connect(button_press_event => sub {
  698.     $::setstep or return;
  699.         my $Y = $_[1]{'y'};
  700.     map_each {
  701.         my (undef, $y, undef, $height) = @{$::b->allocation};
  702.         $y <= $Y && $Y < $y + $height and die "setstep $::a\n";
  703.     } %reachableSteps;
  704.     });
  705.     $w->show;
  706.  
  707.     gtkadd($w->{window},
  708.        gtkpack_(new Gtk::VBox(0,0),
  709.             (map { 1, $_ } map {
  710.             my $step = $o->{steps}{$_};
  711.             my $circle =
  712.               $step->{done}    && \@green_circle  ||
  713.               $step->{entered} && \@orange_circle ||
  714.               \@red_circle;
  715.             my @pixmap = Gtk::Gdk::Pixmap->create_from_xpm_d($w->{window}->window, undef, @$circle);
  716.  
  717.             my $w = new Gtk::Label(translate($step->{text}));
  718.  
  719.             $w->set_name("Steps" . ($step->{reachable} && "Reachable"));
  720.             my $b = new Gtk::HBox(0,5);
  721.             gtkpack_($b, 0, new Gtk::Pixmap(@pixmap), 0, $w);
  722.  
  723.             $reachableSteps{$_} = $b if $step->{reachable};
  724.             $b;
  725.             } grep {
  726.             local $_ = $o->{steps}{$_}{hidden};
  727.             /^$/ or $o->{installClass} and /beginner/ && !$::beginner || /!expert/ && $::expert
  728.             } @{$o->{orderedSteps}}),
  729.             0, gtkpack(new Gtk::HBox(0,0), map {
  730.             my $t = $_;
  731.             my $w = new Gtk::Button('');
  732.             $w->set_name($t);
  733.             $w->set_usize(0, 7);
  734.             gtksignal_connect($w, clicked => sub { 
  735.                 $::setstep or return; 
  736.                 install_theme($o, $t); die "theme_changed\n" 
  737.             });
  738.             } @themes)));
  739.     $w->show;
  740.     $o->{steps_window} = $w;
  741. }
  742.  
  743.  
  744. sub create_logo_window() {
  745.     my ($o) = @_;
  746.     gtkdestroy($o->{logo_window});
  747.     my $w = bless {}, 'my_gtk';
  748.     $w->{rwindow} = $w->{window} = new Gtk::Window;
  749.     $w->{rwindow}->set_uposition($stepswidth, 0);
  750.     $w->{rwindow}->set_usize($logowidth, $logoheight);
  751.     $w->{rwindow}->set_name("background");
  752.     $w->show;
  753.     my $file = "logo-mandrake.xpm";
  754.     -r $file or $file = "/usr/share/$file";
  755.     if (-r $file) {
  756.     my $ww = $w->{window};
  757.     my @logo = Gtk::Gdk::Pixmap->create_from_xpm($ww->window, $ww->style->bg('normal'), $file);
  758.     gtkadd($ww, new Gtk::Pixmap(@logo));
  759.     }
  760.     $o->{logo_window} = $w;
  761. }
  762.  
  763.  
  764. sub createXconf($$$) {
  765.     my ($file, $mouse_type, $mouse_dev, $wacom_dev) = @_;
  766.     $mouse_type ||= "Microsoft";
  767.     $mouse_dev = devices::make($mouse_dev || "ttyS0");
  768.  
  769.     my $wacom;
  770.     if ($wacom_dev) {
  771.     $wacom_dev = devices::make($wacom_dev);
  772.     $wacom = <<END;
  773. Section "Module"
  774.    Load "xf86Wacom.so"
  775. EndSection
  776.  
  777. Section "XInput"
  778.     SubSection "WacomStylus"
  779.         Port "$wacom_dev"
  780.         AlwaysCore
  781.     EndSubSection
  782.     SubSection "WacomCursor"
  783.         Port "$wacom_dev"
  784.         AlwaysCore
  785.     EndSubSection
  786.     SubSection "WacomEraser"
  787.         Port "$wacom_dev"
  788.         AlwaysCore
  789.     EndSubSection
  790. EndSection
  791. END
  792.     }
  793.  
  794.     local *F;
  795.     open F, ">$file" or die "can't create X configuration file $file";
  796.     print F <<END;
  797. Section "Files"
  798.    FontPath   "/usr/X11R6/lib/X11/fonts:unscaled,/usr/X11R6/lib/X11/fonts"
  799. EndSection
  800.  
  801. Section "Keyboard"
  802.    Protocol    "Standard"
  803.    AutoRepeat  0 0
  804.  
  805.    LeftAlt         Meta
  806.    RightAlt        Meta
  807.    ScrollLock      Compose
  808.    RightCtl        Control
  809. EndSection
  810.  
  811. Section "Pointer"
  812.    Protocol    "$mouse_type"
  813.    Device      "$mouse_dev"
  814.    Emulate3Buttons
  815.    Emulate3Timeout    50
  816. EndSection
  817.  
  818. $wacom
  819.  
  820. Section "Monitor"
  821.    Identifier  "My Monitor"
  822.    VendorName  "Unknown"
  823.    ModelName   "Unknown"
  824.    HorizSync   31.5-35.5
  825.    VertRefresh 50-70
  826.    Modeline "640x480"     25.175 640  664  760  800   480  491  493  525
  827.    Modeline "640x480"     28.3   640  664  760  800   480  491  493  525
  828. EndSection
  829.  
  830.  
  831. Section "Device"
  832.    Identifier "Generic VGA"
  833.    VendorName "Unknown"
  834.    BoardName "Unknown"
  835.    Chipset "generic"
  836. EndSection
  837.  
  838.  
  839. Section "Screen"
  840.     Driver "svga"
  841.     Device      "Generic VGA"
  842.     Monitor     "My Monitor"
  843.     Subsection "Display"
  844.         Modes       "640x480"
  845.         ViewPort    0 0
  846.     EndSubsection
  847. EndSection
  848.  
  849. Section "Screen"
  850.     Driver      "vga16"
  851.     Device      "Generic VGA"
  852.     Monitor     "My Monitor"
  853.     Subsection "Display"
  854.         Modes       "640x480"
  855.         ViewPort    0 0
  856.     EndSubsection
  857. EndSection
  858.  
  859. Section "Screen"
  860.     Driver      "fbdev"
  861.     Device      "Generic VGA"
  862.     Monitor     "My Monitor"
  863.     Subsection "Display"
  864.         Depth       16
  865.         Modes       "default"
  866.         ViewPort    0 0
  867.     EndSubsection
  868. EndSection
  869. END
  870.  
  871. }
  872.  
  873.  
  874.  
  875.  
  876. 1; #
  877.