#!/usr/bin/perl # vim: set et ts=4 sw=4: # -*- coding: utf-8 -*- #***************************************************************************** # # Copyright (c) 2002 Guillaume Cottenceau # Copyright (c) 2002-2008 Thierry Vignaud # Copyright (c) 2003, 2004, 2005 MandrakeSoft SA # Copyright (c) 2005-2008 Mandriva SA # Copyright (c) 2013 Matteo Pasotti # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License version 2, as # published by the Free Software Foundation. # # 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. # #***************************************************************************** # # $Id: rpmdragora 267936 2010-04-26 16:40:21Z jvictor $ use MDK::Common::Func 'any'; use lib qw(/usr/lib/libDrakX); use common; use utf8; # TO WORKAROUND LOCALIZATION ISSUE use AdminPanel::Rpmdragora::localization; use AdminPanel::Rpmdragora::init; use standalone; #- standalone must be loaded very first, for 'explanations', but after rpmdragora::init use AdminPanel::rpmdragora; use AdminPanel::Shared; use AdminPanel::Shared::Locales; use AdminPanel::Rpmdragora::open_db; use AdminPanel::Rpmdragora::gui; use AdminPanel::Rpmdragora::rpmnew; use AdminPanel::Rpmdragora::formatting; use AdminPanel::Rpmdragora::pkg; use urpm::media; use yui; use AdminPanel::Rpmdragora::widgets; use feature 'state'; # OLD $ugtk2::wm_icon = get_icon('installremoverpm', "title-$MODE"); #TODO fix $wm_resource_path my $wm_resource_path="/usr/share/rpmdrake/icons"; my $wm_icon = "$wm_resource_path"."/title-$MODE.png"; # Declarations my $my_win; my $factory; my $mgaFactory; my $optFactory; my $extWidgets; my @itemsToBeRemoved; my @itemsToBeInstalled; our $w; our $statusbar; my $loc = AdminPanel::rpmdragora::locale(); my %elems; my $old_value; sub viewbox_callback { my ($selection, $options, $wanted_categories) = @_; my $val = $selection; $old_value="" if(!defined($old_value)); return if $val eq $old_value; # workarounding gtk+ sending us sometimes twice events yui::YUI::app()->busyCursor(); $old_value = $val; $default_list_mode = $options->{rviews}{$val}; # NOTE an undef value assignment produces a an array containing undef that is not a valid value to pass to # join into writeconf() @$mandrakeupdate_wanted_categories = $wanted_categories->{$options->{rviews}{$val}} ? @{$wanted_categories->{$options->{rviews}{$val}}} : (); if ($options->{tree_mode} ne $val) { $tree_mode->[0] = $options->{tree_mode} = $options->{rviews}{$val}; $tree_flat->[0] = $options->{state}{flat}; reset_search(); switch_pkg_list_mode($options->{rviews}{$val}); $options->{rebuild_tree}->(); } yui::YUI::app()->normalCursor(); } sub filterbox_callback { my ($selection, $options, $rfilters) = @_; state $oldval; my $val = $selection; return if $val eq $oldval; # workarounding gtk+ sending us sometimes twice events yui::YUI::app()->busyCursor(); $oldval = $val; $val = $$rfilters{$val}; if ($filter->[0] ne $val) { $filter->[0] = $val; reset_search(); slow_func(sub { switch_pkg_list_mode($default_list_mode) }); $options->{rebuild_tree}->(); } yui::YUI::app()->normalCursor(); } my $current_group = -1; sub tree_callback { my ($selection, $options) = @_; #OLD my ($model, $iter) = $tree->currentItem(); #OLD return if !$iter; #state $current_group; #OLD my $new_group = $model->get_path_str($iter); #my $new_group = $selection->index(); #$current_group = -1 if(!defined($current_group)); #return if $current_group eq $new_group && !$force_displaying_group; undef $force_displaying_group; #$current_group = $new_group; #OLD $model && $iter or return; $selection or return; $DB::single = 1; my $fullname = $selection->label(); my $it = $selection; while ($it = $it->parent()) { $fullname = join("|", $it->label(), $fullname); } my $group = $fullname; utf8::decode($group); if (!$selection->hasChildren()) { #$detail_list->window->freeze_updates; $options->{add_nodes}->(@{$elems{$group}}); #$detail_list->window->thaw_updates if $detail_list->window; } return; } sub detaillist_changeditem_callback { my ($detail_list, $options) = @_; my $changedItem = $detail_list->changedItem(); return if (!$changedItem); # handles installist and droplist my $index=0; if ($changedItem->checked()) { # to be installed if not in to be removed list my $found = 0; foreach $index (0 .. scalar(@itemsToBeRemoved) -1) { my $currItem = $itemsToBeRemoved[$index]; #pasmatt why? changedItem is YCBTableItem now so it's what you're looking for # if(ref $currItem eq "yui::YCBTableItem") { if ($currItem->label() eq $changedItem->label()) { $found = 1; splice (@itemsToBeRemoved, $index ,1); last; } # } } if ($found == 0) { push(@itemsToBeInstalled, $changedItem); # $pkgs->{$options->{table_item_list}[$changedItem->index()]}{selected} = 1; # toggle_veloce($options->{table_item_list}[$changedItem->index()],"to_install"); fast_toggle($changedItem); } } else { # to be removed if not in to be installed list my $found = 0; foreach $index (0 .. scalar(@itemsToBeInstalled)-1) { my $currItem = $itemsToBeInstalled[$index]; # if(ref $currItem eq "yui::YCBTableItem") { if ($currItem->label() eq $changedItem->label()) { $found = 1; splice (@itemsToBeInstalled, $index ,1); last; } # } } if ($found == 0) { push(@itemsToBeRemoved, $changedItem); # $pkgs->{$options->{table_item_list}[$changedItem->index()]}{selected} = 0; # toggle_veloce($options->{table_item_list}[$changedItem->index()],"to_remove"); fast_toggle($changedItem); } } print "itemsToBeRemoved counts ".scalar(@itemsToBeRemoved)." items\n"; print "itemsToBeInstalled counts ".scalar(@itemsToBeInstalled)." items\n"; } sub detaillist_callback { my ($selection, $info, $options, $show_options) = @_; $info->setValue(""); return if( ref $selection ne "yui::YItem"); my $info_text ="

