#!/usr/bin/perl # $Id$ # Copyright (C) 1999-2007 Mandriva # Daouda Lo # Damien Krotkine # Thierry Vignaud # Yves Duret # # This program is free software; you can redistribute it and/or modify it under # the terms of the GNU General Public License as published by the Free Software # Foundation; either version 2, or (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. use strict; use diagnostics; use lib qw(/usr/lib/libDrakX); use c; use standalone; use common; use detect_devices; use lang; # i18n: IMPORTANT: to get correct namespace (drakconf instead of libDrakX) BEGIN { unshift @::textdomains, 'drakconf' } use mygtk2 qw(gtknew); use ugtk2 qw(:create :dialogs :helpers :wrappers); use Gtk2::Pango; use Gtk2::Html2; #------------------------------------------------------------- # paths my ($bindir, $sbindir, $xbindir) = ("/usr/bin", "/usr/sbin", "/usr/X11R6/bin"); my $mcc_dir = "/usr/share/mcc"; my $themes_dir = "$mcc_dir/themes/"; my (%tool_pids, %tool_feedback); my ($version, $conffile, $class_install) = (`cat /etc/mandrakelinux-release` =~ /\b(\d+\.{1}.+\))/, "/etc/mcc.conf", "/etc/sysconfig/system"); my $root_size = join('x', gtkroot()->get_size()); my ($default_width, $default_heigth) = member($root_size, '640x480', '800x600') ? (720, 523) : (800, 600); require_root_capability() if !$::testing; # just to get root capabilities #------------------------------------------------------------- # read configuration, set themes, ... my %h = getVarsFromSh($conffile); my %class = getVarsFromSh($class_install); $h{THEME} ||= 'default'; $h{LOGS} ||= bool2text($class{CLASS} eq 'expert' ? 1 : 0); $h{EXPERT_WIZARD} ||= 0; $h{HEIGTH} ||= $default_heigth; $h{WIDTH} ||= $default_width; my %option_values; $option_values{show_log} = text2bool($h{LOGS}); my $theme = $h{THEME}; my $program; my ($i, $geometry); foreach (@ARGV) { $i++; $theme = $1 if /--theme (\w+)/; $program = $1 if /--start-with=(.*)/; if (/^--geometry$/) { $geometry = splice @ARGV, $i, 1; last; } } -d "$themes_dir/$theme" or $theme = 'default'; add_icon_path("$themes_dir/$theme/"); add_icon_path("$themes_dir/default") if $theme ne 'default'; # fall back if theme miss some icons my $rc = find { -r $_ } ("$themes_dir/$theme/gtkrc", if_($theme ne 'default', "$themes_dir/default/gtkrc")); Gtk2::Rc->parse($rc) if -r $rc; #------------------------------------------------------------- # Splash window: please wait ... my $window_splash = Gtk2::Window->new('popup'); $window_splash->signal_connect(delete_event => \&quit_global); $window_splash->set_title(N("Mandriva Linux Control Center")); $window_splash->set_position('center_always'); $window_splash->add(gtkadd(gtkset_shadow_type(Gtk2::Frame->new, 'etched_out'), gtkput(my $fixed = Gtk2::Fixed->new, gtkpack(Gtk2::VBox->new(0, 0), if_(-r "$themes_dir/$theme/splash_screen.png", gtkcreate_img("splash_screen")), gtkset_markup(Gtk2::Label->new, join('', qq(\n), N("Mandriva Linux Control Center"), ""), ), Gtk2::Label->new(N("Loading... Please wait") . "\n"), ), 0, 0), ) ); $fixed->set_has_window(1); $fixed->signal_connect(realize => sub { ugtk2::set_back_pixmap($fixed) }); $window_splash->show_all; gtkflush(); #------------------------------------------------------------- # Data structures my $more_wizard_dir = "/etc/wizard.d/"; my $isWiz = -e "/usr/sbin/drakwizard"; my $isRpmDrake = -e "/usr/sbin/rpmdrake"; my $isParkRpmDrake = -e "/usr/sbin/park-rpmdrake"; my $isWebAdmin = -e "/usr/bin/mdkwebadmin"; my $isRfbDrake = -e "/usr/bin/rfbdrake"; my $isDrakStats = -e "/usr/sbin/drakstats"; my $application_driven_menu; # { key => { log_exp, binary, embedded?, description ] } # embedded meaning: -1 => not embedded, 0 => external x11 app, 1 => proper embedding my %programs = ( "3D" => { binary => "$sbindir/drak3d", embedded => 1, description => N("Configure 3D Desktop effects"), long_description => N("Configure 3D Desktop effects"), icon => 'drak3d', }, "Authentication" => { binary => "$sbindir/drakauth", embedded => 1, description => #-PO: this message is already translated in drakx domain from which MCC will searchs it: N("Authentication"), long_description => N("Select the authentication method (local, NIS, LDAP, Windows Domain, ...)"), icon => 'drakauth-mdk', }, "Auto Install" => { binary => "$sbindir/drakautoinst", embedded => 1, description => N("Auto Install floppy"), long_description => N("Generate an Auto Install floppy"), icon => 'drakautoinst-mdk', }, "Auto login Config" => { binary => "$sbindir/drakboot", embedded => 1, description => N("Set up autologin to automatically log in"), long_description => N("Enable autologin and select the user to automatically log in"), icon => 'autologin-mdk', }, "Backups" => { binary => "$sbindir/drakbackup", embedded => 1, description => N("Backups"), long_description => N("Configure backups of the system and of the users' data"), icon => 'backup-mdk', application_driven_menu => 1, }, "Boot Config" => { binary => "$sbindir/drakboot --boot", embedded => 1, description => N("Set up boot system"), long_description => N("Set up how the system boots"), icon => 'drakboot-mdk', }, "Boot Theme" => { binary => "$sbindir/drakboot --splash", embedded => 1, description => N("Set up boot graphical theme of system"), long_description => N("Select the graphical theme of the system while booting"), icon => 'boot-theme-mdk', }, "Boot Disk" => { binary => "$sbindir/drakfloppy", embedded => 1, description => N("Boot floppy"), long_description => N("Generate a standalone boot floppy"), icon => 'drakfloppy-mdk', }, "Connection Sharing" => { binary => "$sbindir/drakgw", embedded => 1, description => N("Share the Internet connection with other local machines"), long_description => N("Share the Internet connection with other local machines"), icon => 'drakgw-mdk', }, "Add Connection" => { binary => "$sbindir/drakconnect --wizard", embedded => 1, description => N("Set up a new network interface (LAN, ISDN, ADSL, ...)"), long_description => N("Set up a new network interface (LAN, ISDN, ADSL, ...)"), icon => 'new-connection-mdk', }, "Configure Internet" => { binary => "$sbindir/drakconnect --internet", embedded => 1, description => N("Internet access"), long_description => N("Alter miscellaneous internet settings"), icon => 'internet-access-mdk', }, "Console" => { binary => "$sbindir/drakconsole", embedded => 1, description => N("Open a console as administrator"), long_description => N("Open a console as administrator"), icon => 'console-mdk', #The Console will help you to solve issues }, "Date & Time" => { binary => "$sbindir/clock.pl", embedded => 1, description => N("Manage date and time"), long_description => N("Manage date and time"), icon => 'time-mdk', }, "Display Manager chooser" => { binary => "$sbindir/drakedm", embedded => 1, description => N("Set up display manager"), long_description => N("Choose the display manager that enables to select which user to log in"), icon => 'drakedm-mdk', }, "Fax" => { binary => "$sbindir/drakfax_server", embedded => 1, description => N("Configure a fax server"), long_description => N("Configure a fax server"), icon => 'drakfax-mdk', }, "Firewall" => { binary => "$sbindir/drakfirewall", embedded => 1, description => N("Set up your personal firewall"), long_description => N("Set up a personal firewall in order to protect the computer and the network"), icon => 'firewall-mdk', }, "Fonts" => { binary => "$sbindir/drakfont", embedded => 1, description => N("Manage, add and remove fonts. Import Windows(TM) fonts"), long_description => N("Manage, add and remove fonts. Import Windows(TM) fonts"), icon => 'drakfont-mdk', }, "Graphical server configuration" => { binary => "$sbindir/XFdrake", embedded => 1, description => N("Set up the graphical server"), long_description => N("Set up the graphical server"), icon => 'XFdrake-mdk' }, "Hard Drives" => { binary => "$sbindir/diskdrake --hd", embedded => 1, description => N("Manage disk partitions"), long_description => N("Create, delete and resize hard disk partitions"), icon => 'diskdrake_hd', }, "Hardware List" => { binary => "$sbindir/harddrake2", embedded => 1, description => N("Browse and configure hardware"), long_description => N("Browse and configure hardware"), icon => 'harddrake-mdk', application_driven_menu => 1, }, "Hosts" => { binary => "$sbindir/drakhosts", embedded => 1, description => N("Hosts definitions"), long_description => N("Manage hosts definitions"), icon => 'drakhosts', }, "Install Software" => { binary => "$sbindir/rpmdrake", embedded => 1, description => N("Manage software"), long_description => N("Install, uninstall software"), icon => 'installremoverpm', application_driven_menu => 1, }, "Invictus Firewall" => { binary => "$sbindir/drakinvictus", embedded => 1, description => N("Advanced setup for network interfaces and firewall"), long_description => N("Set up network interfaces failover and firewall replication"), icon => 'invictus', }, "Keyboard" => { binary => "$sbindir/keyboarddrake", embedded => 1, description => N("Set up the keyboard layout"), long_description => N("Set up the keyboard layout"), icon => 'keyboard-mdk', }, "Kolab" => { binary => "$sbindir/kolab", embedded => 1, description => N("Kolab"), long_description => N("Set up a groupware server"), }, "Localization" => { binary => "$bindir/localedrake", embedded => 1, icon => 'localedrake', description => N("Manage localization for your system"), long_description => N("Select the language and the country or region of the system"), }, "Logs" => { binary => "$sbindir/logdrake", embedded => 1, description => N("View and search system logs"), long_description => N("View and search system logs"), icon => 'logdrake-mdk', }, "Manage Connection" => { binary => "$sbindir/drakconnect --skip-wizard", embedded => 1, description => N("Manage connections"), long_description => N("Reconfigure a network interface"), icon => 'manage-connections-mdk', }, "Mandriva Online" => { binary => "$xbindir/mdkonline", embedded => 1, description => N("Upload your configuration to get information on upgrades"), long_description => N("Upload your configuration in order to keep you informed about security and useful upgrades"), icon => 'mdkonline-mdk', }, "Manage park" => { binary => "$sbindir/park-rpmdrake", embedded => 1, description => N("Manage computer group"), long_description => N("Manage installed software packages on a group of computers"), icon => 'drakpark-mdk', }, "Mandriva Update" => { binary => "$sbindir/MandrivaUpdate", embedded => 1, description => N("Update your system"), long_description => N("Look at available updates and apply any fixes or upgrades to installed packages"), icon => 'MandrivaUpdate', application_driven_menu => 1, }, "Menus" => { binary => "$bindir/drakmenustyle", embedded => 1, description => N("Menu Style"), long_description => N("Menu Style Configuration"), icon => 'drakmenustyle', }, "Migration" => { binary => "$sbindir/transfugdrake", embedded => 1, description => N("Import Windows(TM) documents and settings"), long_description => N("Import Windows(TM) documents and settings"), icon => 'migrationtools', }, "Monitor Connection" => { binary => "$sbindir/net_monitor", embedded => 1, description => N("Monitor connections"), long_description => N("Monitor the network connections"), icon => 'net_monitor-mdk', }, "Mouse" => { binary => "$sbindir/mousedrake", embedded => 1, description => N("Set up the pointer device (mouse, touchpad)"), long_description => N("Set up the pointer device (mouse, touchpad)"), icon => 'mousedrake-mdk', }, "Network Center" => { binary => "$sbindir/draknetcenter", embedded => 1, description => N("Network Center"), long_description => N("Manage your network devices"), icon => 'netcenter', }, "Network Profiles" => { binary => "$sbindir/draknetprofile", embedded => 1, description => N("Manage different network profiles"), long_description => N("Activate and manage network profiles"), icon => 'draknetprofile', }, "NFS mount points" => { binary => "$sbindir/diskdrake --nfs", embedded => 1, description => N("Use NFS shares"), long_description => N("Set NFS mount points"), icon => 'diskdrake_nfs', }, "NFS exports" => { binary => "$sbindir/draknfs", embedded => 1, description => N("Share your data through NFS"), long_description => N("Manage NFS shares"), icon => 'draknfs', application_driven_menu => 1, }, "Package stats" => { binary => "$sbindir/drakstats", embedded => 1, description => N("Package Stats"), long_description => N("Show statistics about usage of installed software packages"), icon => 'source-manager', }, "Partition Sharing" => { binary => "$sbindir/diskdrake --fileshare", embedded => 1, description => N("Share your hard disk partitions"), long_description => N("Set up sharing of your hard disk partitions"), icon => 'diskdrake_fileshare', }, "Printer" => { binary => "$sbindir/printerdrake", embedded => 1, description => N("Set up the printer(s), the print job queues, ..."), icon => 'printer-mcc-mdk', long_description => N("Set up the printer(s), the print job queues, ..."), application_driven_menu => 1, }, "Programs scheduling" => { binary => "$xbindir/drakcronat", embedded => 1, description => N("Scheduled tasks"), long_description => N("Schedule programs to run periodically or at given times"), #DrakCronAt enables to schedule Programs execution through crond and atd daemons icon => 'drakcronat-mdk', }, "Proxy Configuration" => { binary => "$sbindir/drakproxy", embedded => 1, description => N("Proxy"), long_description => N("Set up a proxy server for files and web browsing"), icon => 'drakproxy-mdk', }, "Remote Control" => { binary => "$bindir/rfbdrake", embedded => 1, description => N("Remote Control (Linux/Unix, Windows)"), long_description => N("Remote Control of another machine (Linux/Unix, Windows)"), icon => 'internet-access-mdk', }, "Remove Interface" => { binary => "$sbindir/drakconnect --del", embedded => 1, description => N("Remove a connection"), long_description => N("Delete a network interface"), icon => 'remove-connection-mdk', }, #- currently unused "Roaming" => { binary => "$sbindir/drakroam", embedded => 1, description => N("Wireless connection"), long_description => N("Wireless connection"), icon => 'drakroam-mdk', }, "Access Windows shares" => { binary => "$sbindir/diskdrake --smb", embedded => 1, description => N("Share data with Windows system"), long_description => N("Configuration of Windows (Samba) shared drives and directories"), icon => 'diskdrake_samba', }, "Samba configuration" => { binary => "$sbindir/draksambashare", embedded => 1, description => N("Manage Samba configuration"), long_description => N("Manage configuration of Samba"), icon => 'draksambashare', application_driven_menu => 1, }, "Scanner" => { binary => "$sbindir/scannerdrake", embedded => 1, description => N("Set up scanner"), long_description => N("Set up scanner"), icon => 'scanner-mdk', }, "Security Level" => { binary => "$sbindir/draksec", embedded => 1, description => N("Set up security level and audit"), long_description => N("Set the system security level and the periodic security audit"), icon => 'draksec-mdk', }, "Security Permissions" => { binary => "$sbindir/drakperm", embedded => 1, description => N("Tune permissions on system"), long_description => N("Fine tune the security permissions of the system"), icon => 'drakperm-mdk', }, "Services" => { binary => "$sbindir/drakxservices", embedded => 1, description => N("Manage system services by enabling or disabling them"), long_description => N("Manage system services by enabling or disabling them"), icon => 'service-mdk', }, "Software Media Manager" => { binary => "$sbindir/edit-urpm-sources.pl", embedded => 1, description => N("Configure media sources for install and update"), long_description => N("Select from where software packages are downloaded "), icon => 'source-manager', application_driven_menu => 1, }, "UPS" => { binary => "$sbindir/drakups --wizard", embedded => 1, description => #-PO: UPS==Uninterruptible power supply N("Set up a UPS for power monitoring"), long_description => #-PO: here power means electrical power N("Set up a UPS for power monitoring"), icon => 'drakups-mdk', }, "Users" => { # too big binary => "$bindir/userdrake", embedded => 1, description => N("Manage users on system"), long_description => N("Add, remove or change users of the system"), icon => 'user-mdk', application_driven_menu => 1, }, "Virtualization" => { binary => "$sbindir/drakvirt", embedded => 1, description => N("Virtualization"), long_description => N("Virtual machines management"), icon => 'drakvirt', }, "VPN" => { binary => "$sbindir/drakvpn", embedded => 1, description => N("Configure VPN connection to secure network access"), long_description => N("Configure VPN connection to secure network access"), icon => 'drakvpn', }, "WebDAV mount points" => { binary => "$sbindir/diskdrake --dav", embedded => 1, description => N("Use WebDAV shares"), long_description => N("Set WebDAV mount points"), icon => 'webdav-mdk', }, ); sub is_wizard_installed { -f top(glob("/usr/lib/perl5/vendor_perl/*/MDK/Wizard/$_[0]")) } my $is_auth_wizard_installed = is_wizard_installed('Nisautofs.pm'); sub wizard_format { map { my ($id, $wizard, $icon, $description, $long_description, $file) = @$_; $programs{$id} = { binary => "$sbindir/drakwizard $wizard", embedded => 1, description => $description, long_description => $long_description, icon => $icon, }; if_(is_wizard_installed($file), $id); } @_; } # [ [ class_label, class icon name, [ program_label, ... ] ] my @tree = ( if_($isRpmDrake || $isParkRpmDrake, [ N("Software Management"), 'software', [ if_($isRpmDrake, { title => N("Software Management"), list => [ "Install Software", "Mandriva Update", if_(0, "Mandriva Online"), "Software Media Manager", ] }, ), { title => N("Others"), list => [ if_($isParkRpmDrake, "Manage park"), if_($isDrakStats, "Package stats"), ] }, ] ] ), if_(0, [ N("Server wizards"), 'wizard-mdk' ]), [ N("Sharing"), 'file-sharing-mdk', [ { title => N("Sharing"), list => [ (wizard_format( # [ id, wizard file name, icon, description ] [ "FTP wizard", "proftpd", 'ftp-mdk', N("Configure FTP"), N("Set up an FTP server"), 'Proftpd.pm', ], [ "Samba wizard", "samba", 'samba_server-mdk', N("Configure Samba"), N("Set up a file and print server for workstations running Linux and non-Linux systems"), 'Samba.pm', ], [ "Manage Samba share", "sambashare", 'wizard-mdk', N("Manage Samba share"), N("Manage, create special share, create public/user share"), 'Sambashare.pm', 1, ], [ "Web wizard", "apache2", 'web_server-mdk', N("Configure web server"), N("Set up a web server"), 'Apache.pm', ], [ "Installation server wizard", "installsrv", 'wizard-mdk', N("Configure installation server"), N("Set up server for network installations of Mandriva Linux"), 'Installsrv.pm', 1, ], ), ), ] }, ] ], [ N("Network Services"), 'network-services-mdk', [ { title => N("Network Services"), list => [ (wizard_format( # [ id, wizard file name, icon, description ] [ "DHCP wizard", "dhcp", 'dhcp_server-mdk', N("Configure DHCP"), N("Set up a DHCP server"), 'Dhcp.pm', ], [ "DNS wizard", "bind", 'dns_server-mdk', N("Configure DNS"), N("Set up a DNS server (network name resolution)"), 'Bind.pm', ], [ "Squid wizard", "squid", 'drakproxy-mdk', N("Configure proxy"), N("Configure a web caching proxy server"), 'Squid.pm', ], [ "Time wizard", "ntp", 'ntp_server-mdk', N("Configure time"), N("Set the time of the server to be synchronized with an external time server"), 'Ntp.pm', ], [ "SSHD wizard", "sshd", 'wizard-sshd', N("OpenSSH daemon configuration"), N("OpenSSH daemon configuration"), 'Sshd.pm', ], ), ), ] }, ] ], [ N("Authentication"), 'drakauth-mdk', [ { title => N("Authentication"), list => [ if_($is_auth_wizard_installed, "Authentication"), (wizard_format( # [ id, wizard file name, icon, description ] [ 'Nis+autofs wizard', "nisautofs", 'nisautofs', N("Configure NIS and Autofs"), N("Configure the NIS and Autofs services"), 'Nisautofs.pm', ], [ "LDAP wizard", "ldap", "ldap-mdk", N("Configure LDAP"), N("Configure the LDAP directory services"), 'Ldap.pm', ], ), ), ] }, ] ], [ N("Groupware"), 'groupware-mdk', [ { title => N("Groupware"), list => [ (wizard_format( # [ id, wizard file name, icon, description ] if_(0, [ "News wizard", "inn", 'news-mdk', N("Configure news"), N("Configure a newsgroup server"), 'Inn.pm', ], [ "Kolab wizard", "kolab", "kolab-mdk", N("Configure groupware"), N("Configure a groupware server"), 'Kolab.pm', ]), [ "Postfix wizard", "postfix", 'postfix-mdk', N("Configure mail"), N("Configure the Internet Mail services"), 'Postfix.pm' ], ), ), ] }, ] ], if_($isWebAdmin || $isRfbDrake, [ N("Online Administration"), 'online-administration-mdk', [ { title => N("Online Administration"), list => [ if_($isWebAdmin, (map { my ($id, $icon, $op, $description, $long_description) = @$_; $programs{$id} = { binary => "$bindir/mdkwebadmin.pl $op", embedded => -1, # too big description => $description, long_description => $long_description, icon => $icon, }; $id; } ( # [ id, wizard file name, icon, description ] [ "Local Admin", 'local-administration-mdk', '--direct', N("Local administration"), (-e "/usr/bin/webmin" ? N("Configure the local machine via web interface") : N("You don't seem to have webmin intalled. Local config is disabled")) ], [ "Remote Admin", 'remote-administration-mdk', '--link', N("Remote administration"), N("Click here if you want to configure a remote box via Web interface"), ]) ) ), if_($isRfbDrake, "Remote Control", ) ] }, ] ]), [ N("Hardware"), 'drakhard-mdk', [ { title => N("Manage your hardware"), list => [ "Hardware List",, ] }, { title => N("Configure graphics"), list => [ "3D", "Graphical server configuration", ] }, { title => N("Configure mouse and keyboard"), list => [ "Keyboard", "Mouse", ] }, { title => N("Configure printing and scanning"), list => [ "Printer", "Scanner", if_(-x "$bindir/drakfax", "Fax"), ] }, { title => N("Others"), list => [ "UPS", ] }, ] ], [ N("Network & Internet"), 'net-mdk', [ { title => N("Manage your network devices"), list => [ "Network Center", "Add Connection", if_(!-x "$sbindir/draknetcenter", "Configure Internet", "Manage Connection", "Monitor Connection", "Remove Interface", ), ] }, { title => N("Personalize and Secure your network"), list => [ "Proxy Configuration", "Connection Sharing", "Network Profiles", "VPN", ] }, { title => N("Others"), list => [ "Hosts", ] }, ], ], [ N("System"), 'system-mdk', [ { title => N("Manage system services"), list => [ if_(!$is_auth_wizard_installed, "Authentication"), "Menus", "Services", "Fonts", ] }, { title => N("Localization"), list => [ "Date & Time", "Localization", ] }, { title => N("Administration tools"), list => [ "Logs", if_($ENV{LANGUAGE} !~ /^zh/, "Console"), "Users", "Migration", if_(-x "$xbindir/drakcronat", "Programs scheduling"), "Backups", "Virtualization", ] }, ] ], [ N("Network Sharing"), 'network-sharing-mdk', [ { title => N("Configure Windows(R) shares"), list => [ "Access Windows shares", "Samba configuration", ] }, { title => N("Configure NFS shares"), list => [ "NFS mount points", "NFS exports", ] }, { title => N("Configure WebDAV shares"), list => [ "WebDAV mount points", ] }, ], ], [ N("Local disks"), 'partition-mdk', [ { title => N("Local disks"), list => [ "Hard Drives", (map { my ($type, $scan, $text, $long_text) = @$_; map_index { my $full_name = $text . ($::i ? $::i + 1 : ''); $programs{$full_name} = { binary => "$sbindir/diskdrake --removable=$_->{device}", embedded => 1, description => sprintf(translate($text), $_->{info}), long_description => sprintf(translate($long_text), $_->{info}), icon => "diskdrake_$type", }; $full_name; } $scan->(); } do { my %cdroms_by_type; foreach (detect_devices::cdroms()) { my $type = detect_devices::isBurner($_) ? 'burner' : detect_devices::isDvdDrive($_) ? 'DVD' : 'cdrom'; push @{$cdroms_by_type{$type}}, $_; } ([ 'cdrom', sub { @{$cdroms_by_type{cdrom} || []} }, N_("CD-ROM (%s)",), N_("Set where your \"%s\" CD-ROM drive is mounted"), ], [ 'dvd', sub { @{$cdroms_by_type{DVD} || []} }, N_("DVD-ROM (%s)"), N_("Set where your \"%s\" DVD-ROM drive is mounted"), ], [ 'cdwriter', sub { @{$cdroms_by_type{burner} || []} }, N_("CD/DVD burner (%s)"), N_("Set where your \"%s\" CD/DVD burner is mounted"), ], [ 'floppy', \&detect_devices::floppies, N_("Floppy drive"), N_("Set where your floppy drive is mounted"), ], [ 'zip', \&detect_devices::zips, N_("ZIP drive"), N_("Set where your ZIP drive is mounted"), ], ); }), "Partition Sharing", ] }, ] ], [ N("Security"), 'security-mdk', [ { title => N("Security"), list => [ "Security Level", "Security Permissions", "Firewall", "Invictus Firewall", ] }, ] ], [ N("Boot"), 'boot-mdk', [ { title => N("Configure boot steps"), list => [ #if_(detect_devices::floppies, "Boot Disk"), # kernel is too big "Auto login Config", "Boot Config", "Display Manager chooser", ] }, { title => N("Boot look'n feel"), list => [ "Boot Theme", ] }, { title => N("Others"), list => [ if_(0, "Auto Install"), ] }, ] ], ); if (scalar glob_("$more_wizard_dir/*.conf")) { my @leaf = ( N("Additional wizards"), 'wizard-mdk', [] ); foreach my $file (glob_("$more_wizard_dir/*.conf")) { next unless -f $file; my %tmp = getVarsFromSh($file); $programs{$tmp{NAME}} = { binary => "$sbindir/drakwizard " . lc($file), embedded => 1, description => $tmp{DESCRIPTION}, icon => $tmp{ICON} || 'wizard-mdk', long_description => $tmp{LONG_DESCRIPTION}, }; push(@{$leaf[2]}, $tmp{NAME}); } push(@tree, \@leaf); } #------------------------------------------------------------- # let build the GUI # main window : my ($timeout, %check_boxes, $emb_socket); # set default size: my @min_size = $root_size eq '640x480' ? (620, 460) : (680, 500); my $window_global = gtkset_size_request(Gtk2::Window->new('toplevel'), @min_size); $::main_window = $window_global; if ($geometry) { @h{qw(HEIGTH WIDTH)} = $geometry =~ /(\d+)x(\d+)/; my ($x, $y) = $geometry =~ /([+-]\d+)([+-]\d+)/; $window_global->set_uposition($x, $y) if $x || $y; } else { } $window_global->resize(max($default_width, $h{WIDTH}, $min_size[0]), max($h{HEIGTH}, $default_heigth, $min_size[1])); $window_global->set_icon(gtkcreate_pixbuf("/usr/share/icons/drakconf.png")); my $pending_app = 0; my $help_on_context = 'drakconf-intro'; #Please replace with correct contextual help page my @ctx = qw(drakconf-intro mcc-boot mcc-hardware mcc-mountpoints mcc-network mcc-security mcc-system software-management wiz-client); my @themes = grep { -d "$themes_dir/$_" } all($themes_dir); #-PO Translators, please keep all "/" charaters !!! my %options = ( 'show_log' => [ N("/_Options"), N("/Display _Logs") ], 'embedded_mode' => [ N("/_Options"), N("/_Embedded Mode") ], 'wiz_expert' => [ N("/_Options"), N("/Expert mode in _wizards") ], ); my $mdk_rel = common::mandrake_release(); my ($notebook_global); my $release = mandrake_release_info(); my @menu_items = ( [ N("/_File"), undef, undef, undef, '' ], [ N("/_File") . N("/_Upload the hardware list"), N("U"), \&upload, undef, '' ], [ N("/_File") . N("/_Quit"), N("Q"), \&quit_global, undef, '', N("Quit") ], [ N("/_Options"), undef, undef, undef, '' ], [ join('', @{$options{show_log}}), undef, sub { $option_values{show_log} = $check_boxes{show_log}->get_active; if ($option_values{show_log}) { start_logdrake(); } else { kill_logdrake(); } }, undef, '' ], if_(0 && $isWiz, [ join('', @{$options{wiz_expert}}), undef, sub { $option_values{expert_wizard} = $check_boxes{wiz_expert}->get_active }, undef, '', ], ), if_(@themes > 1, [ N("/_Themes"), undef, undef, undef, '' ], (map { my $name = $_; [ N("/_Themes") . "/" . ($name eq $theme ? " O " : " ") . "_$_", undef, sub { return if $theme eq $name; !$pending_app || splash_warning(N("This action will restart the control center.\nAny change not applied will be lost."), 1) and do { # embedded app must be killed kill_children(); kill_logdrake(); child_just_exited(); exec "$0 --theme $name"; }; }, undef, '' ]; } @themes), [ N("/_Themes") . N("/_More themes"), undef, \&more_themes, undef, '' ] ), [ N("/_Help"), undef, undef, undef, '' ], [ N("/_Help") . N("/_Help"), undef, sub { fork_("drakhelp --id $help_on_context", []) }, undef, '', N("Help") ], [ N("/_Help") . N("/_Release notes"), undef, sub { run_browser('Notes') }, undef, '', N("Help") ], [ N("/_Help") . N("/What's _New?"), undef, sub { run_browser("What's New?") }, undef, '', N("Help") ], [ N("/_Help") . N("/_Errata"), undef, sub { run_browser('Errata') }, undef, '', N("Help") ], [ N("/_Help") . N("/_Report Bug"), undef, sub { run_program::raw({ detach => 1 }, 'drakbug', '--report', (split(/\s/, $pending_app))[0] || 'drakconf'); }, undef, '' ], [ N("/_Help") . N("/_About..."), undef, \&about_mdk_cc, undef, '' ] ); sub run_browser { my ($url) = @_; $url = "http://wiki.mandriva.com/en/Releases/Mandriva/$release->{version}/$url" if $url !~ m!^http://!; run_program::raw({ detach => 1 }, '/usr/bin/www-browser', $url); } my ($menu, $factory) = create_factory_menu($window_global, @menu_items); # to retrieve a path, one must prevent "accelerators completion": sub get_path { join('', map { my $i = $_; $i =~ s/_//g; $i } @_) } %check_boxes = map { $_ => $factory->get_widget("
" . get_path(@{$options{$_}})); } ('show_log', if_(0 && $isWiz, "wiz_expert")); gtkadd($window_global, gtkpack_(Gtk2::VBox->new(0, 0), 0, $menu, 0, my $banner_notebook = Gtk2::Notebook->new, 0, Gtk2::HSeparator->new, # 0, gtkset_size_request(Gtk2::VBox->new(10, 10), -1, 2), 1, gtkpack_(Gtk2::HBox->new(0, 0), 1, $notebook_global = gtkset_name(Gtk2::Notebook->new, 'mcc'), 1, gtkpack(my $emb_box = Gtk2::VBox->new(0, 0), my $wait_darea = gtkset_size_request(Gtk2::DrawingArea->new, -1, -1), ), ), 0, Gtk2::HSeparator->new, 0, my $buttons = gtkadd(gtkset_layout(Gtk2::HButtonBox->new, 'start'), map { gtkset_border_width($_, 3) } gtksignal_connect(my $cancel = Gtk2::Button->new(N("Cancel")), clicked => sub { stop_wait_area(); kill_children(); child_just_exited(); }), gtkset_sensitive(gtkset_relief(Gtk2::Button->new(""), 'none'), 0), ), ) ); sub notebook_set_background { my ($w) = @_; return if !$w->realized; my $color = $window_global->get_style->base('normal'); Gtk2::Rc->parse_string(join('', qq(style "mcc" { bg[NORMAL] = { ), join(' ,', $color->red, $color->green, $color->blue), qq( } bg_pixmap[NORMAL] = "" } widget "*mcc*" style "mcc" ))); $notebook_global->reset_rc_styles; } $notebook_global->signal_connect(realize => \¬ebook_set_background); $window_global->signal_connect("style-set" => sub { notebook_set_background($notebook_global) }); $window_global->signal_connect(delete_event => \&quit_global); use POSIX qw(:sys_utsname_h :math_h :sys_wait_h :unistd_h); my (undef, $nodename) = POSIX::uname(); $window_global->set_title(N("Mandriva Linux Control Center %s [on %s]", $version, $nodename)); $window_global->set_position('center'); foreach my $notebook ($banner_notebook) { $notebook->set_property('show-border', 0); $notebook->set_property('show-tabs', 0); } $notebook_global->set_property('tab-pos', 'left'); $notebook_global->set_scrollable(1); # banner : add2notebook($banner_notebook, "", Gtk2::Banner->new("/usr/share/icons/large/drakconf.png", N("Welcome to the Mandriva Linux Control Center"))); my ($_hand_cursor, $wait_cursor) = map { Gtk2::Gdk::Cursor->new($_) } qw(hand2 watch); my ($index, $left_locked) = (0, 0); #my $spacing = 25; my %tool_callbacks; my ($page_count); sub request_url { my ($_document, $url, $stream) = @_; return if !$url; $stream->write(join('', cat_($url))); $stream->close; } my $align = lang::text_direction_rtl() ? "right" : "justify"; my $align2 = lang::text_direction_rtl() ? "right" : "left"; sub clean_list { my ($subtree) = @_; grep { my $stuff = $_; my $exec = first(split /\s+/, $programs{$stuff}{binary}); my $is_present = -x $exec; # do not complain about missing entries in move: warn qq("$exec" is not executable [$stuff]) if $mdk_rel !~ /Move/ && !$is_present; !$programs{$stuff}{hidden} && $is_present; } @$subtree; } my @labels; foreach (@tree) { my ($text, $icon, $subtrees) = @$_; my @subtrees = grep { $_->{list} = [ clean_list($_->{list}) ]; !is_empty_array_ref($_->{list}) } @$subtrees; # Skip empty classes: next if !@subtrees; my $_my_index = $index++; my $string = join("\n", qq( )); my $view = Gtk2::Html2::View->new; my $document = Gtk2::Html2::Document->new; $document->signal_connect(request_url => \&request_url); $document->signal_connect('link-clicked' => sub { my ($_document, $url) = @_; $tool_callbacks{$url}->(); # FIXME: the following code is currently useless: # should we provide a way to kill buggy embedded programs ? return if $left_locked; warn_on_startup(); }); $view->set_document($document); # Create right notebook pages : my $section; foreach my $subtree (@subtrees) { $string .= "
\n" if $section++; $string .= qq(

