1 |
#!/usr/bin/perl |
2 |
#***************************************************************************** |
3 |
# |
4 |
# Copyright (c) 2002 Guillaume Cottenceau |
5 |
# Copyright (c) 2002-2007 Thierry Vignaud <tvignaud@mandriva.com> |
6 |
# Copyright (c) 2003, 2004, 2005 MandrakeSoft SA |
7 |
# Copyright (c) 2005-2007 Mandriva SA |
8 |
# |
9 |
# This program is free software; you can redistribute it and/or modify |
10 |
# it under the terms of the GNU General Public License version 2, as |
11 |
# published by the Free Software Foundation. |
12 |
# |
13 |
# This program is distributed in the hope that it will be useful, |
14 |
# but WITHOUT ANY WARRANTY; without even the implied warranty of |
15 |
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
16 |
# GNU General Public License for more details. |
17 |
# |
18 |
# You should have received a copy of the GNU General Public License |
19 |
# along with this program; if not, write to the Free Software |
20 |
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. |
21 |
# |
22 |
#***************************************************************************** |
23 |
# |
24 |
# $Id: MageiaUpdate 261845 2009-10-13 12:33:58Z tv $ |
25 |
|
26 |
use strict; |
27 |
use MDK::Common::Func 'any'; |
28 |
use lib qw(/usr/lib/libDrakX); |
29 |
use common; |
30 |
|
31 |
use Rpmdrake::init; |
32 |
use standalone; #- standalone must be loaded very first, for 'explanations', but after rpmdrake::init |
33 |
use rpmdrake; |
34 |
use Rpmdrake::gui; |
35 |
use Rpmdrake::rpmnew; |
36 |
use Rpmdrake::formatting; |
37 |
use Rpmdrake::pkg; |
38 |
use Rpmdrake::widgets; |
39 |
|
40 |
use mygtk2 qw(gtknew); #- do not import anything else, especially gtkadd() which conflicts with ugtk2 one |
41 |
use ugtk2 qw(:all); |
42 |
use Gtk2::SimpleList; |
43 |
|
44 |
# make Rpmdrake::gui aware MageiaUpdate do not use the same columns ids as rpmdrake: |
45 |
%pkg_columns = ( |
46 |
image => 0, |
47 |
selected => 1, |
48 |
text => 2, |
49 |
short_name => 3, |
50 |
version => 4, |
51 |
release => 5, |
52 |
'arch' => 6, |
53 |
importance => 7, |
54 |
); |
55 |
|
56 |
$ugtk2::wm_icon = get_icon('MageiaUpdate', "title-$MODE"); |
57 |
|
58 |
our $w; |
59 |
our $statusbar; |
60 |
|
61 |
warn_about_user_mode(); |
62 |
|
63 |
my (%data, $initialized); |
64 |
|
65 |
my %update_icons = ( |
66 |
security => 'security-update', |
67 |
bugfix => 'bugfix-update', |
68 |
normal => 'general-update', |
69 |
); |
70 |
|
71 |
my %icons_cache; |
72 |
|
73 |
sub refresh_packages_list { |
74 |
my ($list, $info, $button) = @_; |
75 |
# select packages to update: |
76 |
my @requested = sort @filtered_pkgs; |
77 |
|
78 |
# don't select packages in skip list: |
79 |
if (!$initialized) { |
80 |
$pkgs->{$_}{selected} = 0 foreach @requested; |
81 |
my @selectable = grep { !$pkgs->{$_}{pkg}->flag_skip } @requested; |
82 |
toggle($list, @selectable) if @selectable; |
83 |
$initialized = 1; |
84 |
} |
85 |
|
86 |
my $i; |
87 |
@{$list->{data}} = map { |
88 |
$data{$_} = $i++; |
89 |
my $summary = get_summary($_); |
90 |
my ($name, $version, $release, $arch) = split_fullname($_); |
91 |
my $pkg = $pkgs->{$_}; |
92 |
my $raw_medium = pkg2medium($pkg->{pkg}, $urpm); |
93 |
my $medium = !$raw_medium->{fake} ? $raw_medium->{name} : undef; |
94 |
my $icon; |
95 |
my $importance = $medium && $descriptions->{$medium}{$name}{importance}; |
96 |
if ($importance) { |
97 |
$icon = $icons_cache{$importance} ||= gtknew('Pixbuf', file => $update_icons{$importance}); |
98 |
} |
99 |
[ $icon, $pkgs->{$_}{selected}, $_, format_name_n_summary($name, $summary), $version, $release, $arch, $importance ]; |
100 |
} grep { $pkgs->{$_}{pkg} } @requested; |
101 |
gtktext_insert($info, |
102 |
formatAlaTeX(N("The list of updates is empty. This means that either there is |
103 |
no available update for the packages installed on your computer, |
104 |
or you already installed all of them."))) if !@{$list->{data}}; |
105 |
$button->set_sensitive(scalar(@{$list->{data}})); |
106 |
} |
107 |
|
108 |
sub toggle { |
109 |
my ($list, @names) = @_; |
110 |
my $name = $names[0]; |
111 |
my $val = $pkgs->{$name}{selected}; |
112 |
my $old_status = $val ? 'to_install' : 'to_update'; |
113 |
my $done; |
114 |
$pkgs->{$name}{pkg}->set_flag_skip(0); |
115 |
toggle_nodes($w->{real_window}->window, $list->get_model, sub { |
116 |
my ($leaf, $_state, $_model) = @_; |
117 |
$done = 1; |
118 |
$list->{data}[$data{$leaf}][$pkg_columns{selected}] = $pkgs->{$name}{selected}; |
119 |
}, |
120 |
$old_status, @names); |
121 |
# handle canceling: |
122 |
$list->{data}[$data{$name}][$pkg_columns{selected}] = !$list->{data}[$data{$name}][$pkg_columns{selected}] if !$done; |
123 |
} |
124 |
|
125 |
$w = ugtk2->new(N("Software Management")); |
126 |
$w->{rwindow}->show_all if $::isEmbedded; |
127 |
$::main_window = $w->{real_window}; |
128 |
|
129 |
sub quit() { |
130 |
($mandrivaupdate_width->[0], $mandrivaupdate_height->[0]) = $::w->{real_window}->get_size; |
131 |
real_quit(); |
132 |
} |
133 |
|
134 |
sub run_treeview_dialog { |
135 |
my ($callback_action) = @_; |
136 |
|
137 |
my ($list, $info, $update_button); |
138 |
|
139 |
my $rootwin_height = second(gtkroot()->get_size); |
140 |
my $is_small_screen = $rootwin_height <= 480; |
141 |
|
142 |
compute_main_window_size($w); |
143 |
|
144 |
gtkadd( |
145 |
$w->{window}, |
146 |
gtkpack_( |
147 |
gtknew('VBox', spacing => 3), |
148 |
if_(!$is_small_screen, 0, getbanner()), |
149 |
0, gtknew('Title2', label => N("Here is the list of software package updates"), width => 600), |
150 |
1, create_vpaned( |
151 |
gtknew('ScrolledWindow', width => $typical_width*0.9, height => $is_small_screen ? 150 : 200, |
152 |
child => $list = Gtk2::SimpleList->new( |
153 |
" " => 'pixbuf', |
154 |
" " . " " . " " => 'bool', #N("Selected") |
155 |
'' => 'hidden', |
156 |
" " . N("Name") . " " => 'markup', #N("Name") |
157 |
" " . N("Version") . " " => 'text', |
158 |
" " . N("Release") . " " => 'text', |
159 |
" " . N("Arch") . " " => 'text', |
160 |
'' => 'hidden', |
161 |
), |
162 |
), |
163 |
|
164 |
gtknew('ScrolledWindow', width => $typical_width*0.9, |
165 |
child => $info = Gtk2::Mdv::TextView->new, height => $is_small_screen ? 150 : 190, |
166 |
), |
167 |
resize1 => 1, |
168 |
), |
169 |
0, gtkset_size_request(Gtk2::HSeparator->new, -1, 5), |
170 |
0, gtkpack_( |
171 |
gtknew('HBox', spacing => 20), |
172 |
0, gtksignal_connect( |
173 |
Gtk2::Button->new(but_(N("Help"))), |
174 |
clicked => sub { rpmdrake::open_help($MODE) }, |
175 |
), |
176 |
0, gtksignal_connect( |
177 |
Gtk2::Button->new(but_(N("Select all"))), |
178 |
clicked => sub { |
179 |
toggle_all({ |
180 |
widgets => { |
181 |
detail_list => $list, |
182 |
detail_list_model => $list->get_model |
183 |
}, |
184 |
}, 1); |
185 |
refresh_packages_list($list, $info, $update_button); |
186 |
}, |
187 |
), |
188 |
1, gtknew('Label'), |
189 |
0, my $action_button = gtksignal_connect( |
190 |
$update_button = Gtk2::Button->new(but_(N("Update"))), |
191 |
clicked => sub { |
192 |
my $res = do_action({ tree_mode => 'all_updates' }, $callback_action); |
193 |
$initialized = 0 if !$res; |
194 |
refresh_packages_list($list, $info, $update_button); |
195 |
}, |
196 |
), |
197 |
0, gtksignal_connect( |
198 |
Gtk2::Button->new(but_(N("Quit"))), |
199 |
clicked => \&quit, |
200 |
), |
201 |
), |
202 |
#0, $statusbar = Gtk2::Statusbar->new, |
203 |
), |
204 |
); |
205 |
$statusbar = Gtk2::Statusbar->new; |
206 |
|
207 |
$list->get_model->set_sort_func($pkg_columns{image} + 1, sub { |
208 |
my ($store, $treeiter1, $treeiter2) = @_; |
209 |
$store->get_value($treeiter1, $pkg_columns{importance}) cmp |
210 |
$store->get_value($treeiter2, $pkg_columns{importance}); |
211 |
}); |
212 |
|
213 |
|
214 |
$list->set_rules_hint(1); |
215 |
my $pix_col = $list->get_column($pkg_columns{image}); |
216 |
$pix_col->set_fixed_width(32); |
217 |
my $bool_col = $list->get_column($pkg_columns{selected}); |
218 |
$bool_col->set_fixed_width(24); |
219 |
$bool_col->set_sizing('fixed'); |
220 |
$bool_col->set_sort_column_id($pkg_columns{selected}); |
221 |
|
222 |
# -1 because actual widget count differs from TreeModel one due to the hidden column: |
223 |
foreach (@pkg_columns{qw(short_name version release arch)}) { |
224 |
my $col = $list->get_column($_-1); |
225 |
($col->get_cell_renderers)[0]->set_property('xpad', '6'); |
226 |
$col->set_sizing('autosize'); |
227 |
$col->set_sort_column_id($_); |
228 |
} |
229 |
|
230 |
my $pretty_column = $list->get_column($pkg_columns{short_name}-1); |
231 |
$pretty_column->set_resizable(1); |
232 |
($pretty_column->get_cell_renderers)[0]->set_property('ellipsize', 'end'); |
233 |
$pretty_column->set_property('expand', '1'); |
234 |
|
235 |
$list->get_selection->signal_connect(changed => sub { |
236 |
my ($model, $iter) = $_[0]->get_selected; |
237 |
$model && $iter or return; |
238 |
gtktext_insert($info, get_info($model->get($iter, $pkg_columns{text}), $w->{real_window}->window)); |
239 |
$info->scroll_to_iter($info->get_buffer->get_start_iter, 0, 0, 0, 0); |
240 |
}); |
241 |
|
242 |
$w->{rwindow}->set_default_size(-1, 500) if !$::isEmbedded; |
243 |
|
244 |
if ($mandrivaupdate_width->[0] && $mandrivaupdate_height->[0]) { |
245 |
# so that we can shrink back: |
246 |
$w->{real_window}->set_default_size($mandrivaupdate_width->[0], $mandrivaupdate_height->[0]); |
247 |
} |
248 |
$w->{rwindow}->show_all; |
249 |
$w->{rwindow}->set_sensitive(0); |
250 |
|
251 |
# ensure treeview get realized so that ->get_selection returns something |
252 |
$list->realize; |
253 |
gtkflush(); |
254 |
|
255 |
$filter->[0] = 'all'; # default filter: availlable updates |
256 |
$Rpmdrake::pkg::probe_only_for_updates = 1; # faster startup |
257 |
pkgs_provider({}, 'all_updates', pure_updates => 1); # default mode |
258 |
|
259 |
refresh_packages_list($list, $info, $update_button); |
260 |
|
261 |
my $cell = ($bool_col->get_cell_renderers)[0]; |
262 |
$cell->signal_connect(toggled => sub { |
263 |
my ($_cell, $text_path) = @_; |
264 |
my $name = @{$list->{data}[$text_path]}[$pkg_columns{text}]; |
265 |
gtkset_mousecursor_wait($w->{real_window}->window); |
266 |
my $_guard = before_leaving(sub { gtkset_mousecursor_normal($w->{real_window}->window) }); |
267 |
toggle($list, $name); |
268 |
}); |
269 |
$action_button->set_sensitive(0) if $>; |
270 |
|
271 |
$w->{rwindow}->set_sensitive(1); |
272 |
|
273 |
$w->main; |
274 |
} |
275 |
|
276 |
|
277 |
# -=-=-=---=-=-=---=-=-=-- main -=-=-=---=-=-=---=-=-=- |
278 |
|
279 |
do_merge_if_needed(); |
280 |
|
281 |
readconf(); |
282 |
|
283 |
init(); |
284 |
run_treeview_dialog(\&perform_installation); |
285 |
|
286 |
writeconf(); |
287 |
|
288 |
myexit(0); |