" . $loc->N("Informations") . "

"; my @data = get_info($options->{table_item_list}[$selection->index()], $show_options); for(@{$data[0]}){ if(ref $_ ne "ARRAY"){ $info_text .= "
" . $_; }else{ $info_text .= "
"; for my $subitem(@{$_}) { $info_text .= "
" . "
   " . $subitem; } } } # change \n to
$info_text =~ s|\n|
|g; $info->setValue($info_text); } sub _do_search($$$$$$) { my ($find_entry, $tree, $options, $current_search_type, $urpm, $pkgs) = @_; my $entry = $find_entry->value(); return if !$entry; if (!$use_regexp->[0]) { $entry = quotemeta $entry; # enable OR search by default: $entry =~ s/\\ /|/g if $current_search_type eq 'normal'; } # remove leading/trailing spacing when pasting: if ($entry !~ /\S\s\S/) { # if spacing in middle, likely a string search in description $entry =~ s/^\s*//; $entry =~ s/^\s*$//; } my $entry_rx = eval { qr/$entry/i } or return; reset_search(); # TODO FIXME speed up, we cannot remove an item but rebuilding all is slow # We could just rebuild the tree items $options->{rebuild_tree}->(); $options->{state}{flat} and $options->{delete_all}->(); # TODO: write a collapse_all method #$tree->collapse_all; my @search_results; if ($current_search_type eq 'normal') { my $count; foreach (@filtered_pkgs) { if ($NVR_searches->[0]) { next if !/$entry_rx/; } else { next if first(split_fullname($_)) !~ /$entry_rx/; } push @search_results, $_; # FIXME: should be done for all research types last if $count++ > 2000; } } elsif ($current_search_type eq 'summaries') { my $count; foreach (@filtered_pkgs) { next if get_summary($_) !~ /$entry_rx/; push @search_results, $_; # FIXME: should be done for all research types last if $count++ > 2000; } } else { my $searchstop; #my $searchw = ugtk2->new($loc->N("Software Management"), grab => 1, transient => $w->{real_window}); my $searchw = $factory->createPopupDialog; my $vbox = $factory->createVBox($searchw); my $lblWIP = $factory->createLabel($vbox, $loc->N("Please wait, searching...")); my $searchprogress = $factory->createProgressBar($vbox, 'ProgressBar'); my $stop_button = $factory->createIconButton($vbox,"",$loc->N("Stop")); #gtkadd( #$searchw->{window}, #gtkpack__( #gtknew('VBox', spacing => 5), #gtknew('Label', text => $loc->N("Please wait, searching...")), #my $searchprogress = gtknew('ProgressBar', width => 300), #gtkpack__( #gtknew('HButtonBox', layout => 'spread'), #gtksignal_connect( #Gtk2::Button->new(but($loc->N("Stop"))), #clicked => sub { $searchstop = 1 }, #), #), #), #); #$searchw->sync; $searchw->pollEvent(); $searchw->recalcLayout(); $searchw->doneMultipleChanges(); # should probably not account backports packages or find a way to search them: my $total_size = keys %$pkgs; my $progresscount; my $update_search_pb = sub { $progresscount++; if (!($progresscount % 100)) { $progresscount <= $total_size and $searchprogress->setValue($progresscount/$total_size); $searchw->flush; # refresh and handle clicks } }; foreach my $medium (grep { !$_->{ignore} } @{$urpm->{media}}) { $searchstop and last; my $gurpm; # per medium download progress bar (if needed) my $_gurpm_clean_guard = before_leaving { undef $gurpm }; my $xml_info_file = urpm::media::any_xml_info($urpm, $medium, ($current_search_type eq 'files' ? 'files' : 'info'), undef, sub { $gurpm ||= AdminPanel::Rpmdragora::gurpm->new($loc->N("Please wait"), transient => $::main_window); download_callback($gurpm, @_) or do { $searchstop = 1; }; }); if (!$xml_info_file) { $urpm->{error}($loc->N("no xml-info available for medium \"%s\"", $medium->{name})); next; } $searchstop and last; require urpm::xml_info; require urpm::xml_info_pkg; $urpm->{log}("getting information from $xml_info_file"); if ($current_search_type eq 'files') { # special version for speed (3x faster), hopefully fully compatible my $F = urpm::xml_info::open_lzma($xml_info_file); my $fn; local $_; while (<$F>) { if ($searchstop) { statusbar_msg($loc->N("Search aborted"), 1); goto end_search; } if (m!^(); } elsif (/$entry_rx/) { $fn or $urpm->{fatal}("fast algorithm is broken, please report a bug"); push @search_results, $fn; } } } else { eval { urpm::xml_info::do_something_with_nodes( 'info', $xml_info_file, sub { $searchstop and die 'search aborted'; my ($node) = @_; $update_search_pb->(); push @search_results, $node->{fn} if $node->{description} =~ $entry_rx; #$searchstop and last; return 0 || $searchstop; }, ); }; my $err = $@; if ($err =~ /search aborted/) { statusbar_msg($loc->N("Search aborted"), 1); } } } end_search: @search_results = uniq(@search_results); #- there can be multiple packages with same version/release for different arch's @search_results = intersection(\@search_results, \@filtered_pkgs); $searchw->destroy; } # my $iter; if (@search_results) { @search_results = sort_packages(@search_results); $elems{$results_ok} = [ map { [ $_, $results_ok ] } @search_results ]; # $iter = $options->{add_parent}->($tree, $results_ok); AdminPanel::Rpmdragora::gui::add_tree_item($tree, $results_ok, 1); $options->{add_nodes}->(map { [ $_, $results_ok . ($options->{tree_mode} eq 'by_presence' ? '|' . ($pkgs->{$_}{pkg}->flag_installed ? $loc->N("Upgradable") : $loc->N("Addable")) : ($options->{tree_mode} eq 'by_selection' ? '|' . ($pkgs->{$_}{selected} ? $loc->N("Selected") : $loc->N("Not selected")) : '')) ] } @search_results); } else { AdminPanel::Rpmdragora::gui::add_tree_item($tree, $results_none, 1); # $iter = $options->{add_parent}->($tree, $results_none); # clear package list: $options->{add_nodes}->(); my $string = $default_list_mode eq 'all' && $filter->[0] eq 'all' ? $loc->N("No search results.") : $loc->N("No search results. You may want to switch to the '%s' view and to the '%s' filter", $loc->N("All"), $loc->N("All"),); statusbar_msg($string , 1); #gtkset_mousecursor_normal($::w->{rwindow}->window); } my $tree_selection = $tree->currentItem(); } #sub quit() { #($rpmdragora_width->[0], $rpmdragora_height->[0]) = $::w->{real_window}->get_size; #real_quit(); #} sub quit { $my_win->destroy(); } sub run_treeview_dialog { my ($callback_action) = @_; my ($options, $tree, $detail_list, $detail_list_model); (undef, $size_free) = MDK::Common::System::df('/usr'); # OLD $::main_window = $w->{real_window}; $::main_window = $my_win; $size_selected = 0; $options = { build_tree => sub { build_tree($tree, \%elems, $options, $force_rebuild, @_) }, partialsel_unsel => sub { my ($unsel, $sel) = @_; @$sel = grep { exists $pkgs->{$_} } @$sel; @$unsel < @$sel; }, get_status => sub { $loc->N("Selected: %s / Free disk space: %s", formatXiB($size_selected), formatXiB($size_free*1024)); }, rebuild_tree => sub { $tree->rebuildTree(); }, }; my $vbox = $factory->createVBox($my_win); my $hbox_headbar = $factory->createHBox($vbox); my $head_align_left = $factory->createLeft($hbox_headbar); my $head_align_right = $factory->createRight($hbox_headbar); my $headbar = $factory->createHBox($head_align_left); my $headRight = $factory->createHBox($head_align_right); #Line for logo and title my $hbox_iconbar = $factory->createHBox($vbox); $head_align_left = $factory->createLeft($hbox_iconbar); $hbox_iconbar = $factory->createHBox($head_align_left); $factory->createImage($hbox_iconbar, $wm_icon); $factory->createHeading($hbox_iconbar, $::MODE eq 'update' ? $loc->N("Software Packages Update") : $loc->N("Software Management")); my $hbox_top = $factory->createHBox($vbox); my $hbox_middle = $factory->createHBox($vbox); my $hbox_bottom = $factory->createHBox($vbox); my $hbox_footbar = $factory->createHBox($vbox); $hbox_headbar->setWeight(1,10); $hbox_top->setWeight(1,10); $hbox_middle->setWeight(1,50); $hbox_bottom->setWeight(1,30); $hbox_footbar->setWeight(1,10); # Tree for groups $tree = $factory->createTree($hbox_middle, ""); $tree->setWeight(0,20); $tree->setNotify(1); #OLD $tree->get_selection->set_mode('browse'); #OLD $tree->append_column(Gtk2::TreeViewColumn->new_with_attributes(undef, Gtk2::MDV::CellRendererPixWithLabel->new, 'pixbuf' => $grp_columns{icon}, label => $grp_columns{label})); #OLD $tree->set_headers_visible(0); #OLD $detail_list_model = Gtk2::ListStore->new("Glib::String", # "Gtk2::Gdk::Pixbuf", # "Glib::String", # "Glib::Boolean", # "Glib::String", # "Glib::String", # "Glib::String", # "Glib::String", # "Glib::Boolean"); #OLD $detail_list = Gtk2::TreeView->new_with_model($detail_list_model); my $detail_list_header = new yui::YTableHeader(); #$detail_list->append_column( # my $col_sel = Gtk2::TreeViewColumn->new_with_attributes( # undef, # Gtk2::CellRendererToggle->new, # active => $pkg_columns{selected}, # activatable => $pkg_columns{selectable} # )); #$col_sel->set_fixed_width(34); # w/o this the toggle cells are not displayed #$col_sel->set_sizing('fixed'); #$col_sel->set_sort_column_id($pkg_columns{selected}); my $display_arch_col = to_bool(arch() =~ /64/); my @columns = (qw(name version release), if_($display_arch_col, 'arch')); my %columns = ( 'name' => { title => $loc->N("Package"), markup => $pkg_columns{short_name}, }, 'version' => { title => $loc->N("Version"), text => $pkg_columns{version}, }, 'release' => { title => $loc->N("Release"), text => $pkg_columns{release}, }, if_($display_arch_col, 'arch' => { title => #-PO: "Architecture" but to be kept *small* !!! $loc->N("Arch."), text => $pkg_columns{arch}, }), 'mark' => { title => $loc->N("ToInst"), } ); ## check column is first no title needed here, but we need to add it $detail_list_header->addColumn(""); foreach my $col (@columns{@columns}) { #OLD $detail_list->append_column( # $col->{widget} = # Gtk2::TreeViewColumn->new_with_attributes( # ' ' . $col->{title} . ' ', # $col->{renderer} = Gtk2::CellRendererText->new, # ($col->{markup} ? (markup => $col->{markup}) : (text => $col->{text})), # ) # ); #$col->{widget}->set_sort_column_id($col->{markup} || $col->{text}); $detail_list_header->addColumn($col->{title}); } #OLD $columns{$_}{widget}->set_sizing('autosize') foreach @columns; #OLD $columns{name}{widget}->set_property('expand', '1'); #OLD $columns{name}{renderer}->set_property('ellipsize', 'end'); #OLD $columns{$_}{renderer}->set_property('xpad', '6') foreach @columns; #OLD $columns{name}{widget}->set_resizable(1); #OLD $detail_list_model->set_sort_column_id($pkg_columns{text}, 'ascending'); #OLD $detail_list_model->set_sort_func($pkg_columns{version}, \&sort_callback); #OLD $detail_list->set_rules_hint(1); #OLD $detail_list->append_column( # my $pixcolumn = # Gtk2::TreeViewColumn->new_with_attributes( # #-PO: "Status" should be kept *small* !!! # $loc->N("Status"), # my $rdr = Gtk2::CellRendererPixbuf->new, # 'pixbuf' => $pkg_columns{state_icon}) # ); #$rdr->set_fixed_size(34, 24); #$pixcolumn->set_sort_column_id($pkg_columns{state}); $detail_list_header->addColumn($loc->N("Status")); # it should be istanciated this way $detail_list = $mgaFactory->createCBTable($hbox_middle,$detail_list_header,$yui::YCBTableCheckBoxOnFirstColumn); $detail_list->setWeight(0,50); $detail_list->setImmediateMode(1); #OLD compute_main_window_size($w); =for comment my $cursor_to_restore; $_->signal_connect( expose_event => sub { $cursor_to_restore or return; gtkset_mousecursor_normal($tree->window); undef $cursor_to_restore; },) foreach $tree, $detail_list; $tree->currentItem(changed => sub { my ($model, $iter) = $_[0]->get_selected; return if !$iter; state $current_group; my $new_group = $model->get_path_str($iter); return if $current_group eq $new_group && !$force_displaying_group; undef $force_displaying_group; $current_group = $new_group; $model && $iter or return; my $group = $model->get($iter, 0); my $parent = $iter; while ($parent = $model->iter_parent($parent)) { $group = join('|', $model->get($parent, 0), $group); } $detail_list->window->freeze_updates; $options->{add_nodes}->(@{$elems{$group}}); $detail_list->window->thaw_updates if $detail_list->window; }); =cut $options->{state}{splited} = 1; $options->{state}{flat} = $tree_flat->[0]; my $is_backports = get_inactive_backport_media(fast_open_urpmi_db()); my %filters = (all => $loc->N("All"), installed => $loc->N("Installed"), non_installed => $loc->N("Not installed"), ); my %rfilters = reverse %filters; # handle migrating config file from rpmdragora <= 4.9 if (exists $filters{$default_list_mode}) { $filter->[0] = $default_list_mode; $default_list_mode = 'all'; } $options->{tree_mode} = $default_list_mode; my %modes = ( flat => $loc->N("All packages, alphabetical"), by_group => $loc->N("All packages, by group"), by_leaves => $loc->N("Leaves only, sorted by install date"), by_presence => $loc->N("All packages, by update availability"), by_selection => $loc->N("All packages, by selection state"), by_size => $loc->N("All packages, by size"), by_source => $loc->N("All packages, by medium repository"), ); my %views = (all => $loc->N("All"), if_($is_backports, backports => #-PO: Backports media are newer but less-tested versions of some packages in main #-PO: See http://wiki.mandriva.com/en/Policies/SoftwareMedia#.2Fmain.2Fbackports $loc->N("Backports")), meta_pkgs => $loc->N("Meta packages"), gui_pkgs => $loc->N("Packages with GUI"), all_updates => $loc->N("All updates"), security => $loc->N("Security updates"), bugfix => $loc->N("Bugfixes updates"), normal => $loc->N("General updates") ); my %rviews = reverse %views; $options->{rviews} = \%rviews; my %default_mode = (install => 'all', # we want the new GUI by default instead of "non_installed" remove => 'installed', update => 'security', ); my %wanted_categories = ( all_updates => [ qw(security bugfix normal) ], security => [ 'security' ], bugfix => [ 'bugfix' ], normal => [ 'normal' ], ); my $view_box = $factory->createComboBox($hbox_top,""); $view_box->addItem($views{all}); $view_box->addItem($views{meta_pkgs}); $view_box->addItem($views{gui_pkgs}); $view_box->addItem($views{all_updates}); $view_box->addItem($views{security}); $view_box->addItem($views{normal}); $view_box->addItem($views{backports}) if($is_backports); $view_box->setNotify(1); $view_box->selectItem($view_box->findItem($views{$default_list_mode})) if(defined($views{$default_list_mode})); $options->{tree_submode} ||= $default_list_mode; $options->{tree_subflat} ||= $options->{state}{flat}; =for comment * OLD * my $filter_box = gtknew( 'ComboBox', list => [ qw(all installed non_installed) ], text => $filters{$filter->[0]}, format => sub { $filters{$_[0]} }, tip => $loc->N("Filter"), changed => sub { state $oldval; my $val = $_[0]->get_text; return if $val eq $oldval; # workarounding gtk+ sending us sometimes twice events $oldval = $val; $val = $rfilters{$val}; if ($filter->[0] ne $val) { $filter->[0] = $val; reset_search(); slow_func($::main_window->window, sub { switch_pkg_list_mode($default_list_mode) }); $options->{rebuild_tree}->(); } } ); my $view_callback = sub { my ($val) = @_; return if $val eq $old_value; # workarounding gtk+ sending us sometimes twice events $old_value = $val; return if $mode->[0] eq $val; $mode->[0] = $val; $tree_flat->[0] = $options->{state}{flat} = member($mode->[0], qw(flat by_leaves by_selection by_size)); if ($options->{tree_mode} ne $val) { reset_search(); $options->{rebuild_tree}->(); } }; =cut my $filter_box = $factory->createComboBox($hbox_top,""); $filter_box->addItem($filters{all}); $filter_box->addItem($filters{installed}); $filter_box->addItem($filters{non_installed}); $filter_box->selectItem($filter_box->findItem($filters{$filter->[0]})) if(defined($filters{$filter->[0]})); $filter_box->setNotify(1); my @search_types = qw(normal descriptions summaries files); my $current_search_type = $search_types[0]; #OLD my $search_menu = Gtk2::Menu->new; my $search_menu = $factory->createComboBox($hbox_top,""); my $i = 0; my $previous; foreach ($loc->N("in names"), $loc->N("in descriptions"), $loc->N("in summaries"), $loc->N("in file names")) { my ($name, $val) = ($_, $i); #OLD $search_menu->append(gtksignal_connect(gtkshow( # $previous = Gtk2::RadioMenuItem->new_with_label($previous, $name)), # activate => sub { $current_search_type = $search_types[$val] })); $search_menu->addItem($name); $i++; } $find_entry = $factory->createInputField($hbox_top, ""); my $find_button = $factory->createIconButton($hbox_top, "/usr/share/mcc/themes/default/logdrake-mdk.png", $loc->N("Search")); $find_button->setWeight(0,6); my $reset_search_button = $factory->createIconButton($hbox_top, "/usr/share/icons/gnome/22x22/actions/gtk-clear.png", $loc->N("Reset")); $reset_search_button->setWeight(0,7); $find_entry->setWeight(0,10); #OLD my $info = Gtk2::Mdv::TextView->new; #my $info = $factory->createMultiLineEdit($hbox_bottom,""); my $info = $factory->createRichText($hbox_bottom,""); #$info->setDisabled(); $info->setWeight(0,40); $info->setWeight(1,40); #OLD $info->set_left_margin(2); #OLD $info->set_right_margin(15); #- workaround when right elevator of scrolled window appears my $find_callback = sub { _do_search($find_entry, $tree, $options, $current_search_type, $urpm, $pkgs); }; my $select_all_button = $factory->createIconButton($hbox_footbar,"",$loc->N("Select all")); $select_all_button->setWeight(0,6); my $apply_button = $factory->createIconButton($hbox_footbar,"",$loc->N("Apply")); $apply_button->setWeight(0,6); my $QuitButton = $factory->createIconButton($hbox_footbar,"",$loc->N("Exit")); $QuitButton->setWeight(0,6); #my $hpaned = gtknew('HPaned', position => $typical_width*0.9, # child1 => gtknew('ScrolledWindow', child => $tree), # resize1 => 0, shrink1 => 0, # resize2 => 1, shrink2 => 0, # child2 => gtknew('VPaned', # child1 => gtknew('ScrolledWindow', child => $detail_list), resize1 => 1, shrink1 => 0, # child2 => gtknew('ScrolledWindow', child => $info), resize2 => 1, shrink2 => 0 # ) # ); my $reload_db_and_clear_all = sub { slow_func(sub { $force_rebuild = 1; AdminPanel::Rpmdragora::gui::pkgs_provider($options->{tree_mode}, skip_updating_mu => 1); AdminPanel::Rpmdragora::gui::reset_search(); $size_selected = 0; $options->{rebuild_tree}->(); $find_callback->(); }); }; #OLD my $status = gtknew('Label'); my $status = $factory->createLabel($vbox, ""); my $checkbox_show_autoselect; my %check_boxes; my $auto_select_string = $loc->N("/_Options") . $loc->N("/_Select dependencies without asking"); my $clean_cache_string = $loc->N("/_Options") . "/" . $loc->N("Clear download cache after successful install"); my $updates_string = $loc->N("/_Options") . $loc->N("/_Compute updates on startup"); my $NVR_string = $loc->N("/_Options") . "/" . $loc->N("Search in _full package names"); my $regexp_search_string = $loc->N("/_Options") . "/" . $loc->N("Use _regular expressions in searches"); # build File menu my %fileMenu = ( widget => $factory->createMenuButton($headbar,$loc->N("File")), update => new yui::YMenuItem($loc->N("Update media")), reset_sel => new yui::YMenuItem($loc->N("Reset the selection")), reload => new yui::YMenuItem($loc->N("Reload the packages list")), quit => new yui::YMenuItem($loc->N("&Quit")), ); my @ordered_menu_lines = qw(update reset_sel reload quit); foreach (@ordered_menu_lines) { $fileMenu{ widget }->addItem($fileMenu{ $_ }); } $fileMenu{ widget }->rebuildMenuTree(); # build View menu my $view_menu = $factory->createMenuButton($headbar,$loc->N("View")); # build Option menu my $option_menu = $factory->createMenuButton($headbar,$loc->N("Options")); my $a_s_string = $auto_select_string; my $c_c_string = $clean_cache_string; # stripping gtk-related stuff $a_s_string =~s/\/.+\/_//g; $c_c_string =~s/\/.+\/_//g; my $optMnuItemAutoSelect = new yui::YMenuItem($a_s_string); my $optMnuItemCleanCache = new yui::YMenuItem($c_c_string); $option_menu->addItem($optMnuItemAutoSelect); $option_menu->addItem($optMnuItemCleanCache); $option_menu->rebuildMenuTree(); # build help menu my %helpMenu = ( widget => $factory->createMenuButton($headRight, $loc->N("&Help")), help => new yui::YMenuItem($loc->N("Manual")), report_bug => new yui::YMenuItem($loc->N("Report Bug")), about => new yui::YMenuItem($loc->N("&About")), ); @ordered_menu_lines = qw(help report_bug about); foreach (@ordered_menu_lines) { $helpMenu{ widget }->addItem($helpMenu{ $_ }); } $helpMenu{ widget }->rebuildMenuTree(); $statusbar = $factory->createBusyIndicator($hbox_footbar, "" ); =for comment my ($menu, $factory) = create_factory_menu( $w->{real_window}, [ $loc->N("/_File"), undef, undef, undef, '' ], if_( ! $>, [ $loc->N("/_File") . $loc->N("/_Update media"), undef, sub { update_sources_interactive($urpm, transient => $w->{real_window}) and $reload_db_and_clear_all->(); }, undef, '' ] ), [ $loc->N("/_File") . $loc->N("/_Reset the selection"), undef, sub { if ($MODE ne 'remove') { my $db = eval { open_rpm_db() }; if (!ref($db)) { statusbar_msg($loc->N("Reset aborted (RPM DB is locked by another process)"), 1); return; } $urpm->disable_selected( $db, $urpm->{state}, map { if_($pkgs->{$_}{selected}, $pkgs->{$_}{pkg}) } keys %$pkgs, ); } undef $pkgs->{$_}{selected} foreach keys %$pkgs; reset_search(); $size_selected = 0; $force_displaying_group = 1; my $tree_selection = $tree->get_selection; $tree_selection->select_path(Gtk2::TreePath->new_from_string('0')) if !$tree_selection->get_selected; $tree_selection->signal_emit('changed'); }, undef, '' ], [ $loc->N("/_File") . $loc->N("/Reload the _packages list"), undef, $reload_db_and_clear_all, undef, '' ], [ $loc->N("/_File") . $loc->N("/_Quit"), $loc->N("Q"), \&quit, undef, '', ], #[ $loc->N("/_View"), undef, undef, undef, '' ], if_(!$>, [ $loc->N("/_Options"), undef, undef, undef, '' ], [ $auto_select_string, undef, sub { my $box = $check_boxes{$auto_select_string}; $auto_select->[0] = $box->get_active; $::rpmdragora_options{auto} = $box->get_active; $urpm->{options}{auto} = $box->get_active; }, undef, '' ], [ $clean_cache_string, undef, sub { $clean_cache->[0] = $check_boxes{$clean_cache_string}->get_active; $::noclean = !$clean_cache->[0]; }, undef, '' ], [ $loc->N("/_Options") . $loc->N("/_Media Manager"), undef, sub { require AdminPanel::Rpmdragora::edit_urpm_sources; AdminPanel::Rpmdragora::edit_urpm_sources::run() && $reload_db_and_clear_all->(); }, undef, '' ], [ $loc->N("/_Options") . $loc->N("/_Show automatically selected packages"), undef, sub { $dont_show_selections->[0] = !$checkbox_show_autoselect->get_active; }, undef, '' ], [ $updates_string, undef, sub { $compute_updates->[0] = $check_boxes{$updates_string}->get_active; }, undef, '' ], [ $NVR_string, undef, sub { $NVR_searches->[0] = $check_boxes{$NVR_string}->get_active; }, undef, '' ], [ $regexp_search_string, undef, sub { $use_regexp->[0] = $check_boxes{$regexp_search_string}->get_active; }, undef, '' ], ), [ $loc->N("/_View"), undef, undef, undef, '' ], (map { state ($idx, $previous); my $type = $idx ? join('/', $loc->N("/_View"), $previous) : ''; $type =~ s/_//g; # gtk+ retrieve widgets by their path w/o any shortcut marks $previous = $modes{$_}; $idx++; my $val = $_; [ $loc->N("/_View") . '/' . $modes{$_}, undef, sub { $view_callback->($val) }, 0, $type ]; } qw(flat by_group by_leaves by_presence by_selection by_size by_source)), [ $loc->N("/_Help"), undef, undef, undef, '' ], [ $loc->N("/_Help") . $loc->N("/_Report Bug"), undef, sub { run_drakbug('rpmdragora') }, undef, '' ], [ $loc->N("/_Help") . $loc->N("/_Help"), undef, sub { AdminPanel::rpmdragora::open_help('') }, undef, '' ], [ $loc->N("/_Help") . $loc->N("/_About..."), undef, sub { my $license = formatAlaTeX(translate($::license)); $license =~ s/\n/\n\n/sg; # nicer formatting my $w = gtknew('AboutDialog', name => $loc->N("Rpmdragora"), version => $AdminPanel::Rpmdragora::init::version, copyright => $loc->N("Copyright (C) %s by Mandriva", '2002-2009')."\n".$loc->N("Copyright (C) %s by Mageia.Org", '2010-2013'), license => $license, wrap_license => 1, comments => $loc->N("Rpmdragora is the Mageia package management tool."), website => 'http://www.mageia.org', website_label => $loc->N("Mageia"), authors => "Thierry Vignaud \nAngelo Naselli \nMatteo Pasotti ", artists => 'Hélène Durosini ', translator_credits => #-PO: put here name(s) and email(s) of translator(s) (eg: "John Smith ") $loc->N("_: Translator(s) name(s) & email(s)\n"), transient_for => $::main_window, modal => 1, position_policy => 'center-on-parent', ); $w->show_all; $w->run; }, undef, '' ] ); # to retrieve a path, one must prevent "accelerators completion": my $get_path = sub { return join('', map { my $i = $_; $i =~ s/_//g; $i } @_) }; if (my $widget = $factory->get_item('
' . $get_path->($loc->N("/_View") . '/' . $modes{$mode->[0]}))) { $widget->set_active(1); } else { warn "Impossible to set $mode->[0] view as default\n"; } %check_boxes = map { $_ => $factory->get_widget("
" . $get_path->($_)); } ($auto_select_string, $clean_cache_string, $NVR_string, $updates_string, $regexp_search_string); if (!$>) { $check_boxes{$regexp_search_string}->set_active($use_regexp->[0]); $check_boxes{$NVR_string}->set_active($NVR_searches->[0]); $check_boxes{$auto_select_string}->set_active($auto_select->[0]); $check_boxes{$updates_string}->set_active($compute_updates->[0]); $check_boxes{$clean_cache_string}->set_active($clean_cache->[0]); } $checkbox_show_autoselect = $factory->get_widget("
" . strip_first_underscore($loc->N("/_Options"), $loc->N("/_Show automatically selected packages"))) and $checkbox_show_autoselect->set_active(!$dont_show_selections->[0]); my $accel = Gtk2::AccelGroup->new; $accel->connect(Gtk2::Gdk->keyval_from_name('F'), [ 'control-mask' ], [ 'visible' ], sub { $find_entry->grab_focus }); $w->{real_window}->add_accel_group($accel); gtkadd( $w->{window}, gtkpack_( gtknew('VBox', spacing => 3), 0, $menu, if_(second(gtkroot()->get_size) >= 600, 0, getbanner()), 1, gtkadd( gtknew('Frame', border_width => 3, shadow_type => 'none'), gtkpack_( gtknew('VBox', spacing => 3), 0, gtkpack_( gtknew('HBox', spacing => 10), 0, $view_box, 0, $filter_box, 0, gtknew('Label', text => $loc->N("Find:")), 1, $find_entry = gtknew('Entry', width => 260, primary_icon => 'gtk-find', secondary_icon => 'gtk-clear', tip => $loc->N("Please type in the string you want to search then press the key"), 'icon-release' => $find_callback, 'icon-press' => sub { my (undef, $pos, $event) = @_; # emulate Sexy::IconEntry's clear_button: if ($pos eq 'secondary') { $find_entry->set_text(''); reset_search(); } return if $pos ne 'primary'; $search_menu->popup(undef, undef, undef, undef, $event->button, $event->time); }, key_press_event => sub { member($_[1]->keyval, $Gtk2::Gdk::Keysyms{Return}, $Gtk2::Gdk::Keysyms{KP_Enter}) and $find_callback->(); }, ), ), 1, $hpaned, 0, $status, 0, gtkpack_( gtknew('HBox', spacing => 20), 0, gtksignal_connect( Gtk2::Button->new(but_($loc->N("Select all"))), clicked => sub { toggle_all($options, 1); }, ), 1, gtknew('Label'), 0, my $action_button = gtksignal_connect( Gtk2::Button->new(but_($loc->N("Apply"))), clicked => sub { do_action($options, $callback_action, $info) }, ), 0, gtksignal_connect( Gtk2::Button->new(but_($loc->N("Quit"))), clicked => \&quit, ), ), ), ), 0, $statusbar = Gtk2::Statusbar->new, ), ); $action_button->set_sensitive(0) if $>; $find_entry->grab_focus; gtktext_insert($info, [ [ $info->render_icon('gtk-dialog-info', 'GTK_ICON_SIZE_DIALOG', undef) ], @{ ugtk2::markup_to_TextView_format( formatAlaTeX(join("\n\n\n", format_header($loc->N("Quick Introduction")), $loc->N("You can browse the packages through the categories tree on the left."), $loc->N("You can view information about a package by clicking on it on the right list."), $loc->N("To install, update or remove a package, just click on its \"checkbox\".")))) } ]); $w->{rwindow}->set_default_size($typical_width*2.7, 500) if !$::isEmbedded; =cut $find_entry->setText($rpmdragora_options{search}[0]) if $rpmdragora_options{search}; #if ($rpmdragora_width->[0] && $rpmdragora_height->[0]) { ## so that we can shrink back: #$w->{real_window}->set_default_size($rpmdragora_width->[0], $rpmdragora_height->[0]); #} #$w->{rwindow}->show_all; #$w->{rwindow}->set_sensitive(0); # ensure treeview get realized so that ->get_selection returns something #$detail_list->realize; #gtkflush(); #OLD slow_func($::main_window->window, sub { pkgs_provider($default_list_mode) }); # default mode slow_func(sub { pkgs_provider($default_list_mode) }); # default mode if (@initial_selection) { print "\n== Initial selection: @initial_selection\n"; $options->{initial_selection} = \@initial_selection; undef $pkgs->{$_}{selected} foreach @initial_selection; } #$w->{rwindow}->set_sensitive(1); $options->{widgets} = { w => $my_win, tree => $tree, #detail_list_model => $detail_list_model, detail_list => $detail_list, info => $info, status => $status, }; $options->{init_callback} = $find_callback if $rpmdragora_options{search}; ask_browse_tree_given_widgets_for_rpmdragora($options); my $info_options = {}; # select group and show items evenctually tree_callback($tree->currentItem(),\%$options); ######## main loop #################### while(1) { my $event = $my_win->waitForEvent(); my $eventType = $event->eventType(); #event type checking if ($eventType == $yui::YEvent::CancelEvent) { quit(); last; } elsif ($eventType == $yui::YEvent::MenuEvent) { ### MENU ### my $item = $event->item(); if (!$item) { #URL emitted or at least a ref into RichText widget my $url = yui::toYMenuEvent($event)->id (); if (AdminPanel::Rpmdragora::gui::info_details($url, $info_options) ) { $item = $detail_list->selectedItem(); detaillist_callback($item, $info, \%$options, $info_options); } else { # default it's really a URL AdminPanel::Rpmdragora::gui::run_browser($url); } } else { my $menuLabel = $item->label(); if ($menuLabel eq $fileMenu{ quit }->label()) { #menu File->Quit quit(); last; } elsif ($menuLabel eq $fileMenu{ update }->label()) { update_sources_interactive($urpm, transient => $my_win) and $reload_db_and_clear_all->(); } elsif ($menuLabel eq $fileMenu{ reset_sel }->label()) { if ($MODE ne 'remove') { my $db = eval { open_rpm_db() }; if (!ref($db)) { statusbar_msg($loc->N("Reset aborted (RPM DB is locked by another process)"), 1); return; } $urpm->disable_selected( $db, $urpm->{state}, map { if_($pkgs->{$_}{selected}, $pkgs->{$_}{pkg}) } keys %$pkgs,); } undef $pkgs->{$_}{selected} foreach keys %$pkgs; reset_search(); $size_selected = 0; $force_displaying_group = 1; my $tree_selection = $tree->currentItem(); } elsif ($menuLabel eq $fileMenu{ reload }->label()) { $reload_db_and_clear_all->(); } elsif ($menuLabel eq $helpMenu{ about }->label()) { my $translators = $loc->N("_: Translator(s) name(s) & email(s)\n"); $translators =~ s/\/\>\;/g; my $sh_gui = AdminPanel::Shared::GUI->new(); $sh_gui->AboutDialog({ name => "Rpmdragora", version => "TODO", credits => $loc->N("Copyright (C) %s Mageia community", '2013-2014'), license => $loc->N("GPLv2"), description => $loc->N("Rpmdragora is the Mageia package management tool."), authors => $loc->N("