$subtree->{title}

); if (@{$subtree->{list}} % 2) { my @widgets = (pop @{$subtree->{list}}, ""); @widgets = reverse @widgets if lang::text_direction_rtl(); push @{$subtree->{list}}, @widgets; } $string .= join("\n", map { "" . join("\n", grep { defined $_ } @$_) . "" } # "" . join("\n\n", grep { defined $_ } @$_) . "" } group_by(2, map { my $label = $_; my $icon = $programs{$label}{icon}; die "$label 's icon is missing" if !$programs{$label} && $::testing; $tool_callbacks{$label} = sub { run_tool($label, undef, #$event_box, $icon, $programs{$label}{description}, $programs{$label}); }; # FIX ME: DO THIS AGAIN: $tool_feedback{$label} = sub {}; #sub { $event_box->window && $event_box->window->set_cursor($hand_cursor) }; my $real_icon = $icon ? '' : ''; my @widgets = ( qq(), qq() ); @widgets = reverse @widgets if lang::text_direction_rtl(); qq( ); } @{$subtree->{list}}) ); $string .= "
$real_icon
$programs{$label}{description}
@widgets
\n"; } # b/c we use Pango text markup language, we've to protect '&' caracter: $text =~ s/&/&/g; $page_count++; $string .= qq(); $document->clear; $document->open_stream("text/html"); $document->write_stream($string); $labels[$index-1]{text} = $text; gtkappend_page($notebook_global, my $_w_ret = create_scrolled_window(gtkset_border_width($view, 5), [ 'never', 'automatic' ], # 'none', ), gtkpack__(Gtk2::HBox->new, Gtk2::Image->new_from_pixbuf(::scale(gtkcreate_pixbuf($icon), -16)), $labels[$index-1]{widget} = Gtk2::WrappedLabel->new($text), ), ); $labels[$index-1]{widget}->set_use_markup(1); # $w_ret->vscrollbar->set_size_request(19, undef); add2notebook($banner_notebook, "", Gtk2::Banner->new($icon, $text)); } my %icons = ( ); # manage tools not present in MCC (localedrake, drakauth, ...): foreach my $label (difference2([ keys %programs ], [ keys %tool_callbacks ])) { my $text = $programs{$label}{description}; $tool_callbacks{$label} = sub { run_tool($label, undef, $icons{$label} || 'wizard-mdk', $text, $programs{$label}) }; $tool_feedback{$label} = sub {}; } foreach (keys %check_boxes) { my $widget = $check_boxes{$_}; if (defined $widget) { $widget->set_active($option_values{$_}); } else { print STDERR qq(BUG with LANGUAGE "$ENV{LANGUAGE}" for "$_"\n); err_dialog(N("Error"), N("There's a bug in translations of your language (%s) Please report that bug.", $ENV{LANGUAGE})); } } # "wait while launching a program" area : my ($run_pixbuf, $run_counter, $run_counter_add, %run_pixbufs); sub stop_wait_area() { $wait_darea->hide; Glib::Source->remove($timeout) if $timeout; undef %run_pixbufs; } $wait_darea->signal_connect(expose_event => sub { my ($w) = @_; return if !$wait_darea->realized; return unless $run_pixbuf; # some people got an expose event before we start an embedded tool return unless $wait_darea->{size}; $wait_darea->{layout} ||= $wait_darea->create_pango_layout(N("Loading... Please wait")); my $pixbuf = $run_pixbufs{$run_counter} ||= render_alpha($run_pixbuf, $run_counter); if (!$wait_darea->{first_expose}) { $wait_darea->{first_expose} = 1; my $size = $wait_darea->{size}; my ($d_width, $d_height) = ($size->width, $size->height); ($w->{pix_width}, $w->{pix_height}) = ($pixbuf->get_width, $pixbuf->get_height); my ($txt_width, $txt_height) = $wait_darea->{layout}->get_pixel_size; $w->{pix_yy} = ($d_width - $w->{pix_width})/2; $w->{pix_xx} = ($d_height - $w->{pix_height} - $txt_height)/2; $w->{text_yy} = $w->{pix_yy} + ($w->{pix_width} - $txt_width)/2; $w->{text_xx} = $w->{pix_xx} + $w->{pix_height} + 5; } $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); my $style = $wait_darea->{style} ||= $wait_darea->get_style; $wait_darea->window->draw_layout($style->text_gc('normal'), $w->{text_yy}, $w->{text_xx}, $w->{layout}); $run_counter += $run_counter_add; $run_counter_add = -$run_counter_add if $run_counter < 100 || 255-$run_counter_add < $run_counter; }); gtkflush(); set_page_raw(0); my $old_index; $notebook_global->signal_connect(switch_page => sub { my ($notebook, $page, $new_index) = @_; return if !$labels[$new_index]{widget}; my $page = $notebook_global->get_current_page; $labels[$old_index]{widget}->set_markup($labels[$old_index]{text}) if -1 < $old_index; $labels[$new_index]{widget}->set_markup('' . $labels[$new_index]{text} . ''); $old_index = $new_index; }); $window_global->show_all; hide_buttons(); $emb_box->hide; $wait_darea->realize; $SIG{USR1} = 'IGNORE'; $SIG{USR2} = 'IGNORE'; $SIG{TERM} = \&quit_global; $SIG{CHLD} = \&sig_child; $window_splash->destroy; undef $window_splash; Glib::Timeout->add(200, sub { sig_child('CHLD', 1); 1 }); if ($program) { if (my $sub = $tool_callbacks{$program}) { Glib::Timeout->add(500, sub { $sub->(); 0 }); } else { err_dialog(N("Error"), N("Impossible to run unknown '%s' program", $program)); } } Gtk2->main; sub group_by { my $nb = shift @_; my @l; for (my $i = 0; $i < @_; $i += $nb) { push @l, [ map { $_[$_] } $i..$i+$nb-1 ]; # $_[$i], $_[$i+1], $_[$i+2] ]; } @l; } sub warn_on_startup() { if ($pending_app) { return if !splash_warning(N("The modifications done in the current module won't be saved."), 1); kill_children(); child_just_exited(); } } sub upload() { my $dialog = _create_dialog(N("Upload the hardware list"), { transient => $window_global->{real_window} }); #, height => 400 gtkpack($dialog->vbox, gtkset_markup(Gtk2::Label->new, qq() . N("Upload the hardware list") . "\n"), create_packtable({ col_spacings => 10, row_spacings => 5, mcc => 1 }, [ N("Account:"), my $account_w = Gtk2::Entry->new ], [ N("Password:"), my $password_w = Gtk2::Entry->new ], [ N("Hostname:"), my $system_name_w = Gtk2::Entry->new ], ), ); $password_w->set_visibility(0); #set_invisible_char('*'); my ($password, $account, $name); gtkadd($dialog->action_area, create_okcancel( { cancel_clicked => sub { $dialog->destroy; Gtk2->main_quit }, ok_clicked => sub { $name = $system_name_w->get_text; $account = $account_w->get_text; $password = $password_w->get_text; $dialog->destroy; Gtk2->main_quit; }, }, undef, undef, '', ), ); $dialog->set_has_separator(0); $dialog->show_all; Gtk2->main; if ($account) { require interactive; my $_wait = 'interactive'->vnew->wait_message(N("Please wait"), N("Uploading in progress")); #info_dialog(N("Please wait"), N("Uploading in progress")); local $ENV{HWDB_PASSWD} = $password; require run_program; run_program::run("/usr/sbin/hwdb_add_system", $account, $name); run_program::raw({ detach => 1 }, "/usr/bin/www-browser", 'http://hcl.mandriva.com/'); } } #------------------------------------------------------------- # socket/plug managment # called once embedded tool has exited sub child_just_exited() { $pending_app = 0; $left_locked = 0; if ($emb_socket) { $emb_socket->destroy; undef $emb_socket; } $emb_box->hide; hide_buttons(); $cancel->hide; gtkset_mousecursor_normal(); foreach my $notebook ($notebook_global, $banner_notebook) { $notebook->show; } stop_wait_area(); } sub hide_socket_and_clean() { $emb_box->hide; $pending_app = 0; } sub create_hidden_socket { my ($icon, $label) = @_; my $banner; gtkpack_($emb_box, 0, $banner = gtkpack__(Gtk2::VBox->new(0, 0), Gtk2::Banner->new($icon, $label), Gtk2::HSeparator->new, ), 1, gtksignal_connect($emb_socket = Gtk2::Socket->new, 'plug-removed' => sub { $menu->show if $application_driven_menu; $banner->destroy; child_just_exited(); })); $banner->hide; # signal emitted when embedded apps begin to draw: $emb_socket->signal_connect('plug-added' => sub { $banner_notebook->hide; if ($application_driven_menu) { $menu->hide; } else { $banner->show; } stop_wait_area(); $left_locked = 0; hide_buttons(); $buttons->hide; return if !$emb_socket; $emb_socket->show; $emb_socket->can_focus(1); $emb_socket->grab_focus; #$emb_socket->window->XSetInputFocus; #only need by console (no more embedded until we've vte/zvt binding) }); $emb_box->set_focus_child($emb_socket); $emb_socket->hide; } #------------------------------------------------------------- # processes managment # embedded processes pid will be stocked there my @pid_launched; # logdrake pid are stocked here my $pid_exp; sub fork_ { my ($prog, $o_pid_table) = @_; $o_pid_table ||= \@pid_launched; my $pid = fork(); if (defined $pid) { !$pid and do { exec($prog) or POSIX::_exit(1) }; # immediate exit, else forked gtk+ object destructors will badly catch up parent mcc push @$o_pid_table, $pid; return $pid; } else { splash_warning(N("cannot fork: %s", "$!")); child_just_exited(); } } sub run_tool { my ($label, $box, $icon, $text, $tool) = @_; my ($exec, $gtkplug) = @$tool{qw(binary embedded)}; $application_driven_menu = $tool->{application_driven_menu}; return if $tool_pids{$label}; if (! -x first(split /\s+/, $exec)) { splash_warning(N("cannot fork and exec \"%s\" since it is not executable", $exec)); return; } $exec .= " --summary" if $option_values{expert_wizard} && $exec =~ /drakwizard/; my $embedded = $gtkplug != -1; # not "explicitely not embedded" if ($embedded) { foreach my $notebook ($notebook_global) { $notebook->hide; } create_hidden_socket($icon, $text); $emb_box->show; $emb_socket->realize; $pending_app = $tool->{binary}; if ($gtkplug > 0) { $buttons->show; $exec .= " --embedded " . $emb_socket->get_id; $wait_darea->show; $cancel->show; $run_pixbuf = gtkcreate_pixbuf($icon . "_128"); $run_counter = 255; $run_counter_add = -5; undef $wait_darea->{color}; undef $wait_darea->{size}; undef $wait_darea->{first_expose}; $wait_darea->{not_yet_complete} = 1; $timeout = Glib::Timeout->add(35, sub { my $style = $wait_darea->{style} ||= $wait_darea->get_style; my $bg = $wait_darea->{bg} ||= $style->bg('normal'); my $base = $wait_darea->{base} ||= $style->base('normal'); my $color = $wait_darea->{color} ||= $base; # $base -> $bg my @colors = ([ $color->red, $bg->red ], [ $color->green, $bg->green ], [ $color->blue, $bg->blue ]); if ($wait_darea->{not_yet_complete} && any { $_->[0] != $_->[1] } @colors) { $wait_darea->window->set_background($color); $wait_darea->{color} = gtkcolor(map { $_->[0] - min(300, $_->[0] - $_->[1]) } @colors); $wait_darea->queue_draw; } elsif ($wait_darea->{not_yet_complete}) { # set exact color $wait_darea->window->set_background($bg); $wait_darea->queue_draw; $wait_darea->{not_yet_complete} = 0; } else { my $w = $wait_darea; $wait_darea->queue_draw_area($w->{pix_yy}, $w->{pix_xx}, $w->{pix_width}, $w->{pix_height}); } 1; }); $left_locked = 1; $buttons->show; $tool_pids{$label} = fork_($exec); } } else { # not embedded # fix #3415 when $gtkplug eq -1 local $option_values{embedded} = 0; $tool_pids{$label} = fork_($exec); } start_logdrake(); $box->window->set_cursor($wait_cursor) if $box; } sub start_logdrake() { # (re)start logdrake if needed if ($option_values{show_log} && !$pid_exp) { my $exec_log = "logdrake --explain=drakxtools"; $pid_exp = fork_($exec_log, []); } } sub kill_them_all { map { if__($_, kill 'TERM', $_) } @_; } sub kill_children() { kill_them_all(@pid_launched); } sub kill_logdrake() { kill_them_all($pid_exp) if $pid_exp; } sub quit_global() { if (@pid_launched) { &kill_children(); return 1; # tell gtk+ not to quit } &kill_children(); &kill_logdrake(); my ($x, $y) = $window_global->get_size; setVarsInSh($conffile, { LOGS => bool2text($option_values{show_log}), EXPERT_WIZARD => bool2text($option_values{expert_wizard}), HEIGTH => $y, WIDTH => $x, THEME => $theme, }); gtkset_mousecursor_normal(); Gtk2::exit(0); standalone::exit(0); } #------------------------------------------------------------- # signals managment # got when child died and gone in zombie state sub sig_child { my ($_sig, $o_is_cleaner) = @_; my $child_pid; do { $child_pid = waitpid(-1, POSIX::WNOHANG); if (my $tool = find { $tool_pids{$_} eq $child_pid } keys %tool_pids) { $tool_feedback{$tool}->(); delete $tool_pids{$tool}; @pid_launched = grep { $_ ne $child_pid } @pid_launched; } undef $pid_exp if $pid_exp eq $child_pid; } while $child_pid > 0; # child unexpectedly died (cleanup since child_just_exited won't be called by plug-removed since plug never was added) return if $o_is_cleaner || !$left_locked; child_just_exited(); splash_warning(N("This program has exited abnormally")); } #------------------------------------------------------------- # mcc dialog specific functions sub splash_warning { my ($label, $o_cancel_button) = @_; warn_dialog(N("Warning"), $label, { cancel => $o_cancel_button }); } sub new_dialog { my ($title, $o_no_button) = @_; my $dialog = gtkset_border_width(Gtk2::Dialog->new, 10); $dialog->set_transient_for($window_global); $dialog->set_position('center-on-parent'); $dialog->set_title($title); $dialog->action_area->pack_start(gtkadd(Gtk2::HButtonBox->new, gtksignal_connect(Gtk2::Button->new(N("Close")), clicked => sub { $dialog->destroy }) ), 0,0,0) unless $o_no_button; gtkset_modal($dialog, 1); } sub more_themes() { my $window_about = new_dialog(N("More themes")); gtkpack_($window_about->vbox, 0, Gtk2::Label->new(N("Getting new themes")), 0, gtkadd(gtkset_shadow_type(gtkset_border_width(Gtk2::Frame->new(N("Additional themes")), 10), 'etched_out'), gtkpack(Gtk2::HBox->new(0, 5), N("Get additional themes on www.damz.net"), ) ) ); $window_about->show_all; } sub about_mdk_cc() { my $window_about = new_dialog(N("About - Mandriva Linux Control Center")); my $tree_model = Gtk2::TreeStore->new("Glib::String", "Glib::String", "Glib::String"); my $credits = Gtk2::TextView->new; my $list = Gtk2::TreeView->new_with_model($tree_model); $list->can_focus(0); each_index { $list->append_column(Gtk2::TreeViewColumn->new_with_attributes(undef, Gtk2::CellRendererText->new, 'text' => $::i)) } 0..1; $list->set_headers_visible(0); foreach my $row ([ N("Authors: "), '' ], [ '', 'Chmouel Boudjnah' ], [ '', 'Damien "dam\'s" Krotkine', #-PO "perl" here is the programming language N("(perl version)") ], [ '', 'Daouda Lo' ], [ '', 'Thierry Vignaud' ], [ '', 'Yves Duret' ], [ '', '' ], [ N("Artwork: "), '', '' ], [ '', 'Anh-Van Nguyen' ], [ '', #-PO If your language allows it, use eacute for first "e" and egrave for 2nd one. N("Helene Durosini"), '' ], ) { $tree_model->append_set(undef, [ map_index { $::i => $_ } @$row ]); } my ($previous_type, $not_first_title, $not_first_block); my $locale = lang::read; foreach my $line (grep { $_ ne "\n" && !/^#/ } cat_(top((glob("/usr/share/doc/mandriva-release-*/CREDITS"), glob("/usr/share/doc/mandriva-release-*/CREDITS.$locale->{lang}"))))) { $line =~ s/ Limited Edition 2005 \|//; if (my ($type, $comment, $contributor) = split(/\|/, $line, 3)) { last if !$type; $comment =~ s/^ //; # fix initial space of first section (CREDITS format should be enhanced to specify lines that really are sections) chomp($contributor); if ($previous_type ne $type) { gtktext_append($credits, [ [ join('', if_($not_first_title, "\n"), translate(common::to_utf8($type)), "\n"), { 'weight' => Gtk2::Pango->PANGO_WEIGHT_BOLD, scale => Gtk2::Pango->PANGO_SCALE_LARGE } ] ]); $previous_type = $type; $not_first_title = 1; } if ($contributor) { gtktext_append($credits, #-PO: this is used as "language: translator" in credits part of the about dialog: N("- %s: %s\n", map { translate($_) } $comment, $contributor) ); } else { $comment = $comment . "\n" if !$not_first_block; # fix spacing before second title; gtktext_append($credits, join('', if_($not_first_block, "- "), translate($comment))); $not_first_block = 1; } } } # Give our translators the ability to show their family and # friends that thez participated ... #-PO Add your Name here to find it in the About section in your language. my $translator_name = N("_: NAME OF TRANSLATORS\nYour names"); #-PO Add your E-Mail address here if you want to show it in the about doialog. my $translator_email = N("_: EMAIL OF TRANSLATORS\nYour emails"); if ($translator_name ne "Your names" && 0) { $tree_model->append_set(undef, [ 0 => $_->[0], 1 => $_->[1] ]) foreach [ '', '' ], [ N("Translator: ") ]; $tree_model->append_set(undef, [ 0 => $_->[0], 1 => $_->[1] ]) foreach [ '', $translator_name, $translator_email ]; } $list->get_selection->set_mode('none'); gtkpack_($window_about->vbox, (0, gtkset_size_request(Gtk2::Banner->new('splash_screen_about', #-PO: here, %s will be replaced by the version (eg: "Mandriva Linux 2007.1 (Discovery) Control Center") N("Mandriva Linux %s (%s) Control Center", @$release{qw(version product)}), { txt_ypos => 50 }), -1, 120)), 0, Gtk2::Label->new(""), 0, Gtk2::Label->new(N("Copyright (C) 1999-2007 Mandriva SA") . "\n"), 0, Gtk2::HSeparator->new, 0, Gtk2::Label->new(""), 1, my $n = Gtk2::Notebook->new, ); add2notebook($n, N("Authors"), $list); add2notebook($n, N("Mandriva Linux Contributors"), gtkset_size_request(create_scrolled_window($credits), 650, 50)); $window_about->show_all; } #------------------------------------------------------------- # mcc specific graphic functions: sub set_page_raw { my ($bool) = @_; foreach my $notebook ($notebook_global, $banner_notebook) { $notebook->set_current_page($bool); } } sub set_page { my ($index) = @_; start_logdrake(); set_page_raw($index); $help_on_context = $ctx[$index]; hide_buttons(); } sub hide_buttons() { $buttons->hide; $cancel->hide; } sub create_packtable2 { my ($options, @l) = @_; my $w = Gtk2::Table->new(0, 0, 1); add2hash_($options, { xpadding => 5, ypadding => 0 }); each_index { my ($i, $l) = ($::i, $_); each_index { my $j = $::i; if ($_) { ref $_ or $_ = gtknew('WrappedLabel', text => $_); $w->attach($_, $j, $j + 1, $i, $i + 1, ['expand', 'fill'], ['expand', 'fill'], $options->{xpadding}, $options->{ypadding}); $_->show; } } @$l; } @l; $w->set_col_spacings($options->{col_spacings} || 0); $w->set_row_spacings($options->{row_spacings} || 0); gtkset_border_width($w, $::isInstall ? 3 : 10); } #------------------------------------------------------------- # mcc specific graphic functions: sub rtl_gtkcreate_pixbuf { my ($icon) = @_; my $pixbuf; eval { $pixbuf = ugtk2::gtkcreate_pixbuf($icon . "_rtl") } if lang::text_direction_rtl(); $pixbuf ||= ugtk2::gtkcreate_pixbuf($icon); } sub rtl_gtkcreate_img { my ($icon) = @_; lang::text_direction_rtl() ? ugtk2::gtkcreate_img($icon . "_rtl") : ugtk2::gtkcreate_img($icon); } sub new_pixbuf { my ($pixbuf) = @_; my ($height, $width) = ($pixbuf->get_height, $pixbuf->get_width); my $new_pixbuf = Gtk2::Gdk::Pixbuf->new('rgb', 1, 8, $height, $width); $new_pixbuf->fill(0x00000000); # transparent white $width, $height, $new_pixbuf; } sub render_alpha { my ($pixbuf, $alpha_threshold) = @_; my ($width, $height, $new_pixbuf) = new_pixbuf($pixbuf); $pixbuf->composite($new_pixbuf, 0, 0, $width, $height, 0, 0, 1, 1, 'nearest', $alpha_threshold); $new_pixbuf; } sub render_shiner { my ($pixbuf, $shine_value) = @_; my $new_pixbuf = (new_pixbuf($pixbuf))[2]; $pixbuf->saturate_and_pixelate($new_pixbuf, $shine_value, 0); $new_pixbuf; } sub scale { my ($pixbuf, $gain) = @_; my ($width, $height) = ($pixbuf->get_height, $pixbuf->get_width); $pixbuf->scale_simple($height+$gain, $width+$gain, 'hyper'); } 1;