/[soft]/control-center/trunk/control-center
ViewVC logotype

Contents of /control-center/trunk/control-center

Parent Directory Parent Directory | Revision Log Revision Log


Revision 2350 - (show annotations) (download)
Sat Dec 10 07:48:47 2011 UTC (12 years, 4 months ago) by tv
File size: 58637 byte(s)
further update Release Notes URL
1 #!/usr/bin/perl
2 # $Id: control-center 269021 2010-05-19 16:37:57Z eugeni $
3
4 # Copyright (C) 1999-2008 Mandriva
5 # Daouda Lo
6 # Damien Krotkine
7 # Thierry Vignaud <tvignaud@mandriva.com>
8 # Yves Duret
9 #
10 # This program is free software; you can redistribute it and/or modify it under
11 # the terms of the GNU General Public License as published by the Free Software
12 # Foundation; either version 2, or (at your option) any later version.
13 #
14 # This program is distributed in the hope that it will be useful,
15 # but WITHOUT ANY WARRANTY; without even the implied warranty of
16 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 # GNU General Public License for more details.
18 #
19 # You should have received a copy of the GNU General Public License
20 # along with this program; if not, write to the Free Software
21 # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
22
23
24 use strict;
25 use diagnostics;
26 use lib qw(/usr/lib/libDrakX);
27 use c;
28 use standalone;
29 use common;
30 use detect_devices;
31 use lang;
32
33 # i18n: IMPORTANT: to get correct namespace (drakconf instead of libDrakX)
34 BEGIN { unshift @::textdomains, 'drakconf' }
35 use mygtk2 qw(gtknew);
36 use ugtk2 qw(:create :dialogs :helpers :wrappers);
37 use Gtk2::WebKit;
38
39 use MDV::Control_Center;
40
41
42 my (%tool_pids, %tool_feedback, $gurpmi_pid);
43
44 my ($conffile, $class_install) = ('/etc/mcc.conf', '/etc/sysconfig/system');
45
46 my ($rootwin_width, $rootwin_height) = gtkroot()->get_size;
47 my $default_width = $rootwin_width <= 800 ? 720 : 800;
48 my $default_height = $rootwin_height <= 480 ? 420 : $rootwin_height <= 600 ? 523 : 600;
49
50 my $min_width = $rootwin_width == 640 ? 620 : 680;
51 my $min_height = $rootwin_height == 480 ? 420 : 500;
52
53 require_root_capability() if !$::testing; # just to get root capabilities
54
55
56 #-------------------------------------------------------------
57 # read configuration, set themes, ...
58 my %h = getVarsFromSh($conffile);
59 my %class = getVarsFromSh($class_install);
60 $h{THEME} ||= 'default';
61 $h{LOGS} ||= bool2text($class{CLASS} eq 'expert' ? 1 : 0);
62 $h{EXPERT_WIZARD} ||= 0;
63 $h{HEIGTH} ||= $default_height;
64 $h{WIDTH} ||= $default_width;
65
66 my %option_values;
67 $option_values{show_log} = text2bool($h{LOGS});
68 my $theme = $h{THEME};
69 my $program;
70 my ($i, $geometry, $save_html);
71 foreach (@ARGV) {
72 $i++;
73 $theme = $1 if /--theme (\w+)/;
74 $program = $1 if /--start-with=(.*)/;
75 if (/^--geometry$/) {
76 $geometry = splice @ARGV, $i, 1;
77 last;
78 }
79 $save_html = 1 if /--save-html-pages/;
80 }
81
82 -d "$themes_dir/$theme" or $theme = 'default';
83 add_icon_path("$themes_dir/$theme/");
84 add_icon_path("$themes_dir/default") if $theme ne 'default'; # fall back if theme miss some icons
85
86 mygtk2::import_style_ressources();
87 my $rc = find { -r $_ } ("$themes_dir/$theme/gtkrc", if_($theme ne 'default', "$themes_dir/default/gtkrc"));
88 Gtk2::Rc->parse($rc) if -r $rc;
89
90 my $branding = N("Mageia");
91 my $product_id = common::parse_LDAP_namespace_structure(cat_('/etc/product.id'));
92 # allow OEM branding:
93 $branding = translate($product_id->{distribution});
94
95
96 #-------------------------------------------------------------
97 # Splash window: please wait ...
98 my $window_splash = Gtk2::Window->new('popup');
99 $window_splash->signal_connect(delete_event => \&quit_global);
100 $window_splash->set_title(N("%s Control Center", $branding));
101 $window_splash->set_position('center_always');
102 $window_splash->add(gtknew('Fixed', widget_name => 'Steps',
103 children => [
104 [ gtknew('Image_using_pixbuf', file => 'splash_screen'), 0, 0 ],
105 [ gtknew('Label', text => N("%s Control Center", $branding)), 21, 60 ],
106 [ gtknew('Label', text => N("Loading... Please wait")), 21, 175 ],
107 ]),
108 );
109 $window_splash->show_all;
110 gtkflush();
111
112
113 #-------------------------------------------------------------
114 # Data structures
115 my $more_wizard_dir = "/etc/wizard.d/";
116
117 my $isWiz = -e "/usr/sbin/drakwizard";
118 my $isRpmDrake = -e "/usr/sbin/rpmdrake";
119 my $isParkRpmDrake = -e "/usr/sbin/park-rpmdrake";
120 my $isWebAdmin = -e "/usr/bin/mdkwebadmin";
121 my $isRfbDrake = -e "/usr/bin/rfbdrake";
122 my $isDrakStats = -e "/usr/sbin/drakstats";
123
124 my $application_driven_menu;
125
126 sub is_wizard_installed { -f top(glob("/usr/lib/perl5/vendor_perl/*/MDK/Wizard/$_[0]")) }
127
128 my $is_auth_wizard_installed = is_wizard_installed('Nisautofs.pm');
129
130
131 sub wizard_format {
132 map {
133 my ($id, $wizard, $icon, $description, $long_description, $file) = @$_;
134 $programs{$id} =
135 {
136 binary => "$sbindir/drakwizard $wizard",
137 embedded => 1,
138 description => $description,
139 long_description => $long_description,
140 icon => $icon,
141 };
142 if_(is_wizard_installed($file), $id);
143 } @_;
144 }
145
146 # [ [ class_label, class icon name, [ program_label, ... ] ]
147 my @tree = (
148 if_($isRpmDrake || $isParkRpmDrake,
149 [
150 #-PO: please keep the following message very short: it must fit in the left list of MCC!!!
151 N("Software Management"), 'software', 'software-management',
152 [
153 if_($isRpmDrake,
154 {
155 title => N("Software Management"),
156 list => [
157 "Install Software",
158 "Mageia Update",
159 if_(0, "Mageia Online"),
160 "Updates Configuration",
161 "Software Media Manager",
162 ]
163 },
164 ),
165 {
166 title => N("Others"),
167 list => [
168 if_($isParkRpmDrake, "Manage park"),
169 if_($isDrakStats, "Package stats"),
170 ]
171 },
172 ]
173 ]
174 ),
175
176 if_(0, [ N("Server wizards"), 'wizard-mdk' ]),
177 [
178 #-PO: please keep the following message very short: it must fit in the left list of MCC!!!
179 N("Sharing"), 'file-sharing-mdk', 'wiz-client',
180 [
181 {
182 title => N("Sharing"),
183 list => [
184 (wizard_format( # [ id, wizard file name, icon, description ]
185 [ "FTP wizard", "proftpd", 'ftp-mdk', N("Configure FTP"),
186 N("Set up an FTP server"), 'Proftpd.pm',
187 ],
188 [ "Samba wizard", "samba", 'samba_server-mdk', N("Configure Samba"),
189 N("Set up a file and print server for workstations running Linux and non-Linux systems"), 'Samba.pm',
190 ],
191 [ "Manage Samba share", "sambashare", 'wizard-mdk', N("Manage Samba share"),
192 N("Manage, create special share, create public/user share"), 'Sambashare.pm', 1,
193 ],
194 [ "Web wizard", "apache2", 'web_server-mdk', N("Configure web server"),
195 N("Set up a web server"), 'Apache.pm',
196 ],
197 [ "Installation server wizard", "installsrv", 'wizard-mdk', N("Configure installation server"),
198 N("Set up server for network installations of %s", $branding), 'Installsrv.pm', 1,
199 ],
200 ),
201 ),
202 ]
203 },
204 ]
205 ],
206 [
207 #-PO: please keep the following message very short: it must fit in the left list of MCC!!!
208 N("Network Services"), 'network-services-mdk', 'mcc-network',
209 [
210 {
211 title => N("Network Services"),
212 list => [
213 (wizard_format( # [ id, wizard file name, icon, description ]
214 [ "DHCP wizard", "dhcp", 'dhcp_server-mdk', N("Configure DHCP"),
215 N("Set up a DHCP server"), 'Dhcp.pm',
216 ],
217 [ "DNS wizard", "bind", 'dns_server-mdk', N("Configure DNS"),
218 N("Set up a DNS server (network name resolution)"), 'Bind.pm',
219 ],
220 [ "Squid wizard", "squid", 'drakproxy-mdk', N("Configure proxy"),
221 N("Configure a web caching proxy server"), 'Squid.pm',
222 ],
223 [ "Time wizard", "ntp", 'ntp_server-mdk', N("Configure time"),
224 N("Set the time of the server to be synchronized with an external time server"), 'Ntp.pm',
225 ],
226 [ "SSHD wizard", "sshd", 'wizard-sshd', N("OpenSSH daemon configuration"),
227 N("OpenSSH daemon configuration"), 'Sshd.pm',
228 ],
229 ),
230 ),
231 ]
232 },
233 ]
234 ],
235
236 [
237 #-PO: please keep the following message very short: it must fit in the left list of MCC!!!
238 N("Authentication"), 'drakauth-mdk', '',
239 [
240 {
241 title => N("Authentication"),
242 list => [
243 if_($is_auth_wizard_installed, "Authentication"),
244 (wizard_format( # [ id, wizard file name, icon, description ]
245 [ 'Nis+autofs wizard', "nisautofs", 'nisautofs', N("Configure NIS and Autofs"),
246 N("Configure the NIS and Autofs services"), 'Nisautofs.pm',
247 ],
248 [ "LDAP wizard", "ldap", "ldap-mdk", N("Configure LDAP"),
249 N("Configure the LDAP directory services"), 'Ldap.pm',
250 ],
251 ),
252 ),
253 ]
254 },
255 ]
256 ],
257
258 [
259 #-PO: please keep the following message very short: it must fit in the left list of MCC!!!
260 N("Groupware"), 'groupware-mdk', '',
261 [
262 {
263 title => N("Groupware"),
264 list => [
265 (wizard_format( # [ id, wizard file name, icon, description ]
266 if_(0, [ "News wizard", "inn", 'news-mdk', N("Configure news"),
267 N("Configure a newsgroup server"), 'Inn.pm',
268 ],
269 [ "Kolab wizard", "kolab", "kolab-mdk", N("Configure groupware"),
270 N("Configure a groupware server"), 'Kolab.pm',
271 ]),
272 [ "Postfix wizard", "postfix", 'postfix-mdk', N("Configure mail"),
273 N("Configure the Internet Mail services"), 'Postfix.pm'
274 ],
275 ),
276 ),
277 ]
278 },
279 ]
280 ],
281
282 if_($isWebAdmin || $isRfbDrake,
283 [
284 #-PO: please keep the following message very short: it must fit in the left list of MCC!!!
285 N("Online Administration"), 'online-administration-mdk', '',
286 [
287 {
288 title => N("Online Administration"),
289 list => [
290 if_($isWebAdmin,
291 (map {
292 my ($id, $icon, $op, $description, $long_description) = @$_;
293 $programs{$id} =
294 {
295 binary => "$bindir/mdkwebadmin.pl $op",
296 embedded => -1, # too big
297 description => $description,
298 long_description => $long_description,
299 icon => $icon,
300 };
301
302 $id;
303 } ( # [ id, wizard file name, icon, description ]
304 [ "Local Admin", 'local-administration-mdk', '--direct', N("Local administration"),
305 (-e "/usr/bin/webmin" ? N("Configure the local machine via web interface") : N("You don't seem to have webmin installed. Local config is disabled"))
306 ],
307 [ "Remote Admin", 'remote-administration-mdk', '--link', N("Remote administration"),
308 N("Click here if you want to configure a remote box via Web interface"),
309 ])
310 )
311 ),
312 if_($isRfbDrake,
313 "Remote Control",
314 )
315 ]
316 },
317 ]
318 ]),
319
320 [
321 #-PO: please keep the following message very short: it must fit in the left list of MCC!!!
322 N("Hardware"), 'drakhard-mdk', 'mcc-hardware',
323 [
324 {
325 title => N("Manage your hardware"),
326 list => [
327 "Hardware List",
328 "Sound",
329 ]
330 },
331 {
332 title => N("Configure graphics"),
333 list => [
334 "3D",
335 "Graphical server configuration",
336 ]
337 },
338 {
339 title => N("Configure mouse and keyboard"),
340 list => [
341 "Keyboard",
342 "Mouse",
343 ]
344 },
345 {
346 title => N("Configure printing and scanning"),
347 list => [
348 "Printer",
349 "Scanner",
350 if_(-x "$bindir/drakfax", "Fax"),
351 ]
352 },
353 {
354 title => N("Others"),
355 list => [
356 "UPS",
357 ]
358 },
359 ]
360 ],
361
362 [
363 #-PO: please keep the following message very short: it must fit in the left list of MCC!!!
364 N("Network & Internet"), 'net-mdk', 'mcc-network',
365 [
366 {
367 title => N("Manage your network devices"),
368 list => [
369 "Network Center",
370 "Add Connection",
371 if_(!-x "$sbindir/draknetcenter",
372 "Configure Internet",
373 "Manage Connection",
374 "Monitor Connection",
375 ),
376 "Remove Interface",
377 ]
378 },
379 {
380 title => N("Personalize and Secure your network"),
381 list => [
382 "Proxy Configuration",
383 "Connection Sharing",
384 "Network Profiles",
385 "VPN",
386 ]
387 },
388 {
389 title => N("Others"),
390 list => [
391 "Hosts",
392 ]
393 },
394 ],
395 ],
396
397 [
398 #-PO: please keep the following message very short: it must fit in the left list of MCC!!!
399 N("System"), 'system-mdk', 'mcc-system',
400 [
401 {
402 title => N("Manage system services"),
403 list => [
404 if_(!$is_auth_wizard_installed, "Authentication"),
405 "Menus",
406 "Services",
407 "Fonts",
408 ]
409 },
410 {
411 title => N("Localization"),
412 list => [
413 "Date & Time",
414 "Localization",
415 ]
416 },
417 {
418 title => N("Administration tools"),
419 list => [
420 "Logs",
421 if_($ENV{LANGUAGE} !~ /^zh/, "Console"),
422 "Users",
423 "Migration",
424 if_(-x "$xbindir/drakcronat", "Programs scheduling"),
425 "Backups",
426 'Snapshots',
427 "Virtualization",
428 ]
429 },
430 ]
431 ],
432
433 [
434 #-PO: please keep the following message very short: it must fit in the left list of MCC!!!
435 N("Network Sharing"), 'network-sharing-mdk', '',
436 [
437 {
438 title => N("Configure Windows(R) shares"),
439 list => [
440 "Access Windows shares",
441 "Samba configuration",
442 ]
443 },
444 {
445 title => N("Configure NFS shares"),
446 list => [
447 "NFS mount points",
448 "NFS exports",
449 ]
450 },
451 {
452 title => N("Configure WebDAV shares"),
453 list => [
454 "WebDAV mount points",
455 ]
456 },
457 ],
458 ],
459
460 [
461 #-PO: please keep the following message very short: it must fit in the left list of MCC!!!
462 N("Local disks"), 'partition-mdk', 'mcc-localdisks',
463 [
464 {
465 title => N("Local disks"),
466 list => [
467 "Hard Drives",
468 (map {
469 my ($type, $scan, $text_orig, $long_text) = @$_;
470 map_index {
471 my $text = sprintf(translate($text_orig), $_->{info});
472 my $full_name = $text . ($::i ? $::i + 1 : '');
473 $programs{$full_name} =
474 {
475 binary => "$sbindir/diskdrake --removable=$_->{device}",
476 embedded => 1,
477 description => $text,
478 long_description => sprintf(translate($long_text), $_->{info}),
479 icon => "diskdrake_$type",
480 };
481 $full_name;
482 } $scan->();
483 } do {
484 my %cdroms_by_type;
485 foreach (detect_devices::cdroms()) {
486 my $type = detect_devices::isBurner($_) ? 'burner' : detect_devices::isDvdDrive($_) ? 'DVD' : 'cdrom';
487 push @{$cdroms_by_type{$type}}, $_;
488 }
489 ([ 'cdrom', sub { @{$cdroms_by_type{cdrom} || []} }, N_("CD-ROM (%s)",),
490 N_("Set where your \"%s\" CD-ROM drive is mounted"),
491 ],
492 [ 'dvd', sub { @{$cdroms_by_type{DVD} || []} }, N_("DVD-ROM (%s)"),
493 N_("Set where your \"%s\" DVD-ROM drive is mounted"),
494 ],
495 [ 'cdwriter', sub { @{$cdroms_by_type{burner} || []} }, N_("CD/DVD burner (%s)"),
496 N_("Set where your \"%s\" CD/DVD burner is mounted"),
497 ],
498 [ 'zip', \&detect_devices::zips, N_("ZIP drive"),
499 N_("Set where your ZIP drive is mounted"),
500 ],
501 );
502 }),
503 "Partition Sharing",
504 ]
505 },
506 ]
507 ],
508
509 [
510 #-PO: please keep the following message very short: it must fit in the left list of MCC!!!
511 N("Security"), 'security-mdk', 'mcc-security',
512 [
513 {
514 title => N("Security"),
515 list => [
516 "Security Level",
517 "Tomoyo Policy",
518 "Firewall",
519 "Mageia Tools Authentication",
520 "Invictus Firewall",
521 "Parental Controls",
522 ]
523 },
524 ]
525 ],
526
527 [
528 #-PO: please keep the following message very short: it must fit in the left list of MCC!!!
529 N("Boot"), 'drakboot-mdk', 'mcc-boot',
530 [
531 {
532 title => N("Configure boot steps"),
533 list => [
534 #if_(detect_devices::floppies, "Boot Disk"), # kernel is too big
535 "Auto login Config",
536 "Boot Config",
537 "Display Manager chooser",
538 ]
539 },
540 {
541 title => N("Boot look'n feel"),
542 list => [
543 #"Boot Theme",
544 ]
545 },
546 {
547 title => N("Others"),
548 list => [
549 if_(0, "Auto Install"),
550 ]
551 },
552 ]
553 ],
554 );
555
556 if (scalar glob_("$more_wizard_dir/*.conf")) {
557 my @leaf = (
558 N("Additional wizards"),
559 'wizard-mdk',
560 []
561 );
562
563 foreach my $file (glob_("$more_wizard_dir/*.conf")) {
564 next unless -f $file;
565 my %tmp = getVarsFromSh($file);
566 $programs{$tmp{NAME}} = {
567 binary => "$sbindir/drakwizard " . lc($file),
568 embedded => 1,
569 description => $tmp{DESCRIPTION},
570 icon => $tmp{ICON} || 'wizard-mdk',
571 long_description => $tmp{LONG_DESCRIPTION},
572 };
573 push(@{$leaf[2]}, $tmp{NAME});
574 }
575 push(@tree, \@leaf);
576 }
577
578 #-------------------------------------------------------------
579 # let build the GUI
580
581
582 my $align = mygtk2::text_direction_rtl() ? "right" : "left";
583 my $align2 = mygtk2::text_direction_rtl() ? "right" : "left";
584
585
586 # main window :
587
588 my ($timeout, %check_boxes, $emb_socket);
589
590 # set default size:
591
592 my $window_global = gtkset_size_request(Gtk2::Window->new('toplevel'), $min_width, $min_height);
593 $::main_window = $window_global;
594
595 if ($geometry) {
596 @h{qw(HEIGTH WIDTH)} = $geometry =~ /(\d+)x(\d+)/;
597 my ($x, $y) = $geometry =~ /([+-]\d+)([+-]\d+)/;
598 $window_global->set_uposition($x, $y) if $x || $y;
599 } else {
600 }
601 $window_global->resize(max($default_width, $h{WIDTH}, $min_width), max($h{HEIGTH}, $default_height, $min_height));
602
603 $window_global->set_icon(gtkcreate_pixbuf("/usr/share/icons/drakconf.png"));
604
605 my $pending_app = 0;
606
607 my $help_on_context = 'drakconf-intro';
608
609 my @themes = grep { -d "$themes_dir/$_" } all($themes_dir);
610
611 #-PO Translators, please keep all "/" charaters !!!
612 my %options = (
613 'show_log' => [ N("/_Options"), N("/Display _Logs") ],
614 'embedded_mode' => [ N("/_Options"), N("/_Embedded Mode") ],
615 'wiz_expert' => [ N("/_Options"), N("/Expert mode in _wizards") ],
616 );
617
618 my $mga_rel = common::mageia_release();
619
620 my ($steps, $view);
621
622 my $release = mageia_release_info();
623
624 my @menu_items = (
625 [ N("/_File"), undef, undef, undef, '<Branch>' ],
626 [ N("/_File") . N("/_Quit"), N("<control>Q"), \&quit_global, undef, '<Item>', N("Quit") ],
627 [ N("/_Options"), undef, undef, undef, '<Branch>' ],
628 [ join('', @{$options{show_log}}), undef,
629 sub {
630 $option_values{show_log} = $check_boxes{show_log}->get_active;
631 if ($option_values{show_log}) {
632 start_logdrake();
633 } else {
634 kill_logdrake();
635 }
636 },
637 undef, '<CheckItem>'
638 ],
639
640 if_(0 && $isWiz,
641 [ join('', @{$options{wiz_expert}}), undef,
642 sub { $option_values{expert_wizard} = $check_boxes{wiz_expert}->get_active },
643 undef, '<CheckItem>',
644 ],
645 ),
646 if_(@themes > 1,
647 [ N("/_Themes"), undef, undef, undef, '<Branch>' ],
648 (map {
649 my $name = $_;
650 [ N("/_Themes") . "/" . ($name eq $theme ? " O " : " ") . "_$_", undef,
651 sub {
652 return if $theme eq $name;
653 !$pending_app || splash_warning(N("This action will restart the control center.\nAny change not applied will be lost."), 1) and do {
654 # embedded app must be killed
655 kill_children();
656 kill_logdrake();
657 child_just_exited();
658 exec "$0 --theme $name";
659 };
660 }, undef, '<CheckItem>'
661 ];
662 } @themes),
663 [ N("/_Themes") . N("/_More themes"), undef, \&more_themes, undef, '<Item>' ]
664 ),
665 [ N("/_Help"), undef, undef, undef, '<Branch>' ],
666 [ N("/_Help") . N("/_Help"), undef, \&run_help, undef, '<Item>', N("Help") ],
667 [ N("/_Help") . N("/_Release notes"), undef, sub { run_browser('Release_Notes') }, undef, '<Item>', N("Help") ],
668 [ N("/_Help") . N("/What's _New?"), undef, sub { run_browser("What's New?") }, undef, '<Item>', N("Help") ],
669 [ N("/_Help") . N("/_Errata"), undef, sub { run_browser('Errata') }, undef, '<Item>', N("Help") ],
670 [ N("/_Help") . N("/_Report Bug"), undef, sub {
671 run_program::raw({ detach => 1, as_user => 1 }, 'drakbug', '--report', (split(/\s/, $pending_app))[0] || 'drakconf');
672 }, undef, '<Item>' ],
673 [ N("/_Help") . N("/_About..."), undef, \&about_mga_cc, undef, '<Item>' ]
674 );
675
676
677 sub run_help() {
678 run_program::raw({ detach => 1, as_user => 1 }, 'drakhelp', '--id', $help_on_context);
679 }
680
681 sub run_browser {
682 my ($url) = @_;
683 $url = "http://wiki.mageia.org/en/$release->{distribution}_$release->{version}_$url" if $url !~ m!^http://!;
684 run_program::raw({ detach => 1, as_user => 1 }, '/usr/bin/www-browser', $url);
685 }
686
687 my ($menu, $factory) = create_factory_menu($window_global, @menu_items);
688
689 # to retrieve a path, one must prevent "accelerators completion":
690 sub get_path { join('', map { my $i = $_; $i =~ s/_//g; $i } @_) }
691
692 %check_boxes = map {
693 $_ => $factory->get_widget("<main>" . get_path(@{$options{$_}}));
694 } ('show_log', if_(0 && $isWiz, "wiz_expert"));
695
696 my @buttons;
697 my $offset = 15;
698
699 $view = gtknew('WebKit_View', no_popup_menu => 1);
700 # so that it exists when building steps:
701 my $banner_notebook = Gtk2::Notebook->new;
702 build_list();
703
704 gtkadd($window_global,
705 gtkpack_(Gtk2::VBox->new(0, 0),
706 0, $menu,
707 #0, $banner_notebook,
708 0, Gtk2::HSeparator->new,
709 # 0, gtkset_size_request(Gtk2::VBox->new(10, 10), -1, 2),
710 1, gtkpack_(Gtk2::HBox->new(0, 0),
711 1, $steps = gtknew('MDV_Notebook', parent_window => $window_global, children => [ #Layout Fixed
712 # 145 is the vertical offset in order to be below the actual logo:
713 [ gtknew('VBox', widget_name => 'Steps', spacing => 0, width => (192 - $offset),
714 children_tight => [ map {
715 gtknew('HBox', spacing => 0, children => [
716 1, $_,
717 0, gtknew('Alignment', width => 12),
718 ]);
719 } @buttons ]), 0, 100 ],
720 ], right_child => gtknew('ScrolledWindow', child => gtkset_border_width($view, 5),
721 no_shadow => 1, h_policy => 'never')),
722 1, gtkpack(my $emb_box = Gtk2::VBox->new(0, 0),
723 my $wait_darea = gtkset_size_request(Gtk2::DrawingArea->new, -1, -1),
724 ),
725 ),
726 0, Gtk2::HSeparator->new,
727 0, my $buttons = gtkadd(gtkset_layout(Gtk2::HButtonBox->new, 'start'),
728 map { gtkset_border_width($_, 3) }
729 gtksignal_connect(my $cancel = Gtk2::Button->new(N("Cancel")),
730 clicked => sub {
731 stop_wait_area();
732 kill_children();
733 child_just_exited();
734 }),
735 ),
736 )
737 );
738
739 $view->set_size_request(-1, -1);
740
741 $window_global->signal_connect(delete_event => \&quit_global);
742
743 my $accel = Gtk2::AccelGroup->new;
744 $accel->connect(Gtk2::Gdk->keyval_from_name('F1'), [], ['visible'], \&run_help);
745 $window_global->add_accel_group($accel);
746
747 use POSIX qw(:sys_utsname_h :math_h :sys_wait_h :unistd_h);
748 my (undef, $nodename) = POSIX::uname();
749 $window_global->set_title(N("%s Control Center %s [on %s]", $branding, $version, $nodename));
750 $window_global->set_position('center');
751
752 foreach my $notebook ($banner_notebook) {
753 $notebook->set_property('show-border', 0);
754 $notebook->set_property('show-tabs', 0);
755 }
756
757
758 # banner :
759
760 #add2notebook($banner_notebook, "", Gtk2::Banner->new("/usr/share/icons/large/drakconf.png",
761 # N("Welcome to the %s Control Center", $branding)));
762
763
764 my ($_hand_cursor, $wait_cursor) = map { Gtk2::Gdk::Cursor->new($_) } qw(hand2 watch);
765
766 my $left_locked = 0;
767
768 #my $spacing = 25;
769
770 my %tool_callbacks;
771
772 my ($page_count);
773
774
775 my $conf_file = '/etc/sysconfig/mcc.conf';
776 foreach (cat_($conf_file)) {
777 #s/^ENABLE_//;
778 #my ($key, $val) = /^(.*)=(.*)/;
779 if (my ($key, $val) = /^ENABLE_(.*)=(.*)/) {
780 $key =~ s/_/ /g;
781 #warn "--> ($key, $val)\n";
782 $programs{$key}{disabled} = 1 if $val ne 'yes';
783 warn ">> disabling $key\n" if $val ne 'yes';
784 } else {
785 warn "bogus line in $conf_file: $_\n";
786 next;
787 }
788 }
789
790 sub load_packages2install() {
791 my $progs_conf_file = '/usr/share/mcc/progs.conf';
792 foreach (cat_($progs_conf_file)) {
793 #if (my ($key, $val) = /^USE_WRAPPER_FOR_(.*)=(.*)/) {
794 if (my ($key, $val) = /^INSTALL_FOR_(.*)=(.*)/) {
795 $key =~ s/_/ /g;
796 # we'll use gurpmi in order to install missing packages if needed;
797 $programs{$key}{packages2install} = $val if $val;
798 } else {
799 warn "bogus line in $conf_file: $_\n";
800 next;
801 }
802 }
803 }
804
805 sub clean_list {
806 my ($subtree) = @_;
807 grep {
808 my $stuff = $_;
809 my $exec = real_bin_path($programs{$stuff}{binary});
810 my $is_present = -x $exec;
811 if (!$is_present && $programs{$stuff}{packages2install}) {
812 $is_present = 1;
813 # override missing icon:
814 $programs{$stuff}{real_icon} ||= $programs{$stuff}{icon};
815 $programs{$stuff}{icon} = 'installremoverpm';
816 } elsif ($programs{$stuff}{real_icon}) {
817 $programs{$stuff}{icon} = $programs{$stuff}{real_icon};
818 }
819 # do not complain about missing entries in move:
820 warn qq("$exec" is not executable [$stuff]) if $mga_rel !~ /Move/ && !$is_present && !$programs{$stuff}{disabled};
821 !$programs{$stuff}{hidden} && $is_present && !$programs{$stuff}{disabled};
822 } @$subtree;
823 }
824
825 sub build_widget_element {
826 my ($label) = @_;
827 my $icon = $programs{$label}{icon};
828
829 die "$label 's icon is missing" if !$programs{$label} && $::testing;
830 $tool_callbacks{$label} = sub {
831 run_tool($label, undef, #$event_box,
832 $icon, $programs{$label}{description}, $programs{$label});
833 };
834 # FIX ME: DO THIS AGAIN:
835 $tool_feedback{$label} = sub {}; #sub { $event_box->window && $event_box->window->set_cursor($hand_cursor) };
836 my $real_icon = $icon ? '<IMG SRC="' . mygtk2::_find_imgfile($icon) . '">' : '';
837 my @widgets = (
838 qq(<TD class="img">$real_icon</TD>),
839 qq(<TD style="text-align: $align"><DIV>)
840 . escape_text_for_TextView_markup_format($programs{$label}{description})
841 . qq(</DIV></TD>)
842 );
843 qq(<TD WIDTH="49%">
844 <A HREF="$label"><TABLE align="$align2" ID="subtable"><TR>
845 @widgets
846 </TR></TABLE></A></TD>
847 );
848 }
849
850 my (@strings, $current_string_idx);
851 sub load_view() {
852 $view->load_html_string($strings[$current_string_idx], 'file:///');
853 }
854
855 sub build_list() {
856 my $index = 0;
857 load_packages2install();
858 my $i;
859 foreach (@tree) {
860 my ($text, $icon, $help, $subtrees) = @$_;
861
862 my @subtrees = grep { $_->{list} = [ clean_list($_->{list}) ]; !is_empty_array_ref($_->{list}) } @$subtrees;
863
864
865 # Skip empty classes:
866 next if !@subtrees;
867 $i++;
868
869
870 my $my_index = $index++;
871 my $square_icon_uri = mygtk2::_find_imgfile('cadre-ic');
872 my $back_img = mygtk2::_find_imgfile('right-white-background_right_part_768.png');
873 my $string = join("\n", qq(<HTML>
874 <HEAD>
875 <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
876 <style type="text/css">
877 body {
878 // background-color: #ecf0f2;
879 // background-image: url($back_img);
880 background-repeat: no-repeat; /*pas de répition de l'image*/
881 background-attachment: fixed;
882 background-position: top left
883 }
884 p {text-align: $align}
885 td {text-align: $align}
886 #title {
887 text-align: $align;
888 color: #grey;
889 font-weight: bold;
890 margin-left: 13px;
891 margin-top: 16px;
892 margin-bottom: 8px;
893 }
894 #top_margin {
895 margin-top: 30px;
896 }
897 #block {
898 margin-left: 4px;
899 margin-bottom: 24px;
900 border-spacing: 8px 0px;
901 }
902 #subtable {
903 border-spacing: 8px 8px;
904 }
905 td.img {
906 background-image: url($square_icon_uri);
907 background-repeat: no-repeat;
908 background-position: center center;
909 width: 60; height: 60;
910 text-align: center;
911 }
912 hr {
913 background-color: #eef2f6;
914 margin-left: 21px;
915 margin-right: 22px;
916 height: 1;
917 border: 0;
918 }
919 tr {text-align: $align}
920 td {
921 margin-left: 10px;
922 margin-right: 10px;
923 }
924 ),
925 if_(mygtk2::text_direction_rtl(), " a { direction: rtl; unicode-bidi: embed }"), qq(
926 a:link {color:black; text-decoration:none }
927 a:visited {color:black; text-decoration:none }
928 a:hover {color:grey }
929 // a:active {color:black; text-decoration:none }
930 </style>
931
932 </HEAD>
933 <BODY>
934 ));
935
936
937
938 # Create right notebook pages :
939
940 my $section;
941 foreach my $subtree (@subtrees) {
942 $string .= $section++ ? "<hr NOSHADE>\n" : '<div ID="top_margin"></div>';
943 my $title = mygtk2::asteriskize($subtree->{title});
944 $string .= qq(
945 <div ID="title">$title</div>
946 <TABLE BORDER=0 WIDTH="100%" ID="block">
947 );
948 if (@{$subtree->{list}} % 2) {
949 my @widgets = (pop @{$subtree->{list}}, "");
950 @widgets = reverse @widgets if mygtk2::text_direction_rtl();
951 push @{$subtree->{list}}, @widgets;
952 }
953 $string .= join("\n",
954 map {
955 "<TR>" . join("\n", grep { defined $_ } @$_) . "</TR>" }
956 # "<TR>" . join("\n<TD> </TD>\n", grep { defined $_ } @$_) . "</TR>" }
957 group_by(2, map { $_ ? build_widget_element($_) : '<TD></TD>' } @{$subtree->{list}})
958 );
959
960 $string .= "</TABLE>\n";
961 }
962 my $text_orig = $text;
963 # b/c we use Pango text markup language, we've to protect '&' caracter:
964 $text =~ s/&/&amp;/g;
965 $page_count++;
966
967 $string .= qq(</BODY></HTML>);
968 if ($save_html) {
969 mkdir_p('/tmp/mcc');
970 MDK::Common::File::output_utf8("/tmp/mcc/$i.html", $string);
971 }
972
973 $strings[$my_index] = $string;
974 push @buttons, gtknew('Button', relief => 'none', child =>
975 gtknew('Label_Right', text_markup => qq(<small>$text</small>), ellipsize => 'end'),
976 clicked => sub {
977 $current_string_idx = $my_index;
978 load_view();
979 $steps->move_selection($_[0]->child);
980 $banner_notebook->set_current_page($my_index);
981 $help_on_context = $help;
982 },
983 );
984
985 #add2notebook($banner_notebook, "", Gtk2::Banner->new($icon, $text_orig));
986 }
987 }
988
989 $view->signal_connect('navigation-requested' =>
990 sub {
991 my (undef, undef, $request) = @_;
992 my $res = 'ignore';
993
994 # get the actual program ID:
995 my $url = Glib::filename_from_uri($request->get_uri);
996 $url =~ s!^/*!!; # not a path
997
998 # workaround wekbit calling navigation-requested with "/":
999 if (!$url) {
1000 return 'accept';
1001 }
1002
1003 # url can be a translated UTF-8 string (eg: for CD/DVD entries):
1004 c::set_tagged_utf8($url);
1005
1006 # do not crash on eg: "reload":
1007 if (!$tool_callbacks{$url}) {
1008 warn "Warning: invalid tool name: $url\n";
1009 return $res;
1010 }
1011 $tool_callbacks{$url}->();
1012 # FIXME: the following code is currently useless:
1013 # should we provide a way to kill buggy embedded programs ?
1014 return $res if $left_locked;
1015 warn_on_startup();
1016 return $res;
1017 });
1018
1019 my %icons = (
1020 );
1021
1022 # manage tools not present in MCC (localedrake, drakauth, ...):
1023 foreach my $label (difference2([ keys %programs ], [ keys %tool_callbacks ])) {
1024 my $text = $programs{$label}{description};
1025 $tool_callbacks{$label} = sub { run_tool($label, undef, $icons{$label} || 'wizard-mdk', $text, $programs{$label}) };
1026 $tool_feedback{$label} = sub {};
1027 }
1028
1029
1030 foreach (keys %check_boxes) {
1031 my $widget = $check_boxes{$_};
1032 if (defined $widget) {
1033 $widget->set_active($option_values{$_});
1034 } else {
1035 print STDERR qq(BUG with LANGUAGE "$ENV{LANGUAGE}" for "$_"\n);
1036 err_dialog(N("Error"), N("There's a bug in translations of your language (%s)
1037
1038 Please report that bug.", $ENV{LANGUAGE}));
1039 }
1040 }
1041
1042 # "wait while launching a program" area :
1043
1044 my ($run_pixbuf, $run_counter, $run_counter_add, %run_pixbufs);
1045
1046 sub stop_wait_area() {
1047 $wait_darea->hide;
1048 Glib::Source->remove($timeout) if $timeout;
1049 undef %run_pixbufs;
1050 }
1051
1052 $wait_darea->signal_connect(expose_event => sub {
1053 my ($w) = @_;
1054 return if !$wait_darea->realized;
1055 return unless $run_pixbuf; # some people got an expose event before we start an embedded tool
1056 return unless $wait_darea->{size};
1057 $wait_darea->{layout} ||= $wait_darea->create_pango_layout(N("Loading... Please wait"));
1058 my $pixbuf = $run_pixbufs{$run_counter} ||= mygtk2::_pixbuf_render_alpha($run_pixbuf, $run_counter);
1059 if (!$wait_darea->{first_expose}) {
1060 $wait_darea->{first_expose} = 1;
1061 my $size = $wait_darea->{size};
1062 my ($d_width, $d_height) = ($size->width, $size->height);
1063 ($w->{pix_width}, $w->{pix_height}) = ($pixbuf->get_width, $pixbuf->get_height);
1064 my ($txt_width, $txt_height) = $wait_darea->{layout}->get_pixel_size;
1065 $w->{pix_yy} = ($d_width - $w->{pix_width})/2;
1066 $w->{pix_xx} = ($d_height - $w->{pix_height} - $txt_height)/2;
1067 $w->{text_yy} = $w->{pix_yy} + ($w->{pix_width} - $txt_width)/2;
1068 $w->{text_xx} = $w->{pix_xx} + $w->{pix_height} + 5;
1069 }
1070 $pixbuf->render_to_drawable($w->window, $w->style->fg_gc('normal'), 0, 0, $w->{pix_yy}, $w->{pix_xx}, $w->{pix_width}, $w->{pix_height}, 'normal', 0, 0);
1071 my $style = $wait_darea->{style} ||= $wait_darea->get_style;
1072 $wait_darea->window->draw_layout($style->text_gc('normal'), $w->{text_yy}, $w->{text_xx}, $w->{layout});
1073 $run_counter += $run_counter_add;
1074 $run_counter_add = -$run_counter_add if $run_counter < 100 || 255-$run_counter_add < $run_counter;
1075 });
1076
1077 gtkflush();
1078
1079 # display first page (we use a timeout so that Y position of widgets is know):
1080 Glib::Timeout->add(100, sub { $buttons[0]->signal_emit('clicked'); 0 });
1081
1082 $window_global->show_all;
1083
1084 hide_buttons();
1085 $emb_box->hide;
1086 $wait_darea->realize;
1087
1088 $SIG{USR1} = 'IGNORE';
1089 $SIG{USR2} = 'IGNORE';
1090 $SIG{TERM} = \&quit_global;
1091 $SIG{CHLD} = \&sig_child;
1092
1093 $window_splash->destroy;
1094 undef $window_splash;
1095 Glib::Timeout->add(200, sub { sig_child('CHLD', 1); 1 });
1096
1097 if ($program) {
1098 if (my $sub = $tool_callbacks{$program}) {
1099 Glib::Timeout->add(500, sub { $sub->(); 0 });
1100 } else {
1101 err_dialog(N("Error"), N("Impossible to run unknown '%s' program", $program));
1102
1103 }
1104 }
1105
1106 Gtk2->main;
1107
1108
1109 sub group_by {
1110 my $nb = shift @_;
1111 my @l;
1112 for (my $i = 0; $i < @_; $i += $nb) {
1113 push @l, [ map { $_[$_] } $i..$i+$nb-1 ]; # $_[$i], $_[$i+1], $_[$i+2] ];
1114 }
1115 @l;
1116 }
1117
1118 sub warn_on_startup() {
1119 if ($pending_app) {
1120 return if !splash_warning(N("The modifications done in the current module won't be saved."), 1);
1121 kill_children();
1122 child_just_exited();
1123 }
1124 }
1125
1126 #-------------------------------------------------------------
1127 # socket/plug managment
1128
1129 # called once embedded tool has exited
1130 sub child_just_exited() {
1131 $pending_app = 0;
1132 $left_locked = 0;
1133 if ($emb_socket) {
1134 $emb_socket->destroy;
1135 undef $emb_socket;
1136 }
1137 $emb_box->hide;
1138 hide_buttons();
1139 $cancel->hide;
1140 gtkset_mousecursor_normal();
1141 foreach my $w ($steps, $banner_notebook) {
1142 $w->show;
1143 }
1144
1145 stop_wait_area();
1146 }
1147
1148 sub hide_socket_and_clean() {
1149 $emb_box->hide;
1150 $pending_app = 0;
1151 }
1152
1153 sub create_hidden_socket {
1154 my ($icon, $label) = @_;
1155 my $banner;
1156 gtkpack_($emb_box,
1157 0, $banner = gtkpack__(Gtk2::VBox->new(0, 0), Gtk2::Banner->new($icon, $label),
1158 Gtk2::HSeparator->new,
1159 ),
1160 1, gtksignal_connect($emb_socket = Gtk2::Socket->new, 'plug-removed' => sub {
1161 $menu->show if $application_driven_menu;
1162 $banner->destroy;
1163 child_just_exited();
1164 }));
1165 $banner->hide;
1166 # signal emitted when embedded apps begin to draw:
1167 $emb_socket->signal_connect('plug-added' => sub {
1168 $banner_notebook->hide;
1169 if ($application_driven_menu) {
1170 $menu->hide;
1171 } else {
1172 $banner->show;
1173 }
1174 stop_wait_area();
1175 $left_locked = 0;
1176 hide_buttons();
1177 $buttons->hide;
1178 return if !$emb_socket;
1179 $emb_socket->show;
1180 $emb_socket->can_focus(1);
1181 $emb_socket->grab_focus;
1182 #$emb_socket->window->XSetInputFocus; #only need by console (no more embedded until we've vte/zvt binding)
1183 });
1184 $emb_box->set_focus_child($emb_socket);
1185 $emb_socket->hide;
1186 }
1187
1188
1189 #-------------------------------------------------------------
1190 # processes managment
1191
1192 # embedded processes pid will be stocked there
1193 my @pid_launched;
1194
1195 # logdrake pid are stocked here
1196 my $pid_exp;
1197
1198 sub fork_ {
1199 my ($prog, $o_pid_table) = @_;
1200 $o_pid_table ||= \@pid_launched;
1201 my $pid = fork();
1202 if (defined $pid) {
1203 !$pid and do { exec($prog) or POSIX::_exit(1) }; # immediate exit, else forked gtk+ object destructors will badly catch up parent mcc
1204 push @$o_pid_table, $pid;
1205 return $pid;
1206 } else {
1207 splash_warning(N("cannot fork: %s", "$!"));
1208 child_just_exited();
1209 }
1210 }
1211
1212 sub real_bin_path {
1213 my ($prog) = @_;
1214 first(split /\s+/, $prog);
1215 }
1216
1217 sub run_tool {
1218 my ($label, $box, $icon, $text, $tool) = @_;
1219 my ($exec, $gtkplug) = @$tool{qw(binary embedded)};
1220 $application_driven_menu = $tool->{application_driven_menu};
1221 return if $tool_pids{$label};
1222 my $will_run_gurpmi;
1223 if (! -x real_bin_path($exec)) {
1224 if ($tool->{packages2install}) {
1225 # gurpmi doesn't support being embedded yet:
1226 $gtkplug = -1;
1227 $exec = join(' ', "$bindir/gurpmi", split(/\s/, $tool->{packages2install}));
1228 $will_run_gurpmi = 1;
1229 } else {
1230 splash_warning(N("cannot fork and exec \"%s\" since it is not executable", $exec));
1231 return;
1232 }
1233 }
1234 $exec .= " --summary" if $option_values{expert_wizard} && $exec =~ /drakwizard/;
1235 my $embedded = $gtkplug != -1; # not "explicitely not embedded"
1236 if ($embedded) {
1237 $steps->hide;
1238 create_hidden_socket($icon, $text);
1239 $emb_box->show;
1240 $emb_socket->realize;
1241 $pending_app = $tool->{binary};
1242 if ($gtkplug > 0) {
1243 $buttons->show;
1244 $exec .= " --embedded " . $emb_socket->get_id;
1245 $wait_darea->show;
1246 $cancel->show;
1247 $run_pixbuf = eval { gtkcreate_pixbuf($icon . "_128") };
1248 $run_counter = 255;
1249 $run_counter_add = -5;
1250 undef $wait_darea->{color};
1251 undef $wait_darea->{size};
1252 undef $wait_darea->{first_expose};
1253 $wait_darea->{not_yet_complete} = 1;
1254 $timeout = Glib::Timeout->add(35, sub {
1255 $wait_darea->{size} ||= $wait_darea->allocation;
1256 my $style = $wait_darea->{style} ||= $wait_darea->get_style;
1257 my $bg = $wait_darea->{bg} ||= $style->bg('normal');
1258 my $base = $wait_darea->{base} ||= $style->base('normal');
1259 my $color = $wait_darea->{color} ||= $base;
1260 # $base -> $bg
1261 my @colors = ([ $color->red, $bg->red ],
1262 [ $color->green, $bg->green ],
1263 [ $color->blue, $bg->blue ]);
1264 if ($wait_darea->{not_yet_complete} && any { $_->[0] != $_->[1] } @colors) {
1265 $wait_darea->window->set_background($color);
1266 $wait_darea->{color} = gtkcolor(map { $_->[0] - min(300, $_->[0] - $_->[1]) } @colors);
1267 $wait_darea->queue_draw;
1268 } elsif ($wait_darea->{not_yet_complete}) {
1269 # set exact color
1270 $wait_darea->window->set_background($bg);
1271 $wait_darea->queue_draw;
1272 $wait_darea->{not_yet_complete} = 0;
1273 } else {
1274 my $w = $wait_darea;
1275 $wait_darea->queue_draw_area($w->{pix_yy}, $w->{pix_xx}, $w->{pix_width}, $w->{pix_height});
1276 }
1277 1;
1278 });
1279 $left_locked = 1;
1280 $buttons->show;
1281 $tool_pids{$label} = fork_($exec);
1282 }
1283 } else { # not embedded
1284 # fix #3415 when $gtkplug eq -1
1285 local $option_values{embedded} = 0;
1286 $tool_pids{$label} = fork_($exec);
1287 $gurpmi_pid = $tool_pids{$label} if $will_run_gurpmi;
1288 }
1289 start_logdrake();
1290 $box->window->set_cursor($wait_cursor) if $box;
1291 }
1292
1293 sub start_logdrake() {
1294 # (re)start logdrake if needed
1295 if ($option_values{show_log} && !$pid_exp) {
1296 my $exec_log = "logdrake --explain=drakxtools";
1297 $pid_exp = fork_($exec_log, []);
1298 }
1299
1300 }
1301
1302 sub kill_them_all {
1303 foreach my $pid (@_) {
1304 kill('TERM', $pid) if $pid;
1305 }
1306 }
1307
1308 sub kill_children() {
1309 kill_them_all(@pid_launched);
1310 }
1311
1312 sub kill_logdrake() {
1313 kill_them_all($pid_exp) if $pid_exp;
1314 }
1315
1316 sub quit_global() {
1317 if (@pid_launched) {
1318 &kill_children();
1319 return 1; # tell gtk+ not to quit
1320 }
1321 &kill_children();
1322 &kill_logdrake();
1323 my ($x, $y) = $window_global->get_size;
1324 setVarsInSh($conffile, {
1325 LOGS => bool2text($option_values{show_log}),
1326 EXPERT_WIZARD => bool2text($option_values{expert_wizard}),
1327 HEIGTH => $y,
1328 WIDTH => $x,
1329 THEME => $theme,
1330 });
1331 gtkset_mousecursor_normal();
1332 Gtk2::exit(0);
1333 standalone::exit(0);
1334 }
1335
1336
1337 #-------------------------------------------------------------
1338 # signals managment
1339
1340 # got when child died and gone in zombie state
1341 sub sig_child {
1342 my ($_sig, $o_is_cleaner) = @_;
1343 my $child_pid;
1344 do {
1345 $child_pid = waitpid(-1, POSIX::WNOHANG);
1346 if (my $tool = find { $tool_pids{$_} eq $child_pid } keys %tool_pids) {
1347 $tool_feedback{$tool}->();
1348 delete $tool_pids{$tool};
1349 @pid_launched = grep { $_ ne $child_pid } @pid_launched;
1350 if ($child_pid == $gurpmi_pid) {
1351 undef $gurpmi_pid;
1352
1353 my @services;
1354 if ($programs{$tool}{services_to_start_after_install}) {
1355 @services = @{$programs{$tool}{services_to_start_after_install}};
1356 run_program::raw({ detach => 1 }, 'service', $_, 'restart') foreach @services;
1357 }
1358
1359 # refresh the icon list if some package got installed (eg: system-config-printer)
1360 build_list();
1361 load_view();
1362 }
1363 }
1364 undef $pid_exp if $pid_exp eq $child_pid;
1365 } while $child_pid > 0;
1366 # child unexpectedly died (cleanup since child_just_exited won't be called by plug-removed since plug never was added)
1367 return if $o_is_cleaner || !$left_locked;
1368 child_just_exited();
1369 splash_warning(N("This program has exited abnormally"));
1370 }
1371
1372
1373 #-------------------------------------------------------------
1374 # mcc dialog specific functions
1375
1376 sub splash_warning {
1377 my ($label, $o_cancel_button) = @_;
1378 warn_dialog(N("Warning"), $label, { cancel => $o_cancel_button });
1379 }
1380
1381 sub new_dialog {
1382 my ($title, $o_no_button) = @_;
1383 my $dialog = gtkset_border_width(Gtk2::Dialog->new, 10);
1384 $dialog->set_transient_for($window_global);
1385 $dialog->set_position('center-on-parent');
1386 $dialog->set_title($title);
1387 $dialog->action_area->pack_start(gtkadd(Gtk2::HButtonBox->new,
1388 gtksignal_connect(Gtk2::Button->new(N("Close")), clicked => sub { $dialog->destroy })
1389 ),
1390 0,0,0) unless $o_no_button;
1391 gtkset_modal($dialog, 1);
1392 }
1393
1394 sub more_themes() {
1395 my $window_about = new_dialog(N("More themes"));
1396 gtkpack_($window_about->vbox,
1397 0, Gtk2::Label->new(N("Getting new themes")),
1398 0, gtkadd(gtkset_shadow_type(gtkset_border_width(Gtk2::Frame->new(N("Additional themes")), 10), 'etched_out'),
1399 gtkpack(Gtk2::HBox->new(0, 5),
1400 N("Get additional themes on www.damz.net"),
1401 )
1402 )
1403 );
1404 $window_about->show_all;
1405 }
1406
1407 sub about_mga_cc() {
1408 my $window_about = new_dialog(N("About - %s Control Center", $branding));
1409 my $tree_model = Gtk2::TreeStore->new("Glib::String", "Glib::String", "Glib::String");
1410 my $credits = Gtk2::TextView->new;
1411 my $list = Gtk2::TreeView->new_with_model($tree_model);
1412 $list->can_focus(0);
1413 each_index { $list->append_column(Gtk2::TreeViewColumn->new_with_attributes(undef, Gtk2::CellRendererText->new, 'text' => $::i)) } 0..1;
1414 $list->set_headers_visible(0);
1415
1416 foreach my $row ([ N("Authors: "), '' ],
1417 [ '', 'Chmouel Boudjnah' ],
1418 [ '', 'Damien "dam\'s" Krotkine',
1419 #-PO "perl" here is the programming language
1420 N("(perl version)") ],
1421 [ '', 'Daouda Lo' ],
1422 [ '', 'Thierry Vignaud' ],
1423 [ '', 'Yves Duret' ],
1424 [ '', '' ],
1425 [ N("Artwork: "), '', '' ],
1426 [ '', 'Anh-Van Nguyen' ],
1427
1428 [ '',
1429 #-PO If your language allows it, use eacute for first "e" and egrave for 2nd one.
1430 N("Helene Durosini"), '<ln@mandriva.com>' ],
1431 ) {
1432 $tree_model->append_set(undef, [ map_index { $::i => $_ } @$row ]);
1433 }
1434
1435 my ($previous_type, $not_first_title, $not_first_block);
1436 my $locale = lang::read;
1437 require Gtk2::Pango;
1438 foreach my $line (grep { $_ ne "\n" && !/^#/ } cat_(top(glob("/usr/share/doc/mageia-release-*/CREDITS.$locale->{lang}")))) {
1439 if (my ($type, $comment, $contributor) = split(/\|/, $line, 3)) {
1440 last if !$type;
1441 $comment =~ s/^ //; # fix initial space of first section (CREDITS format should be enhanced to specify lines that really are sections)
1442 chomp($contributor);
1443 if ($previous_type ne $type) {
1444 gtktext_append($credits, [ [ join('', if_($not_first_title, "\n"), translate(common::to_utf8($type)), "\n"),
1445 { 'weight' => Gtk2::Pango->PANGO_WEIGHT_BOLD, scale => Gtk2::Pango->scale_large } ] ]);
1446 $previous_type = $type;
1447 $not_first_title = 1;
1448 }
1449 if ($contributor) {
1450 gtktext_append($credits,
1451 #-PO: this is used as "language: translator" in credits part of the about dialog:
1452 N("- %s: %s\n", map { translate($_) } $comment, $contributor)
1453 );
1454 } else {
1455 $comment = $comment . "\n" if !$not_first_block; # fix spacing before second title;
1456 gtktext_append($credits, join('', if_($not_first_block, "- "), translate($comment)));
1457 $not_first_block = 1;
1458 }
1459 }
1460 }
1461
1462
1463 # Give our translators the ability to show their family and
1464 # friends that thez participated ...
1465
1466 #-PO Add your Name here to find it in the About section in your language.
1467 my $translator_name = N("_: NAME OF TRANSLATORS\nYour names");
1468 #-PO Add your E-Mail address here if you want to show it in the about doialog.
1469 my $translator_email = N("_: EMAIL OF TRANSLATORS\nYour emails");
1470 if ($translator_name ne "Your names" && 0) {
1471 $tree_model->append_set(undef, [ 0 => $_->[0], 1 => $_->[1] ]) foreach [ '', '' ], [ N("Translator: ") ];
1472 $tree_model->append_set(undef, [ 0 => $_->[0], 1 => $_->[1] ]) foreach [ '', $translator_name, $translator_email ];
1473 }
1474 $list->get_selection->set_mode('none');
1475
1476 gtkpack_($window_about->vbox,
1477 (0, Gtk2::Banner->new('/usr/share/icons/large/drakconf.png',
1478 #-PO: Here, first %s will be replaced by 'Mageia'
1479 #-PO: second %s will be replaced by the version (eg: "Mageia 1 (Free) Control Center")
1480 N("%s %s (%s) Control Center",
1481 $branding, @$release{qw(version product)}))),
1482 0, Gtk2::Label->new(""),
1483 0, Gtk2::Label->new(
1484 #-PO: here %s is eg: "1999-2008"
1485 N("Copyright (C) %s Mandriva SA", '1999-2008') . "\n" . N("Copyright (C) %s Mageia", '2011') . "\n" ),
1486 0, Gtk2::HSeparator->new,
1487 0, Gtk2::Label->new(""),
1488 1, my $n = Gtk2::Notebook->new,
1489 );
1490
1491 add2notebook($n, N("Authors"), $list);
1492 add2notebook($n, N("Mageia Contributors"), gtkset_size_request(create_scrolled_window($credits), 650, 50));
1493 $n->set_current_page(0);
1494
1495 $window_about->show_all;
1496 }
1497
1498
1499 #-------------------------------------------------------------
1500 # mcc specific graphic functions:
1501
1502
1503 sub set_page {
1504 my ($index) = @_;
1505 start_logdrake();
1506 set_page_raw($index);
1507 hide_buttons();
1508 }
1509
1510 sub hide_buttons() {
1511 $buttons->hide;
1512 $cancel->hide;
1513 }
1514
1515
1516 sub create_packtable2 {
1517 my ($options, @l) = @_;
1518 my $w = Gtk2::Table->new(0, 0, 1);
1519 add2hash_($options, { xpadding => 5, ypadding => 0 });
1520 each_index {
1521 my ($i, $l) = ($::i, $_);
1522 each_index {
1523 my $j = $::i;
1524 if ($_) {
1525 ref $_ or $_ = gtknew('WrappedLabel', text => $_);
1526 $w->attach($_, $j, $j + 1, $i, $i + 1, ['expand', 'fill'], ['expand', 'fill'], $options->{xpadding}, $options->{ypadding});
1527 $_->show;
1528 }
1529 } @$l;
1530 } @l;
1531 $w->set_col_spacings($options->{col_spacings} || 0);
1532 $w->set_row_spacings($options->{row_spacings} || 0);
1533 gtkset_border_width($w, $::isInstall ? 3 : 10);
1534 }
1535
1536 #-------------------------------------------------------------
1537 # mcc specific graphic functions:
1538
1539 sub render_shiner {
1540 my ($pixbuf, $shine_value) = @_;
1541 my $new_pixbuf = (mygtk2::_new_alpha_pixbuf($pixbuf))[2];
1542 $pixbuf->saturate_and_pixelate($new_pixbuf, $shine_value, 0);
1543 $new_pixbuf;
1544 }
1545
1546 sub scale {
1547 my ($pixbuf, $gain) = @_;
1548 my ($width, $height) = ($pixbuf->get_height, $pixbuf->get_width);
1549 $pixbuf->scale_simple($height+$gain, $width+$gain, 'hyper');
1550 }
1551
1552
1553 1;

Properties

Name Value
svn:executable *

  ViewVC Help
Powered by ViewVC 1.1.30