#!/usr/bin/perl # -*- coding: utf-8 -*- # # Copyright (C) 2001-2007 by Mandriva SA # DUPONT Sebastien # Damien Chaumette # Thierry Vignaud # # 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. # # drakfont Future Overview # - Fonts import: # pfb ( Adobe Type 1 binary ) # pfa ( Adobe Type 1 ASCII ) # ttf ( True-Type ) # pcf.gz # Speedo # and Bitmap (PCF, BDF, and SNF) # - Features # - Install fonts from any directory # - Get windows fonts on any vfat partitions # - Get fonts on any partitions. # - UN-installation of any fonts (even if not installed through drakfont) # - Support # - Xfs # - ghostscript & printer # - Staroffice & printer # - abiword # - netscape # - Koffice, Gnumeric, ... studying # - all fonts supported by printer # - anti-aliases by RENDER in Xfree86 .... # supported by KDE. # will be supported by gnome 1.2. # Visual Interface: # Window interface: # - Fontselectiondialog widget # - Command buttons under Fontselectiondialog (like the actual frontend). # Commands buttons: # - import from windows partition. # import from all fat32 partitions and look for winnt/windows/font # and import all (delete doubles) but do not import if they already exist. # - import from directory # look to see if each font exists and do not delete the original. # (replace all, no, none) # expert options: # specify the directory, and look to see if it exists before # if it exists ask: (replace all, no, none) # - uninstall with list per font type # Expert additional switch # - option support: ghostscript, Staroffice, etc... # check-button. (by default all check) # - Printer Application Fonts Support... # check-button. (by default all check) # # TODO: # - Speedo and Bitmap (PCF, BDF, and SNF) # # REQUIRE: # - font-tools.*.mdk.i586.rpm # # USING: # - pfm2afm: by Ken Borgendale: Convert a Windows .pfm file to a .afm (Adobe Font Metrics) # - type1inst: by James Macnicol: type1inst generates files fonts.dir fonts.scale & Fontmap. # - ttf2pt1: by Andrew Weeks, Frank Siegert, Thomas Henlich, Sergey Babkin convert ttf font files to afm and pfb fonts # # # directory to install fonts /usr/lib/X11/fonts/ # -->> /usr/lib/X11/fonts/drakfont use strict; use diagnostics; use utf8; use lib qw(/usr/lib/libDrakX); use standalone; #- warning, standalone must be loaded very first, for 'explanations' use mygtk2 qw(gtknew); #- do not import gtkadd which conflicts with ugtk2 version use ugtk2 qw(:create :dialogs :helpers :wrappers); use common; use run_program; require_root_capability(); $ugtk2::wm_icon = "drakfont"; # global variables needed by each functions my $xlsfonts = 0; my $windows = 0; my $replace; my $so = 1; my $gs = 1; my $abi = 1; my $printer = 1; my $mode = -1; my @application; my @install; my @uninstall; my $interactive; my $pbar; my $pbar1; my $pbar2; my $pbar3; my $window1; my $model; my $list; my $list_all_font_path; my $left_list; my $right_list; my $left_model; my $right_model; foreach (@ARGV) { /--list|-l/ and $list_all_font_path = 1, $mode = -1; /--xls_fonts/ and $xlsfonts = 1, $mode = -1; /--windows_import|-wi/ and $windows = 1, $mode = -1; /--replace|-r/ and $replace = 1, $mode = -1; /--application/ and $mode = 0, next; $mode == 0 and push @application, $_; /--install/ and $mode = 1, next; $mode == 1 and push @install, $_; /--uninstall/ and $mode = 2, next; $mode == 2 and push @uninstall, $_; } foreach my $i (@application) { if ($i =~ /so/i) { if ($gs != 2) { $gs = 0 } $so = 2; } if ($i =~ /gs/i) { if ($so != 2) { $so = 0 } $gs = 2; } } # PATH and binary full path #my $xfs_conffile = '/etc/fonts/fonts.conf'; my $font_dir = '/usr/share/fonts'; my $fontpathd_dir = '/etc/X11/fontpath.d/'; my $drakfont_dir = "$font_dir/drakfont"; my $ttf2pt1 = '/usr/sbin/ttf2pt1'; my $pfm2afm = '/usr/sbin/pfm2afm'; my $type1inst = '/usr/sbin/type1inst'; my $chkfontpath = '/usr/sbin/chkfontpath'; # mkttfdir only knows about iso-8859-1, using ttmkfdir -u instead -- pablo my $ttmkfdir = '/usr/sbin/ttmkfdir'; my $fccache = '/usr/bin/fc-cache'; my @font_list; # list of fonts to install my @installed_fonts; # list of installed fonts my @installed_fonts_path; # list of path included in xfs my @installed_fonts_full_path; # full path list of fonts to uninstall sub list_fontpath() { foreach (uniq((map { expand_symlinks($_) } glob_("$fontpathd_dir/*")), grep { /\d+:\s/ } `$chkfontpath -l`)) { chomp; s/\d+:\s//gi; s/:\w*$//gi; push @installed_fonts_path, $_; } } sub chk_empty_xfs_path() { foreach my $tmp_path (@installed_fonts_path) { if (every { /^fonts/ || /^type/ } all($tmp_path)) { system("$chkfontpath -r $tmp_path ") or print "PERL::system command failed during chkfontpath\n"; } } } sub search_installed_fonts() { list_fontpath(); interactive_progress($pbar, 0.1, N("Search installed fonts")); push @installed_fonts, all($_) foreach @installed_fonts_path; interactive_progress($pbar, 0.1, N("Unselect fonts installed")); } sub search_installed_fonts_full_path() { list_fontpath(); foreach my $i (@installed_fonts_path) { foreach my $j (all($i)) { push @installed_fonts_full_path, "$i/$j"; } } } sub search_windows_font() { my @fonts; foreach my $fstab_line (grep { /vfat|smbfs|ntfs|fuse/ } cat_('/etc/mtab')) { my $win_dir = (split('\s', $fstab_line))[1]; foreach my $sys_dir (grep { /^win(nt|dows)$/i } all($win_dir)) { foreach my $font_dir (grep { /^fonts$/i } map { all($_) } "$win_dir/$sys_dir") { push @fonts, map { "$win_dir/$sys_dir/$font_dir/$_" } all("$win_dir/$sys_dir/$font_dir"); } } } my $nb_dir = @fonts; if (!$nb_dir) { err_dialog(N("Error"), N("No fonts found")); return 0; } foreach my $font (@fonts) { progress($pbar, 0.25 / $nb_dir, N("parse all fonts")); my $font_name = basename($font); !$replace && any { /^$font_name$/ } @installed_fonts and next; any { /^$font_name$/ } @font_list or push @font_list, $font; } $interactive && $nb_dir and progress($pbar, 1, N("done")); if (!@font_list) { print "[35mdrakfont:: could not find any font in /win*/fonts [0m\n"; $interactive and err_dialog(N("Error"), N("Could not find any font in your mounted partitions")); return 0; } 1; } my @font_extensions = qw(ttf ttc pfa pfb pcf pcf.gz pfm gsf ttc otf); sub is_a_font($) { my ($file) = @_; any { $file =~ /\Q.$_\E$/i } @font_extensions; } # Optimisation de cette etape indispensable sub search_dir_font() { foreach my $fn (@install) { my @font_list_tmp; if (!(-e $fn)) { print "$fn :: no such file or directory \n" } else { if (-d $fn) { foreach my $i (all($fn)) { if (is_a_font($i)) { push @font_list_tmp, $i; foreach my $i (@font_list_tmp) { !$replace && any { /$i/ } @installed_fonts and next; any { /$i/ } @font_list or push @font_list, "$fn/$i"; } } } } elsif (is_a_font($fn)) { !$replace && any { /$fn/ } @installed_fonts and next; !any { /$fn/ } @installed_fonts and push @font_list, $fn; } } interactive_progress($pbar, 0.50 / @install, N("Reselect correct fonts")); } interactive_progress($pbar, 1, N("done")); !@font_list && $interactive and err_dialog(N("Error"), N("Could not find any font.\n")); } sub search_dir_font_uninstall { my ($fn) = @_; print "Fonts to uninstal: " . $_ . "\n" foreach uniq(@font_list, -d $fn ? (grep { is_a_font($_) } all($fn)) : if_(is_a_font($fn), $fn)); } sub search_dir_font_uninstall_gi() { @font_list = @uninstall; interactive_progress($pbar, 1, N("Search for fonts in installed list")); } sub print_list() { print "Font(s) to Install:\n\n"; print "$_\n" foreach @font_list; } sub dir_created() { return if $::testing; foreach (qw(Type1 ttf otf ttc tmp/ttf tmp/Type1 tmp/tmp)) { my $dir = "$drakfont_dir/$_"; next if -e $dir; mkdir_p($dir); symlink($dir, "$fontpathd_dir/drakfont_$_:pri=50"); } } sub convert_fonts { my ($fonts, $converter, $font_type, $o_generate_pfb) = @_; $o_generate_pfb = $o_generate_pfb ? "-b" : ""; foreach my $fontname (@$fonts) { system("cd $drakfont_dir/tmp/tmp && $converter $o_generate_pfb $fontname"); interactive_progress($pbar2, 0.50 / @$fonts, N("%s fonts conversion", $font_type)); } } sub convert_ttf_fonts { my ($fonts, $o_generate_pfb) = @_; convert_fonts($fonts, $ttf2pt1, "TTF", $o_generate_pfb); } sub move_fonts { my ($src_dir, $dest_dir, @extensions) = @_; my @fonts = map { s!.*/!!; $_ } map { glob("$src_dir/*.$_") } @extensions; system("cd $src_dir && mv @fonts $dest_dir") if @fonts; } sub my_rm_rf { my ($target) = @_; eval { rm_rf(@_) }; if (my $err = $@) { warn "cannot remove $target: $err\n"; } } sub put_font_dir_real { my ($subdir, $command, $progress, $title) = @_; system("cd $drakfont_dir/$subdir && $fccache && $command"); interactive_progress($pbar2, $progress, $title); return "$chkfontpath -a $drakfont_dir/$subdir; rm -f $font_dir/fonts.cache-1"; } sub put_font_dir() { -e "/usr/share/ghostscript" or do { $gs = 0; print "ghostscript is not installed on your system...\n" }; if (@font_list) { dir_created(); foreach my $i (@font_list) { cp_af($i, $drakfont_dir . "/tmp/tmp"); interactive_progress($pbar1, 1 / @font_list, N("Fonts copy")); } interactive_progress($pbar1, 0.01, N("done")); interactive_progress($pbar2, 0.10, N("True Type fonts installation")); my $temp_dir = "$drakfont_dir/tmp/tmp/"; foreach my $font (glob("$temp_dir/*.TTF")) { my $newfont = $font; $newfont =~ s/\.TTF$/.ttf/; rename($font, $newfont); } system('cd ' . $temp_dir . ' && cp *.ttf ../../ttf; chmod 644 ../../ttf/*ttf') if glob("$temp_dir/*.ttf"); interactive_progress($pbar2, 0.20, N("please wait during ttmkfdir...")); my $update_chkfontpath = put_font_dir_real("ttf", "$ttmkfdir -u > fonts.dir", 0.10, N("True Type install done")); if ($gs) { convert_ttf_fonts([ glob("$drakfont_dir/tmp/tmp/*.ttf") ], 1); move_fonts("$drakfont_dir/tmp/tmp", "../Type1", qw(afm gsf pfb pfm)); system("cd $drakfont_dir/tmp/Type1 && $type1inst"); interactive_progress($pbar2, 0.1, N("type1inst building")); if ($so) { -e "$drakfont_dir/tmp/Type1/Fontmap" and system("cd $drakfont_dir/tmp/Type1 && cat Fontmap >> `rpm -ql ghostscript-common | grep Fontmap.GS` "); move_fonts("$drakfont_dir/tmp/Type1", "../../Type1", qw(afm gsf pfb pfm)); } else { system("cd $drakfont_dir/tmp/Type1 && cat Fontmap >> `rpm -ql ghostscript-common | grep Fontmap.GS` "); move_fonts("$drakfont_dir/tmp/Type1", "../../Type1", qw(afm gsf pfb pfm)); } $update_chkfontpath .= "; " . put_font_dir_real("Type1", $type1inst, 0.05, N("Ghostscript referencing")); } elsif ($so) { convert_ttf_fonts([ glob("$drakfont_dir/tmp/tmp/*.ttf") ]); convert_fonts([ glob("$drakfont_dir/tmp/tmp/*.pfm") ], $pfm2afm, "PFM"); move_fonts("$drakfont_dir/tmp/tmp", "../Type1", qw(afm)); move_fonts("$drakfont_dir/tmp/Type1", "../../Type1", qw(afm)); $update_chkfontpath .= put_font_dir_real("Type1", $type1inst, 0.14, N("type1inst building")); } foreach my $subdir (qw(otf ttc)) { my $dir = "$drakfont_dir/$subdir"; move_fonts("$drakfont_dir/tmp/tmp", "../../$subdir", $subdir); run_program::run($_, $dir) foreach qw(mkfontscale mkfontdir), $fccache; run_program::run($chkfontpath, '-a', $dir); } interactive_progress($pbar2, 1, N("done")); interactive_progress($pbar3, 0.25, N("Suppress Temporary Files")); my_rm_rf("$drakfont_dir/tmp/"); print "\n\nretarting xfs......\n"; interactive_progress($pbar3, 0.5, N("Restart XFS")); system($update_chkfontpath); system('/etc/rc.d/init.d/xfs restart'); system('xset fp rehash'); interactive_progress($pbar3, 0.30, N("done")); } } sub remove_gs_fonts() { my @Fontmap_new; if (all("$drakfont_dir/remove")) { system(" cd $drakfont_dir/remove && $type1inst"); my @Fontmap_out = cat_("$drakfont_dir/remove/Fontmap"); my $FontmapGS = `rpm -ql ghostscript-common | grep Fontmap.GS`; chomp($FontmapGS); my @FontmapGS_list = cat_($FontmapGS); foreach my $font_gs (@FontmapGS_list) { my @tmp_list = split(' ', $font_gs); any { /$tmp_list[0]/ } @Fontmap_out or push @Fontmap_new, $font_gs; } print $_ foreach @Fontmap_new; output($FontmapGS, @Fontmap_new); } } sub remove_fonts() { my @list_dir; -e $drakfont_dir . "/remove" or mkdir_p($drakfont_dir . "/remove") if !$::testing; interactive_progress($pbar, 1, N("done")); foreach my $i (@font_list) { local $_ = $i; if (/.pfb$/ || /.gsf$/ || /.pfm$/ || /.pfa$/) { system("mv $_ $drakfont_dir/remove "); } else { next if $::testing; if (/.ttf$/) { my_rm_rf($_); # rebuild of the fonts.dir and fc-cache files system("cd `dirname $_` && $fccache && $ttmkfdir -u > fonts.dir"); } else { my_rm_rf($i) } } $i =~ s!/\w*\.\w*!!gi; any { $i } @list_dir or push @list_dir, $i; interactive_progress($pbar1, 1 / @font_list, N("Suppress Fonts Files")); } interactive_progress($pbar1, 0.01, N("done")); -e "/usr/share/ghostscript" and remove_gs_fonts(); foreach my $i (@list_dir) { if (listlength all($i) < 3) { system("chkfontpath -r $i") or print "PERL::system command failed during chkfontpath\n"; } else { system("cd $i && type1inst") or print "PERL::system command failed during cd or type1inst\n"; } interactive_progress($pbar2, 1 / @list_dir, N("Suppress Fonts Files")); } interactive_progress($pbar2, 0.01, N("Restart XFS")); system("/etc/rc.d/init.d/xfs restart"); system('xset fp rehash'); -e "/usr/share/ghostscript" and my_rm_rf("$drakfont_dir/remove") if !$::testing; interactive_progress($pbar2, 0.01, N("done")); } sub license_msg() { N("Before installing any fonts, be sure that you have the right to use and install them on your system.\n\nYou can install the fonts the normal way. In rare cases, bogus fonts may hang up your X Server.") . "\n"; } sub backend_mod() { $xlsfonts and system("xlsfonts"); $list_all_font_path and system($chkfontpath); if ($windows) { print license_msg(); print "\nWindows fonts Installation........\n"; search_installed_fonts(); if (search_windows_font()) { print_list(); put_font_dir(); } print "\nThe End...........................\n"; } if (@install) { print license_msg(); print "\nInstall Specifics Fonts...........\n"; search_installed_fonts(); search_dir_font(); print "Font to install: " . $_ . "\n" foreach @font_list; put_font_dir(); print "\nThe End...........................\n"; } if (@uninstall) { print "\nUninstall Specifics Fonts.........\n"; search_installed_fonts_full_path(); if ($interactive) { search_dir_font_uninstall_gi() } else { search_dir_font_uninstall($_) foreach @uninstall } remove_fonts(); print "\nThe End............................\n"; } } sub interactive_mode() { $interactive = 1; $window1 = ugtk2->new(N("Font Installation")); $::main_window = $window1->{real_window}; $window1->{rwindow}->signal_connect(delete_event => sub { ugtk2->exit(0) }); $window1->{rwindow}->set_position('center') if !$::isEmbedded; my $button = {}; my $disable = sub { my ($b) = @_; $button->{$_}->set_sensitive($_ ne $b) foreach keys %$button }; local $::Wizard_no_previous = 1; gtkadd($window1->{window}, gtkpack_(Gtk2::VBox->new(0, 2), if_(!$::isEmbedded, 0, Gtk2::Banner->new("drakfont", N("DrakFont"))), 0, gtknew('Title2', label => N("Font List")), 1, Gtk2::FontSelection->new, 0, gtkadd(create_hbox(), gtksignal_connect(Gtk2::Button->new(N("Get Windows Fonts")), clicked => sub { $windows = 1; import_status(); $windows = 0 }), ), 0, create_okcancel(my $oc = { ok_clicked => sub { Gtk2->main_quit }, }, undef, undef, '', if_(0, [ N("About"), \&help, 1 ]), [ N("Options"), \&appli_choice, 1 ], [ N("Uninstall"), \&uninstall, 1 ], [ N("Import"), \&advanced_install, 1 ], ), ), ); $oc->{ok}->set_label(N("Close")); $disable->('font_list'); $window1->{rwindow}->show_all; $window1->{rwindow}->realize; $window1->main; ugtk2->exit(0); } $list_all_font_path || $xlsfonts || $windows || @install || @uninstall ? backend_mod() : interactive_mode(); sub help() { my $license = formatAlaTeX(translate($::license)); $license =~ s/\n/\n\n/sg; # nicer formatting my $w = gtknew('AboutDialog', name => N("Drakfont"), version => '2007', copyright => N("Copyright (C) 2001-2006 by Mandriva"), license => $license, wrap_license => 1, comments => N("Font installer."), website => 'http://mandrivalinux.com', website_label => N("Mandriva Linux"), authors => 'Sébastien Dupont Damien Chaumette Thierry Vignaud <vignaud@mandriva.com>', artists => 'Hélène Durosini <ln@mandriva.com>', translator_credits => #-PO: put here name(s) and email(s) of translator(s) (eg: "John Smith <jsmith@nowhere.com>") N("_: Translator(s) name(s) & email(s)\n"), transient_for => $window1->{real_window}, modal => 1, position_policy => 'center-on-parent', ); $w->show_all; $w->run; } sub appli_choice() { dialog(N("Options"), [ 0, gtknew('Title2', label => N("Choose the applications that will support the fonts:")), 0, Gtk2::WrappedLabel->new(formatAlaTeX(license_msg())), (map { my ($label, $ref) = @$_; (0, gtkpack_(Gtk2::HBox->new, 0, $label, 1, Gtk2::HBox->new, # BUG: that code never had supported canceling 0, gtksignal_connect(gtkset_active(Gtk2::CheckButton->new, $$ref), toggled => sub { $$ref = $$ref ? 0 : 1 }), ), ); } ([ N("Ghostscript"), \$gs ], [ N("OpenOffice.org"), \$so ], [ N("Abiword"), \$abi ], [ N("Generic Printers"), \$printer ], ), ), ], [ gtksignal_connect(Gtk2::Button->new(N("Ok")), clicked => \&exitdialog, ), ], ); } sub font_choice() { my $file_dialog; my $_select_font_msg = N("Select the font file or directory and click on 'Add'"); $file_dialog = Gtk2::FileChooserDialog->new(N("File Selection"), $::main_window, 'open', N("Cancel") => 'cancel', N("Ok") => 'ok'); # 'select_folder' $file_dialog->set_select_multiple(1); my $filter = Gtk2::FileFilter->new; $filter->set_name(N("Fonts")); $filter->add_pattern("*.$_") foreach @font_extensions, map { uc($_) } @font_extensions; $file_dialog->add_filter($filter); $file_dialog->set_filter($filter); $file_dialog->show; while (my $answer = $file_dialog->run) { if (member($answer, qw(cancel delete-event))) { $file_dialog->destroy; return; } elsif ($answer eq 'ok') { my @files = $file_dialog->get_filenames; foreach my $file_name (difference2(\@files, \@install)) { push @install, $file_name; $model->append_set(undef, [ 0 => $file_name ]); } $file_dialog->destroy; return; } } } sub list_remove() { #- TODO : multi-selection my ($treeStore, $iter) = $list->get_selection->get_selected; return unless $iter; my $to_remove = $treeStore->get($iter, 0); my ($index) = map_index { if_($_ eq $to_remove, $::i) } @install; splice @install, $index, 1; $treeStore->remove($iter); } sub exitdialog() { Gtk2->main_quit } sub dialog { my ($title, $widgets, $buttons, $o_main_loop, $o_options) = @_; $o_options ||= {}; my $dialog = _create_dialog($title, { transient => $::main_window }); local $::main_window = $dialog; $dialog->signal_connect(delete_event => \&exitdialog); $dialog->set_size_request(@{$o_options->{size}}) if ref $o_options->{size}; gtkpack_($dialog->vbox, @$widgets); gtkpack($dialog->action_area, @$buttons) if $buttons; $dialog->show_all; if ($o_main_loop) { gtkflush(); $o_main_loop->(); } else { Gtk2->main; } $dialog->destroy if $dialog; undef $dialog; } sub advanced_install() { my $button; $model = Gtk2::TreeStore->new("Glib::String"); $list = Gtk2::TreeView->new_with_model($model); $list->append_column(Gtk2::TreeViewColumn->new_with_attributes(undef, Gtk2::CellRendererText->new, 'text' => 0)); $list->set_headers_visible(0); $list->get_selection->set_mode('browse'); $list->set_rules_hint(1); $model->signal_connect("row-inserted" => sub { $button and $button->set_sensitive(1) }); $model->signal_connect("row-deleted" => sub { $button and $button->set_sensitive($model->get_iter_first) }); dialog(N("Import fonts"), [ 0, gtknew('Title2', label => N("Font List")), 1, gtknew('HBox', children => [ 1, create_scrolled_window($list), 0, gtknew('VBox', children_tight => [ gtksignal_connect(Gtk2::Button->new(N("Add")), clicked => \&font_choice), gtksignal_connect(Gtk2::Button->new(N("Remove")), clicked => \&list_remove), ]), ]), ], [ gtksignal_connect(Gtk2::Button->new(N("Cancel")), clicked => \&exitdialog), gtksignal_connect($button = gtkset_sensitive(Gtk2::Button->new(N("Install")), 0), clicked => sub { import_status() if @install; }), ], undef, { size => [ 300, 200 ] }, ); } sub list_to_remove() { #my @files_path = grep(!/fonts/, all($current_path)); garbage ? gtkflush(); my (@tux) = $left_list->get_selection->get_selected_rows; #- get tree & paths push @uninstall, map { $left_model->get($left_model->get_iter($_), 0) } @tux; #push @uninstall, $current_path . "/" . $files_path[$_] foreach @number_to_remove; garbage ? show_list_to_remove(); } sub show_list_to_remove() { my $model = Gtk2::TreeStore->new("Glib::String"); my $list = Gtk2::TreeView->new_with_model($model); $list->append_column(Gtk2::TreeViewColumn->new_with_attributes(undef, Gtk2::CellRendererText->new, 'text' => 0)); $list->set_headers_visible(0); $list->get_selection->set_mode('browse'); $list->set_rules_hint(1); $model->append_set(undef, [ 0 => $_ ]) foreach sort @uninstall; dialog(N("Warning"), [ 0, Gtk2::Label->new(N("Are you sure you want to uninstall the following fonts?")), 1, gtkpack_(Gtk2::HBox->new(0, 4), 1, create_scrolled_window($list)), ], [ gtksignal_connect(Gtk2::Button->new(N("Yes")), clicked => sub { import_status_uninstall(); exitdialog() }), gtksignal_connect(Gtk2::Button->new(N("No")), clicked => \&exitdialog ), ], ); } sub uninstall() { #- TODO : add item to right list with gtksignal_connect @install = (); @installed_fonts_path = (); list_fontpath(); chk_empty_xfs_path(); #- left part $left_model = Gtk2::TreeStore->new("Glib::String"); $left_list = Gtk2::TreeView->new_with_model($left_model); $left_list->append_column(Gtk2::TreeViewColumn->new_with_attributes(undef, Gtk2::CellRendererText->new, 'text' => 0)); $left_list->set_headers_visible(0); $left_list->set_rules_hint(1); $left_list->get_selection->set_mode('multiple'); $left_model->append_set(undef, [ 0 => $_ ]) foreach sort @installed_fonts_path; #- right part $right_model = Gtk2::TreeStore->new("Glib::String"); $right_list = Gtk2::TreeView->new_with_model($right_model); $right_list->append_column(Gtk2::TreeViewColumn->new_with_attributes(undef, Gtk2::CellRendererText->new, 'text' => 0)); $right_list->set_headers_visible(0); $right_list->get_selection->set_mode('multiple'); $right_list->set_rules_hint(1); dialog(N("Uninstall"), [ 1, gtkpack_(Gtk2::HBox->new(0, 4), 1, create_scrolled_window($left_list), #1, create_scrolled_window($right_list) ), ], [ gtksignal_connect(Gtk2::Button->new(N("Unselected All")), clicked => sub { $left_list->get_selection->unselect_all } ), gtksignal_connect(Gtk2::Button->new(N("Selected All")), clicked => sub { $left_list->get_selection->select_all } ), gtksignal_connect(Gtk2::Button->new(N("Remove")), clicked => sub { exitdialog(); list_to_remove() }), gtksignal_connect(Gtk2::Button->new(N("Cancel")), clicked => \&exitdialog), ], undef, { size => [ -1, 300 ] } ); } sub import_status() { $pbar = Gtk2::ProgressBar->new; $pbar1 = Gtk2::ProgressBar->new; $pbar2 = Gtk2::ProgressBar->new; $pbar3 = Gtk2::ProgressBar->new; dialog(N("Importing fonts"), [ 0, create_packtable({ col_spacings => 10, row_spacings => 50 }, [ "", "" ], [ N("Initial tests"), $pbar, $pbar->set_text(' ') ], [ N("Copy fonts on your system"), $pbar1, $pbar1->set_text(' ') ], [ N("Install & convert Fonts"), $pbar2, $pbar2->set_text(' ') ], [ N("Post Install"), $pbar3, $pbar3->set_text(' ') ], ), ], [], \&backend_mod, ); } sub import_status_uninstall() { $pbar = Gtk2::ProgressBar->new; $pbar1 = Gtk2::ProgressBar->new; $pbar2 = Gtk2::ProgressBar->new; dialog(N("Importing fonts"), [ 0, create_packtable({ col_spacings => 10, row_spacings => 50 }, [ "", "" ], [ "", "" ], [ N("Initial tests"), $pbar, $pbar->set_text(' ') ], [ N("Remove fonts on your system"), $pbar1, $pbar1->set_text(' ') ], [ N("Post Uninstall"), $pbar2, $pbar2->set_text(' ') ], ), ], [], \&backend_mod, ); } sub progress { my ($progressbar, $incr, $label_text) = @_; $progressbar->set_fraction(min(1, $progressbar->get_fraction + $incr)); $progressbar->set_text($label_text); gtkflush(); } sub interactive_progress { $interactive and progress(@_); }