Developers

  • %s
  • %s

Translators

  • %s
", "Angelo Naselli <anaselli\@linux.it>", "Matteo Pasotti <matteo.pasotti\@gmail.com>", $translators ), } ); } } } elsif ($eventType == $yui::YEvent::WidgetEvent) { # widget selected my $widget = $event->widget(); if($widget == $reset_search_button) { $find_entry->setValue(''); reset_search(); } elsif ($widget == $find_button) { yui::YUI::app()->busyCursor(); _do_search($find_entry, $tree, $options, $current_search_type, $urpm, $pkgs); yui::YUI::app()->normalCursor(); } elsif ($widget == $select_all_button) { toggle_all($options, 1); #select_all_current_packages(\$detail_list); } elsif ($widget == $apply_button) { do_action($options, $callback_action, $info); } elsif ($widget == $view_box) { viewbox_callback($view_box->selectedItem()->label(), \%$options, \%wanted_categories); } elsif ($widget == $filter_box) { filterbox_callback($filter_box->selectedItem()->label(), \%$options, \%rfilters); } elsif ($widget == $tree) { tree_callback($tree->currentItem(),\%$options); } elsif ($widget == $detail_list){ $info_options = {}; detaillist_callback($detail_list->selectedItem(), $info, \%$options); detaillist_changeditem_callback($detail_list, \%$options); } elsif ($widget == $QuitButton) { quit(); last; } } } } # -=-=-=---=-=-=---=-=-=-- main -=-=-=---=-=-=---=-=-=- if (my $pid = is_running('rpmdragora')) { interactive_msg($loc->N("Warning"), $loc->N("rpmdragora is already running (pid: %s)", $pid), yesno => [ $loc->N("Quit") ]); exit(0); } yui::YUI::app()->setApplicationTitle($loc->N("Software Management")); yui::YUI::app()->setApplicationIcon($wm_icon); my $MGAPlugin = "mga"; $factory = yui::YUI::widgetFactory; $mgaFactory = yui::YExternalWidgets::externalWidgetFactory($MGAPlugin); $mgaFactory = yui::YMGAWidgetFactory::getYMGAWidgetFactory($mgaFactory); $optFactory = yui::YUI::optionalWidgetFactory; ### MAIN DIALOG ### $my_win = $factory->createMainDialog; readconf(); if(!warn_about_user_mode()) { quit(); exit(0); } do_merge_if_needed(); init(); run_treeview_dialog(\&perform_installation); writeconf();