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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 8568 - (show annotations) (download)
Wed Jun 26 13:39:23 2013 UTC (10 years, 9 months ago) by tv
File size: 58810 byte(s)
further delay event for slow machines (mga#10289)
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, 85 ],
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', 'mcc-networksharing',
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 mygtk2::register_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"),
627 #-PO: "<control>" must _NOT_ be translated. This is a keyboard shortcut for "Quit".
628 #-PO: you just have to select the proper letter for your language (eg: english: "Quit" => "Q")
629 N("<control>Q"), \&quit_global, undef, '<Item>', N("Quit") ],
630 [ N("/_Options"), undef, undef, undef, '<Branch>' ],
631 [ join('', @{$options{show_log}}), undef,
632 sub {
633 $option_values{show_log} = $check_boxes{show_log}->get_active;
634 if ($option_values{show_log}) {
635 start_logdrake();
636 } else {
637 kill_logdrake();
638 }
639 },
640 undef, '<CheckItem>'
641 ],
642
643 if_(0 && $isWiz,
644 [ join('', @{$options{wiz_expert}}), undef,
645 sub { $option_values{expert_wizard} = $check_boxes{wiz_expert}->get_active },
646 undef, '<CheckItem>',
647 ],
648 ),
649 if_(@themes > 1,
650 [ N("/_Themes"), undef, undef, undef, '<Branch>' ],
651 (map {
652 my $name = $_;
653 [ N("/_Themes") . "/" . ($name eq $theme ? " O " : " ") . "_$_", undef,
654 sub {
655 return if $theme eq $name;
656 !$pending_app || splash_warning(N("This action will restart the control center.\nAny change not applied will be lost."), 1) and do {
657 # embedded app must be killed
658 kill_children();
659 kill_logdrake();
660 child_just_exited();
661 exec "$0 --theme $name";
662 };
663 }, undef, '<CheckItem>'
664 ];
665 } @themes),
666 [ N("/_Themes") . N("/_More themes"), undef, \&more_themes, undef, '<Item>' ]
667 ),
668 [ N("/_Help"), undef, undef, undef, '<Branch>' ],
669 [ N("/_Help") . N("/_Help"), undef, \&run_help, undef, '<Item>', N("Help") ],
670 [ N("/_Help") . N("/_Release notes"), undef, sub { run_browser('Release_Notes') }, undef, '<Item>', N("Help") ],
671 [ N("/_Help") . N("/What's _New?"), undef, sub { run_browser("What's New?") }, undef, '<Item>', N("Help") ],
672 [ N("/_Help") . N("/_Errata"), undef, sub { run_browser('Errata') }, undef, '<Item>', N("Help") ],
673 [ N("/_Help") . N("/_Report Bug"), undef, sub {
674 run_program::raw({ detach => 1, as_user => 1 }, 'drakbug', '--report', (split(/\s/, $pending_app))[0] || 'drakconf');
675 }, undef, '<Item>' ],
676 [ N("/_Help") . N("/_About..."), undef, \&about_mga_cc, undef, '<Item>' ]
677 );
678
679
680 sub run_help() {
681 run_program::raw({ detach => 1, as_user => 1 }, 'drakhelp', '--id', $help_on_context);
682 }
683
684 sub run_browser {
685 my ($url) = @_;
686 $url = "http://wiki.mageia.org/en/$release->{distribution}_$release->{version}_$url" if $url !~ m!^http://!;
687 run_program::raw({ detach => 1, as_user => 1 }, '/usr/bin/www-browser', $url);
688 }
689
690 my ($menu, $factory) = create_factory_menu($window_global, @menu_items);
691
692 # to retrieve a path, one must prevent "accelerators completion":
693 sub get_path { join('', map { my $i = $_; $i =~ s/_//g; $i } @_) }
694
695 %check_boxes = map {
696 $_ => $factory->get_widget("<main>" . get_path(@{$options{$_}}));
697 } ('show_log', if_(0 && $isWiz, "wiz_expert"));
698
699 my @buttons;
700 my $offset = 15;
701
702 $view = gtknew('WebKit_View', no_popup_menu => 1);
703 # so that it exists when building steps:
704 my $banner_notebook = Gtk2::Notebook->new;
705 build_list();
706
707 gtkadd($window_global,
708 gtkpack_(Gtk2::VBox->new(0, 0),
709 0, $menu,
710 #0, $banner_notebook,
711 0, Gtk2::HSeparator->new,
712 # 0, gtkset_size_request(Gtk2::VBox->new(10, 10), -1, 2),
713 1, gtkpack_(Gtk2::HBox->new(0, 0),
714 1, $steps = gtknew('MDV_Notebook', parent_window => $window_global, children => [ #Layout Fixed
715 # 145 is the vertical offset in order to be below the actual logo:
716 [ gtknew('VBox', widget_name => 'Steps', spacing => 0, width => (192 - $offset),
717 children_tight => [ map {
718 gtknew('HBox', spacing => 0, children => [
719 1, $_,
720 0, gtknew('Alignment', width => 12),
721 ]);
722 } @buttons ]), 0, 100 ],
723 ], right_child => gtknew('ScrolledWindow', child => gtkset_border_width($view, 5),
724 no_shadow => 1, h_policy => 'never')),
725 1, gtkpack(my $emb_box = Gtk2::VBox->new(0, 0),
726 my $wait_darea = gtkset_size_request(Gtk2::DrawingArea->new, -1, -1),
727 ),
728 ),
729 0, Gtk2::HSeparator->new,
730 0, my $buttons = gtkadd(gtkset_layout(Gtk2::HButtonBox->new, 'start'),
731 map { gtkset_border_width($_, 3) }
732 gtksignal_connect(my $cancel = Gtk2::Button->new(N("Cancel")),
733 clicked => sub {
734 stop_wait_area();
735 kill_children();
736 child_just_exited();
737 }),
738 ),
739 )
740 );
741
742 $view->set_size_request(-1, -1);
743
744 $window_global->signal_connect(delete_event => \&quit_global);
745
746 my $accel = Gtk2::AccelGroup->new;
747 $accel->connect(Gtk2::Gdk->keyval_from_name('F1'), [], ['visible'], \&run_help);
748 $window_global->add_accel_group($accel);
749
750 use POSIX qw(:sys_utsname_h :math_h :sys_wait_h :unistd_h);
751 my (undef, $nodename) = POSIX::uname();
752 $window_global->set_title(N("%s Control Center %s [on %s]", $branding, $version, $nodename));
753 $window_global->set_position('center');
754
755 foreach my $notebook ($banner_notebook) {
756 $notebook->set_property('show-border', 0);
757 $notebook->set_property('show-tabs', 0);
758 }
759
760
761 # banner :
762
763 #add2notebook($banner_notebook, "", Gtk2::Banner->new("/usr/share/icons/large/drakconf.png",
764 # N("Welcome to the %s Control Center", $branding)));
765
766
767 my ($_hand_cursor, $wait_cursor) = map { Gtk2::Gdk::Cursor->new($_) } qw(hand2 watch);
768
769 my $left_locked = 0;
770
771 #my $spacing = 25;
772
773 my %tool_callbacks;
774
775 my ($page_count);
776
777
778 my $conf_file = '/etc/sysconfig/mcc.conf';
779 foreach (cat_($conf_file)) {
780 #s/^ENABLE_//;
781 #my ($key, $val) = /^(.*)=(.*)/;
782 if (my ($key, $val) = /^ENABLE_(.*)=(.*)/) {
783 $key =~ s/_/ /g;
784 #warn "--> ($key, $val)\n";
785 $programs{$key}{disabled} = 1 if $val ne 'yes';
786 warn ">> disabling $key\n" if $val ne 'yes';
787 } else {
788 warn "bogus line in $conf_file: $_\n";
789 next;
790 }
791 }
792
793 sub load_packages2install() {
794 my $progs_conf_file = '/usr/share/mcc/progs.conf';
795 foreach (cat_($progs_conf_file)) {
796 #if (my ($key, $val) = /^USE_WRAPPER_FOR_(.*)=(.*)/) {
797 if (my ($key, $val) = /^INSTALL_FOR_(.*)=(.*)/) {
798 $key =~ s/_/ /g;
799 # we'll use gurpmi in order to install missing packages if needed;
800 $programs{$key}{packages2install} = $val if $val;
801 } else {
802 warn "bogus line in $conf_file: $_\n";
803 next;
804 }
805 }
806 }
807
808 sub clean_list {
809 my ($subtree) = @_;
810 grep {
811 my $stuff = $_;
812 my $exec = real_bin_path($programs{$stuff}{binary});
813 my $is_present = -x $exec;
814 if (!$is_present && $programs{$stuff}{packages2install}) {
815 $is_present = 1;
816 # override missing icon:
817 $programs{$stuff}{real_icon} ||= $programs{$stuff}{icon};
818 $programs{$stuff}{icon} = 'installremoverpm';
819 } elsif ($programs{$stuff}{real_icon}) {
820 $programs{$stuff}{icon} = $programs{$stuff}{real_icon};
821 }
822 # do not complain about missing entries in move:
823 warn qq("$exec" is not executable [$stuff]) if $mga_rel !~ /Move/ && !$is_present && !$programs{$stuff}{disabled};
824 !$programs{$stuff}{hidden} && $is_present && !$programs{$stuff}{disabled};
825 } @$subtree;
826 }
827
828 sub build_widget_element {
829 my ($label) = @_;
830 my $icon = $programs{$label}{icon};
831
832 die "$label 's icon is missing" if !$programs{$label} && $::testing;
833 $tool_callbacks{$label} = sub {
834 run_tool($label, undef, #$event_box,
835 $icon, $programs{$label}{description}, $programs{$label});
836 };
837 # FIX ME: DO THIS AGAIN:
838 $tool_feedback{$label} = sub {}; #sub { $event_box->window && $event_box->window->set_cursor($hand_cursor) };
839 my $real_icon = $icon ? '<IMG SRC="' . mygtk2::_find_imgfile($icon) . '">' : '';
840 my @widgets = (
841 qq(<TD class="img">$real_icon</TD>),
842 qq(<TD style="text-align: $align"><DIV>)
843 . escape_text_for_TextView_markup_format($programs{$label}{description})
844 . qq(</DIV></TD>)
845 );
846 qq(<TD WIDTH="49%">
847 <A HREF="$label"><TABLE align="$align2" ID="subtable"><TR>
848 @widgets
849 </TR></TABLE></A></TD>
850 );
851 }
852
853 my (@strings, $current_string_idx);
854 sub load_view() {
855 $view->load_html_string($strings[$current_string_idx], 'file:///');
856 }
857
858 sub build_list() {
859 my $index = 0;
860 load_packages2install();
861 my $i;
862 foreach (@tree) {
863 my ($text, $_icon, $help, $subtrees) = @$_;
864
865 my @subtrees = grep { $_->{list} = [ clean_list($_->{list}) ]; !is_empty_array_ref($_->{list}) } @$subtrees;
866
867
868 # Skip empty classes:
869 next if !@subtrees;
870 $i++;
871
872
873 my $my_index = $index++;
874 my $square_icon_uri = mygtk2::_find_imgfile('cadre-ic');
875 my $back_img = mygtk2::_find_imgfile('right-white-background_right_part_768.png');
876 my $string = join("\n", qq(<HTML>
877 <HEAD>
878 <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
879 <style type="text/css">
880 body {
881 // background-color: #ecf0f2;
882 // background-image: url($back_img);
883 background-repeat: no-repeat; /*pas de répition de l'image*/
884 background-attachment: fixed;
885 background-position: top left
886 }
887 p {text-align: $align}
888 td {text-align: $align}
889 #title {
890 text-align: $align;
891 color: #grey;
892 font-weight: bold;
893 margin-left: 13px;
894 margin-top: 16px;
895 margin-bottom: 8px;
896 }
897 #top_margin {
898 margin-top: 30px;
899 }
900 #block {
901 margin-left: 4px;
902 margin-bottom: 24px;
903 border-spacing: 8px 0px;
904 }
905 #subtable {
906 border-spacing: 8px 8px;
907 }
908 td.img {
909 background-image: url($square_icon_uri);
910 background-repeat: no-repeat;
911 background-position: center center;
912 width: 60; height: 60;
913 text-align: center;
914 }
915 hr {
916 background-color: #eef2f6;
917 margin-left: 21px;
918 margin-right: 22px;
919 height: 1;
920 border: 0;
921 }
922 tr {text-align: $align}
923 td {
924 margin-left: 10px;
925 margin-right: 10px;
926 }
927 ),
928 if_(mygtk2::text_direction_rtl(), " a { direction: rtl; unicode-bidi: embed }"), qq(
929 a:link {color:black; text-decoration:none }
930 a:visited {color:black; text-decoration:none }
931 a:hover {color:grey }
932 // a:active {color:black; text-decoration:none }
933 </style>
934
935 </HEAD>
936 <BODY>
937 ));
938
939
940
941 # Create right notebook pages :
942
943 my $section;
944 foreach my $subtree (@subtrees) {
945 $string .= $section++ ? "<hr NOSHADE>\n" : '<div ID="top_margin"></div>';
946 my $title = mygtk2::asteriskize($subtree->{title});
947 $string .= qq(
948 <div ID="title">$title</div>
949 <TABLE BORDER=0 WIDTH="100%" ID="block">
950 );
951 if (@{$subtree->{list}} % 2) {
952 my @widgets = (pop @{$subtree->{list}}, "");
953 @widgets = reverse @widgets if mygtk2::text_direction_rtl();
954 push @{$subtree->{list}}, @widgets;
955 }
956 $string .= join("\n",
957 map {
958 "<TR>" . join("\n", grep { defined $_ } @$_) . "</TR>" }
959 # "<TR>" . join("\n<TD> </TD>\n", grep { defined $_ } @$_) . "</TR>" }
960 group_by(2, map { $_ ? build_widget_element($_) : '<TD></TD>' } @{$subtree->{list}})
961 );
962
963 $string .= "</TABLE>\n";
964 }
965 # b/c we use Pango text markup language, we've to protect '&' caracter:
966 $text =~ s/&/&amp;/g;
967 $page_count++;
968
969 $string .= qq(</BODY></HTML>);
970 if ($save_html) {
971 mkdir_p('/tmp/mcc');
972 MDK::Common::File::output_utf8("/tmp/mcc/$i.html", $string);
973 }
974
975 $strings[$my_index] = $string;
976 push @buttons, gtknew('Button', relief => 'none', child =>
977 gtknew('Label_Right', text_markup => qq(<small>$text</small>), ellipsize => 'end'),
978 clicked => sub {
979 $current_string_idx = $my_index;
980 load_view();
981 $steps->move_selection($_[0]->child);
982 $banner_notebook->set_current_page($my_index);
983 $help_on_context = $help;
984 },
985 );
986
987 }
988 }
989
990 $view->signal_connect('navigation-requested' =>
991 sub {
992 my (undef, undef, $request) = @_;
993 my $res = 'ignore';
994
995 # get the actual program ID:
996 my $url = eval { Glib::filename_from_uri($request->get_uri) };
997 $url =~ s!^/*!!; # not a path
998
999 # workaround wekbit calling navigation-requested with "/":
1000 return 'accept' if !$url;
1001
1002 # url can be a translated UTF-8 string (eg: for CD/DVD entries):
1003 c::set_tagged_utf8($url);
1004
1005 # do not crash on eg: "reload":
1006 if (!$tool_callbacks{$url}) {
1007 warn "Warning: invalid tool name: $url\n";
1008 return $res;
1009 }
1010 $tool_callbacks{$url}->();
1011 # FIXME: the following code is currently useless:
1012 # should we provide a way to kill buggy embedded programs ?
1013 return $res if $left_locked;
1014 warn_on_startup();
1015 return $res;
1016 });
1017
1018 my %icons = (
1019 );
1020
1021 # manage tools not present in MCC (localedrake, drakauth, ...):
1022 foreach my $label (difference2([ keys %programs ], [ keys %tool_callbacks ])) {
1023 my $text = $programs{$label}{description};
1024 $tool_callbacks{$label} = sub { run_tool($label, undef, $icons{$label} || 'wizard-mdk', $text, $programs{$label}) };
1025 $tool_feedback{$label} = sub {};
1026 }
1027
1028
1029 foreach (keys %check_boxes) {
1030 my $widget = $check_boxes{$_};
1031 if (defined $widget) {
1032 $widget->set_active($option_values{$_});
1033 } else {
1034 print STDERR qq(BUG with LANGUAGE "$ENV{LANGUAGE}" for "$_"\n);
1035 err_dialog(N("Error"), N("There's a bug in translations of your language (%s)
1036
1037 Please report that bug.", $ENV{LANGUAGE}));
1038 }
1039 }
1040
1041 # "wait while launching a program" area :
1042
1043 my ($run_pixbuf, $run_counter, $run_counter_add, %run_pixbufs);
1044
1045 sub stop_wait_area() {
1046 $wait_darea->hide;
1047 Glib::Source->remove($timeout) if $timeout;
1048 undef %run_pixbufs;
1049 }
1050
1051 $wait_darea->signal_connect(expose_event => sub {
1052 my ($w) = @_;
1053 return if !$wait_darea->realized;
1054 return unless $run_pixbuf; # some people got an expose event before we start an embedded tool
1055 return unless $wait_darea->{size};
1056 $wait_darea->{layout} ||= $wait_darea->create_pango_layout(N("Loading... Please wait"));
1057 my $pixbuf = $run_pixbufs{$run_counter} ||= mygtk2::_pixbuf_render_alpha($run_pixbuf, $run_counter);
1058 if (!$wait_darea->{first_expose}) {
1059 $wait_darea->{first_expose} = 1;
1060 my $size = $wait_darea->{size};
1061 my ($d_width, $d_height) = ($size->width, $size->height);
1062 ($w->{pix_width}, $w->{pix_height}) = ($pixbuf->get_width, $pixbuf->get_height);
1063 my ($txt_width, $txt_height) = $wait_darea->{layout}->get_pixel_size;
1064 $w->{pix_yy} = ($d_width - $w->{pix_width})/2;
1065 $w->{pix_xx} = ($d_height - $w->{pix_height} - $txt_height)/2;
1066 $w->{text_yy} = $w->{pix_yy} + ($w->{pix_width} - $txt_width)/2;
1067 $w->{text_xx} = $w->{pix_xx} + $w->{pix_height} + 5;
1068 }
1069 $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);
1070 my $style = $wait_darea->{style} ||= $wait_darea->get_style;
1071 $wait_darea->window->draw_layout($style->text_gc('normal'), $w->{text_yy}, $w->{text_xx}, $w->{layout});
1072 $run_counter += $run_counter_add;
1073 $run_counter_add = -$run_counter_add if $run_counter < 100 || 255-$run_counter_add < $run_counter;
1074 });
1075
1076 gtkflush();
1077
1078 # display first page (we use a timeout so that Y position of widgets is know):
1079 Glib::Timeout->add(100, sub { $buttons[0]->signal_emit('clicked'); 0 });
1080
1081 $window_global->show_all;
1082
1083 hide_buttons();
1084 $emb_box->hide;
1085 $wait_darea->realize;
1086
1087 $SIG{USR1} = 'IGNORE';
1088 $SIG{USR2} = 'IGNORE';
1089 $SIG{TERM} = \&quit_global;
1090
1091
1092 $window_splash->destroy;
1093 undef $window_splash;
1094 Glib::Timeout->add(400, sub { $SIG{CHLD} = \&sig_child; sig_child('CHLD', 1); 1 });
1095
1096 if ($program) {
1097 if (my $sub = $tool_callbacks{$program}) {
1098 Glib::Timeout->add(500, sub { $sub->(); 0 });
1099 } else {
1100 err_dialog(N("Error"), N("Impossible to run unknown '%s' program", $program));
1101
1102 }
1103 }
1104
1105 Gtk2->main;
1106
1107
1108 sub group_by {
1109 my $nb = shift @_;
1110 my @l;
1111 for (my $i = 0; $i < @_; $i += $nb) {
1112 push @l, [ map { $_[$_] } $i..$i+$nb-1 ]; # $_[$i], $_[$i+1], $_[$i+2] ];
1113 }
1114 @l;
1115 }
1116
1117 sub warn_on_startup() {
1118 if ($pending_app) {
1119 return if !splash_warning(N("The modifications done in the current module won't be saved."), 1);
1120 kill_children();
1121 child_just_exited();
1122 }
1123 }
1124
1125 #-------------------------------------------------------------
1126 # socket/plug managment
1127
1128 # called once embedded tool has exited
1129 sub child_just_exited() {
1130 $pending_app = 0;
1131 $left_locked = 0;
1132 if ($emb_socket) {
1133 $emb_socket->destroy;
1134 undef $emb_socket;
1135 }
1136 $emb_box->hide;
1137 hide_buttons();
1138 $cancel->hide;
1139 gtkset_mousecursor_normal();
1140 foreach my $w ($steps, $banner_notebook) {
1141 $w->show;
1142 }
1143
1144 stop_wait_area();
1145 }
1146
1147 sub hide_socket_and_clean() {
1148 $emb_box->hide;
1149 $pending_app = 0;
1150 }
1151
1152 sub create_hidden_socket {
1153 my ($icon, $label) = @_;
1154 my $banner;
1155 gtkpack_($emb_box,
1156 0, $banner = gtkpack__(Gtk2::VBox->new(0, 0), Gtk2::Banner->new($icon, $label),
1157 Gtk2::HSeparator->new,
1158 ),
1159 1, gtksignal_connect($emb_socket = Gtk2::Socket->new, 'plug-removed' => sub {
1160 $menu->show if $application_driven_menu;
1161 $banner->destroy;
1162 child_just_exited();
1163 }));
1164 $banner->hide;
1165 # signal emitted when embedded apps begin to draw:
1166 $emb_socket->signal_connect('plug-added' => sub {
1167 $banner_notebook->hide;
1168 if ($application_driven_menu) {
1169 $menu->hide;
1170 } else {
1171 $banner->show;
1172 }
1173 stop_wait_area();
1174 $left_locked = 0;
1175 hide_buttons();
1176 $buttons->hide;
1177 return if !$emb_socket;
1178 $emb_socket->show;
1179 $emb_socket->can_focus(1);
1180 $emb_socket->grab_focus;
1181 #$emb_socket->window->XSetInputFocus; #only need by console (no more embedded until we've vte/zvt binding)
1182 });
1183 $emb_box->set_focus_child($emb_socket);
1184 $emb_socket->hide;
1185 }
1186
1187
1188 #-------------------------------------------------------------
1189 # processes managment
1190
1191 # embedded processes pid will be stocked there
1192 my @pid_launched;
1193
1194 # logdrake pid are stocked here
1195 my $pid_exp;
1196
1197 sub fork_ {
1198 my ($prog, $o_pid_table) = @_;
1199 $o_pid_table ||= \@pid_launched;
1200 my $pid = fork();
1201 if (defined $pid) {
1202 !$pid and do { exec($prog) or POSIX::_exit(1) }; # immediate exit, else forked gtk+ object destructors will badly catch up parent mcc
1203 push @$o_pid_table, $pid;
1204 return $pid;
1205 } else {
1206 splash_warning(N("cannot fork: %s", "$!"));
1207 child_just_exited();
1208 }
1209 }
1210
1211 sub real_bin_path {
1212 my ($prog) = @_;
1213 first(split /\s+/, $prog);
1214 }
1215
1216 sub run_tool {
1217 my ($label, $box, $icon, $text, $tool) = @_;
1218 my ($exec, $gtkplug) = @$tool{qw(binary embedded)};
1219 $application_driven_menu = $tool->{application_driven_menu};
1220 return if $tool_pids{$label};
1221 my $will_run_gurpmi;
1222 if (! -x real_bin_path($exec)) {
1223 if ($tool->{packages2install}) {
1224 # gurpmi doesn't support being embedded yet:
1225 $gtkplug = -1;
1226 $exec = join(' ', "$bindir/gurpmi", split(/\s/, $tool->{packages2install}));
1227 $will_run_gurpmi = 1;
1228 } else {
1229 splash_warning(N("cannot fork and exec \"%s\" since it is not executable", $exec));
1230 return;
1231 }
1232 }
1233 $exec .= " --summary" if $option_values{expert_wizard} && $exec =~ /drakwizard/;
1234 my $embedded = $gtkplug != -1; # not "explicitely not embedded"
1235 if ($embedded) {
1236 $steps->hide;
1237 create_hidden_socket($icon, $text);
1238 $emb_box->show;
1239 $emb_socket->realize;
1240 $pending_app = $tool->{binary};
1241 if ($gtkplug > 0) {
1242 $buttons->show;
1243 $exec .= " --embedded " . $emb_socket->get_id;
1244 $wait_darea->show;
1245 $cancel->show;
1246 $run_pixbuf = eval { gtkcreate_pixbuf($icon . "_128") };
1247 $run_counter = 255;
1248 $run_counter_add = -5;
1249 undef $wait_darea->{color};
1250 undef $wait_darea->{size};
1251 undef $wait_darea->{first_expose};
1252 $wait_darea->{not_yet_complete} = 1;
1253 $timeout = Glib::Timeout->add(35, sub {
1254 $wait_darea->{size} ||= $wait_darea->allocation;
1255 my $style = $wait_darea->{style} ||= $wait_darea->get_style;
1256 my $bg = $wait_darea->{bg} ||= $style->bg('normal');
1257 my $base = $wait_darea->{base} ||= $style->base('normal');
1258 my $color = $wait_darea->{color} ||= $base;
1259 # $base -> $bg
1260 my @colors = ([ $color->red, $bg->red ],
1261 [ $color->green, $bg->green ],
1262 [ $color->blue, $bg->blue ]);
1263 if ($wait_darea->{not_yet_complete} && any { $_->[0] != $_->[1] } @colors) {
1264 $wait_darea->window->set_background($color);
1265 $wait_darea->{color} = gtkcolor(map { $_->[0] - min(300, $_->[0] - $_->[1]) } @colors);
1266 $wait_darea->queue_draw;
1267 } elsif ($wait_darea->{not_yet_complete}) {
1268 # set exact color
1269 $wait_darea->window->set_background($bg);
1270 $wait_darea->queue_draw;
1271 $wait_darea->{not_yet_complete} = 0;
1272 } else {
1273 my $w = $wait_darea;
1274 $wait_darea->queue_draw_area($w->{pix_yy}, $w->{pix_xx}, $w->{pix_width}, $w->{pix_height});
1275 }
1276 1;
1277 });
1278 $left_locked = 1;
1279 $buttons->show;
1280 $tool_pids{$label} = fork_($exec);
1281 }
1282 } else { # not embedded
1283 # fix #3415 when $gtkplug eq -1
1284 local $option_values{embedded} = 0;
1285 $tool_pids{$label} = fork_($exec);
1286 $gurpmi_pid = $tool_pids{$label} if $will_run_gurpmi;
1287 }
1288 start_logdrake();
1289 $box->window->set_cursor($wait_cursor) if $box;
1290 }
1291
1292 sub start_logdrake() {
1293 # (re)start logdrake if needed
1294 if ($option_values{show_log} && !$pid_exp) {
1295 my $exec_log = "logdrake --explain=drakxtools";
1296 $pid_exp = fork_($exec_log, []);
1297 }
1298
1299 }
1300
1301 sub kill_them_all {
1302 foreach my $pid (@_) {
1303 kill('TERM', $pid) if $pid;
1304 }
1305 }
1306
1307 sub kill_children() {
1308 kill_them_all(@pid_launched);
1309 }
1310
1311 sub kill_logdrake() {
1312 kill_them_all($pid_exp) if $pid_exp;
1313 }
1314
1315 sub quit_global() {
1316 return 1 if mygtk2::quit_popup();
1317
1318 if (@pid_launched) {
1319 &kill_children();
1320 return 1; # tell gtk+ not to quit
1321 }
1322 &kill_children();
1323 &kill_logdrake();
1324 my ($x, $y) = $window_global->get_size;
1325 setVarsInSh($conffile, {
1326 LOGS => bool2text($option_values{show_log}),
1327 EXPERT_WIZARD => bool2text($option_values{expert_wizard}),
1328 HEIGTH => $y,
1329 WIDTH => $x,
1330 THEME => $theme,
1331 });
1332 gtkset_mousecursor_normal();
1333 Gtk2::exit(0);
1334 standalone::exit(0);
1335 }
1336
1337
1338 #-------------------------------------------------------------
1339 # signals managment
1340
1341 # got when child died and gone in zombie state
1342 sub sig_child {
1343 my ($_sig, $o_is_cleaner) = @_;
1344 my $child_pid;
1345 do {
1346 $child_pid = waitpid(-1, POSIX::WNOHANG);
1347 if (my $tool = find { $tool_pids{$_} eq $child_pid } keys %tool_pids) {
1348 $tool_feedback{$tool}->();
1349 delete $tool_pids{$tool};
1350 @pid_launched = grep { $_ ne $child_pid } @pid_launched;
1351 if ($child_pid == $gurpmi_pid) {
1352 undef $gurpmi_pid;
1353
1354 my @services;
1355 if ($programs{$tool}{services_to_start_after_install}) {
1356 @services = @{$programs{$tool}{services_to_start_after_install}};
1357 run_program::raw({ detach => 1 }, 'service', $_, 'restart') foreach @services;
1358 }
1359
1360 # refresh the icon list if some package got installed (eg: system-config-printer)
1361 build_list();
1362 load_view();
1363 }
1364 }
1365 undef $pid_exp if $pid_exp eq $child_pid;
1366 } while $child_pid > 0;
1367 # child unexpectedly died (cleanup since child_just_exited won't be called by plug-removed since plug never was added)
1368 return if $o_is_cleaner || !$left_locked;
1369 child_just_exited();
1370 splash_warning(N("This program has exited abnormally"));
1371 }
1372
1373
1374 #-------------------------------------------------------------
1375 # mcc dialog specific functions
1376
1377 sub splash_warning {
1378 my ($label, $o_cancel_button) = @_;
1379 warn_dialog(N("Warning"), $label, { cancel => $o_cancel_button });
1380 }
1381
1382 sub new_dialog {
1383 my ($title, $o_no_button) = @_;
1384 my $dialog = gtkset_border_width(Gtk2::Dialog->new, 10);
1385 $dialog->set_transient_for($window_global);
1386 $dialog->set_position('center-on-parent');
1387 $dialog->set_title($title);
1388 $dialog->action_area->pack_start(gtkadd(Gtk2::HButtonBox->new,
1389 gtksignal_connect(Gtk2::Button->new(N("Close")), clicked => sub { $dialog->destroy })
1390 ),
1391 0,0,0) unless $o_no_button;
1392 gtkset_modal($dialog, 1);
1393 }
1394
1395 sub more_themes() {
1396 my $window_about = new_dialog(N("More themes"));
1397 gtkpack_($window_about->vbox,
1398 0, Gtk2::Label->new(N("Getting new themes")),
1399 0, gtkadd(gtkset_shadow_type(gtkset_border_width(Gtk2::Frame->new(N("Additional themes")), 10), 'etched_out'),
1400 gtkpack(Gtk2::HBox->new(0, 5),
1401 N("Get additional themes on www.damz.net"),
1402 )
1403 )
1404 );
1405 $window_about->show_all;
1406 }
1407
1408 sub about_mga_cc() {
1409 my $window_about = new_dialog(N("About - %s Control Center", $branding));
1410 my $tree_model = Gtk2::TreeStore->new("Glib::String", "Glib::String", "Glib::String");
1411 my $credits = Gtk2::TextView->new;
1412 my $list = Gtk2::TreeView->new_with_model($tree_model);
1413 $list->can_focus(0);
1414 each_index { $list->append_column(Gtk2::TreeViewColumn->new_with_attributes(undef, Gtk2::CellRendererText->new, 'text' => $::i)) } 0..1;
1415 $list->set_headers_visible(0);
1416
1417 foreach my $row ([ N("Authors: "), '' ],
1418 [ '', 'Chmouel Boudjnah' ],
1419 [ '', 'Damien "dam\'s" Krotkine',
1420 #-PO "perl" here is the programming language
1421 N("(perl version)") ],
1422 [ '', 'Daouda Lo' ],
1423 [ '', 'Thierry Vignaud' ],
1424 [ '', 'Yves Duret' ],
1425 [ '', '' ],
1426 [ N("Artwork: "), '', '' ],
1427 [ '', 'Anh-Van Nguyen' ],
1428
1429 [ '',
1430 #-PO If your language allows it, use eacute for first "e" and egrave for 2nd one.
1431 N("Helene Durosini"), '<ln@mandriva.com>' ],
1432 ) {
1433 $tree_model->append_set(undef, [ map_index { $::i => $_ } @$row ]);
1434 }
1435
1436 my ($previous_type, $not_first_title, $not_first_block);
1437 my $locale = lang::read;
1438 require Gtk2::Pango;
1439 foreach my $line (grep { $_ ne "\n" && !/^#/ } cat_(top(glob("/usr/share/doc/mageia-release-*/CREDITS.$locale->{lang}")))) {
1440 if (my ($type, $comment, $contributor) = split(/\|/, $line, 3)) {
1441 last if !$type;
1442 $comment =~ s/^ //; # fix initial space of first section (CREDITS format should be enhanced to specify lines that really are sections)
1443 chomp($contributor);
1444 if ($previous_type ne $type) {
1445 gtktext_append($credits, [ [ join('', if_($not_first_title, "\n"), translate(common::to_utf8($type)), "\n"),
1446 { 'weight' => Gtk2::Pango->PANGO_WEIGHT_BOLD, scale => Gtk2::Pango->scale_large } ] ]);
1447 $previous_type = $type;
1448 $not_first_title = 1;
1449 }
1450 if ($contributor) {
1451 gtktext_append($credits,
1452 #-PO: this is used as "language: translator" in credits part of the about dialog:
1453 N("- %s: %s\n", map { translate($_) } $comment, $contributor)
1454 );
1455 } else {
1456 $comment = $comment . "\n" if !$not_first_block; # fix spacing before second title;
1457 gtktext_append($credits, join('', if_($not_first_block, "- "), translate($comment)));
1458 $not_first_block = 1;
1459 }
1460 }
1461 }
1462
1463
1464 # Give our translators the ability to show their family and
1465 # friends that thez participated ...
1466
1467 #-PO Add your Name here to find it in the About section in your language.
1468 my $translator_name = N("_: NAME OF TRANSLATORS\nYour names");
1469 #-PO Add your E-Mail address here if you want to show it in the about doialog.
1470 my $translator_email = N("_: EMAIL OF TRANSLATORS\nYour emails");
1471 if ($translator_name ne "Your names" && 0) {
1472 $tree_model->append_set(undef, [ 0 => $_->[0], 1 => $_->[1] ]) foreach [ '', '' ], [ N("Translator: ") ];
1473 $tree_model->append_set(undef, [ 0 => $_->[0], 1 => $_->[1] ]) foreach [ '', $translator_name, $translator_email ];
1474 }
1475 $list->get_selection->set_mode('none');
1476
1477 gtkpack_($window_about->vbox,
1478 (0, Gtk2::Banner->new('/usr/share/icons/large/drakconf.png',
1479 #-PO: Here, first %s will be replaced by 'Mageia'
1480 #-PO: second %s will be replaced by the version (eg: "Mageia 1 (Free) Control Center")
1481 N("%s %s (%s) Control Center",
1482 $branding, @$release{qw(version product)}))),
1483 0, Gtk2::Label->new(""),
1484 0, Gtk2::Label->new(
1485 #-PO: here %s is eg: "1999-2008"
1486 N("Copyright (C) %s Mandriva SA", '1999-2008') . "\n" . N("Copyright (C) %s Mageia", '2011-2013') . "\n" ),
1487 0, Gtk2::HSeparator->new,
1488 0, Gtk2::Label->new(""),
1489 1, my $n = Gtk2::Notebook->new,
1490 );
1491
1492 add2notebook($n, N("Authors"), $list);
1493 add2notebook($n, N("Mageia Contributors"), gtkset_size_request(create_scrolled_window($credits), 650, 50));
1494 $n->set_current_page(0);
1495
1496 $window_about->show_all;
1497 }
1498
1499
1500 #-------------------------------------------------------------
1501 # mcc specific graphic functions:
1502
1503
1504 sub set_page {
1505 my ($index) = @_;
1506 start_logdrake();
1507 set_page_raw($index);
1508 hide_buttons();
1509 }
1510
1511 sub hide_buttons() {
1512 $buttons->hide;
1513 $cancel->hide;
1514 }
1515
1516
1517 sub create_packtable2 {
1518 my ($options, @l) = @_;
1519 my $w = Gtk2::Table->new(0, 0, 1);
1520 add2hash_($options, { xpadding => 5, ypadding => 0 });
1521 each_index {
1522 my ($i, $l) = ($::i, $_);
1523 each_index {
1524 my $j = $::i;
1525 if ($_) {
1526 ref $_ or $_ = gtknew('WrappedLabel', text => $_);
1527 $w->attach($_, $j, $j + 1, $i, $i + 1, ['expand', 'fill'], ['expand', 'fill'], $options->{xpadding}, $options->{ypadding});
1528 $_->show;
1529 }
1530 } @$l;
1531 } @l;
1532 $w->set_col_spacings($options->{col_spacings} || 0);
1533 $w->set_row_spacings($options->{row_spacings} || 0);
1534 gtkset_border_width($w, $::isInstall ? 3 : 10);
1535 }
1536
1537 #-------------------------------------------------------------
1538 # mcc specific graphic functions:
1539
1540 sub render_shiner {
1541 my ($pixbuf, $shine_value) = @_;
1542 my $new_pixbuf = (mygtk2::_new_alpha_pixbuf($pixbuf))[2];
1543 $pixbuf->saturate_and_pixelate($new_pixbuf, $shine_value, 0);
1544 $new_pixbuf;
1545 }
1546
1547 sub scale {
1548 my ($pixbuf, $gain) = @_;
1549 my ($width, $height) = ($pixbuf->get_height, $pixbuf->get_width);
1550 $pixbuf->scale_simple($height+$gain, $width+$gain, 'hyper');
1551 }
1552
1553
1554 1;

Properties

Name Value
svn:executable *

  ViewVC Help
Powered by ViewVC 1.1.30