1 #!/usr/bin/python2.4
2 #
3 # CDDL HEADER START
4 #
5 # The contents of this file are subject to the terms of the
6 # Common Development and Distribution License (the "License").
7 # You may not use this file except in compliance with the License.
8 #
9 # You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 # or http://www.opensolaris.org/os/licensing.
11 # See the License for the specific language governing permissions
12 # and limitations under the License.
13 #
14 # When distributing Covered Code, include this CDDL HEADER in each
15 # file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16 # If applicable, add the following below this CDDL HEADER, with the
17 # fields enclosed by brackets "[]" replaced with your own identifying
18 # information: Portions Copyright [yyyy] [name of copyright owner]
19 #
20 # CDDL HEADER END
21 #
22 # Copyright 2008 Sun Microsystems, Inc. All rights reserved.
23 # Use is subject to license terms.
24 #
25
26 # Progress:
27 # Startup Progress has two phases:
28 # - Start phase:
29 # The start phase should be fairly constant at around a few seconds and so is given 5%
30 # of the total progress bar.
31 # - Package entry loading phase:
32 # The package entry loading phase is given the remaining 95% of the bar for progress.
33
34 INITIAL_PROGRESS_TIME_INTERVAL = 0.5 # Time to update progress during start phase
35 INITIAL_PROGRESS_TIME_PERCENTAGE = 0.005 # Amount to update progress during start phase
36 INITIAL_PROGRESS_TOTAL_PERCENTAGE = 0.05 # Total progress for start phase
37 PACKAGE_PROGRESS_TOTAL_INCREMENTS = 95.0 # Total increments for loading phase
38 PACKAGE_PROGRESS_PERCENT_INCREMENT = 0.01 # Amount to update progress during loading phase
39 PACKAGE_PROGRESS_PERCENT_TOTAL = 1.0 # Total progress for loading phase
40
41 import getopt
42 import os
43 import sys
44 import time
45 import locale
46 import socket
47 import gettext
48 from threading import Thread
49 try:
50 import gobject
51 gobject.threads_init()
52 import gtk
53 import gtk.glade
54 import pygtk
55 pygtk.require("2.0")
56 except ImportError:
57 sys.exit(1)
58 import pkg.client.image as image
59 import pkg.client.progress as progress
60 import pkg.misc as misc
61 import pkg.portable as portable
62 import pkg.gui.beadmin as beadm
63 import pkg.gui.imageinfo as imageinfo
64 import pkg.gui.installupdate as installupdate
65 import pkg.gui.remove as remove
66 import pkg.gui.enumerations as enumerations
67
68
69 class PackageManager:
70 def __init__(self):
71 self.image_o = None
72 socket.setdefaulttimeout(
73 int(os.environ.get("PKG_CLIENT_TIMEOUT", "30"))) # in seconds
74
75 # Override default MAX_TIMEOUT_COUNT if a value has been specified
76 # in the environment.
77 timeout_max = misc.MAX_TIMEOUT_COUNT
78 misc.MAX_TIMEOUT_COUNT = int(os.environ.get("PKG_TIMEOUT_MAX",
79 timeout_max))
80
81 try:
82 self.application_dir = os.environ["PACKAGE_MANAGER_ROOT"]
83 except KeyError:
84 self.application_dir = "/"
85 locale.setlocale(locale.LC_ALL, '')
86 for module in (gettext, gtk.glade):
87 module.bindtextdomain("packagemanager", self.application_dir + \
88 "/usr/share/locale")
89 module.textdomain("packagemanager")
90 self._ = gettext.gettext
91 main_window_title = self._('Package Manager - revision 0.1')
92 self.user_rights = portable.is_admin()
93 self.cancelled = False # For background processes
94 self.image_directory = None
95 self.description_thread_running = False # For background processes
96 self.pkginfo_thread = None # For background processes
97 gtk.rc_parse('~/.gtkrc-1.2-gnome2') # Load gtk theme
98 self.main_clipboard_text = None
99 self.ipkg_fmri = "SUNWipkg"
100 self.ipkggui_fmri = "SUNWipkg-gui"
101 self.progress_stop_timer_thread = False
102 self.progress_fraction_time_count = 0
103 self.progress_canceled = False
104 self.ips_uptodate = False
105 self.image_dir_arg = None
106 self.application_path = None
107
108 self.application_list = \
109 gtk.ListStore(
110 gobject.TYPE_BOOLEAN, # enumerations.MARK_COLUMN
111 gtk.gdk.Pixbuf, # enumerations.STATUS_ICON_COLUMN
112 gtk.gdk.Pixbuf, # enumerations.ICON_COLUMN
113 gobject.TYPE_STRING, # enumerations.NAME_COLUMN
114 gobject.TYPE_STRING, # enumerations.INSTALLED_VERSION_COLUMN
115 gobject.TYPE_PYOBJECT, # enumerations.INSTALLED_OBJECT_COLUMN
116 gobject.TYPE_STRING, # enumerations.LATEST_AVAILABLE_COLUMN
117 gobject.TYPE_INT, # enumerations.RATING_COLUMN
118 gobject.TYPE_STRING, # enumerations.DESCRIPTION_COLUMN
119 gobject.TYPE_PYOBJECT, # enumerations.PACKAGE_OBJECT_COLUMN
120 gobject.TYPE_PYOBJECT, # enumerations.IMAGE_OBJECT_COLUMN
121 gobject.TYPE_BOOLEAN, # enumerations.IS_VISIBLE_COLUMN
122 gobject.TYPE_PYOBJECT # enumerations.CATEGORY_LIST_OBJECT
123 )
124 self.category_list = \
125 gtk.ListStore(
126 gobject.TYPE_INT, # enumerations.CATEGORY_ID
127 gobject.TYPE_STRING, # enumerations.CATEGORY_NAME
128 gobject.TYPE_STRING, # enumerations.CATEGORY_DESCRIPTION
129 gtk.gdk.Pixbuf, # enumerations.CATEGORY_ICON
130 gobject.TYPE_BOOLEAN, # enumerations.CATEGORY_VISIBLE
131 gobject.TYPE_PYOBJECT, # enumerations.SECTION_LIST_OBJECT
132 )
133 self.section_list = \
134 gtk.ListStore(
135 gobject.TYPE_INT, # enumerations.SECTION_ID
136 gobject.TYPE_STRING, # enumerations.SECTION_NAME
137 )
138 self.filter_list = \
139 gtk.ListStore(
140 gobject.TYPE_INT, # enumerations.FILTER_ID
141 gobject.TYPE_STRING, # enumerations.FILTER_NAME
142 )
143 self.repositories_list = \
144 gtk.ListStore(
145 gobject.TYPE_INT, # enumerations.REPOSITORY_ID
146 gobject.TYPE_STRING, # enumerations.REPOSITORY_NAME
147 )
148
149 self.application_list_filter = self.application_list.filter_new()
150 self.pr = progress.NullProgressTracker()
151
152 # Create Widgets and show gui
153
154 self.gladefile = self.application_dir + \
155 "/usr/share/package-manager/packagemanager.glade"
156 w_tree_main = gtk.glade.XML(self.gladefile, "mainwindow")
157 w_tree_progress = gtk.glade.XML(self.gladefile, "progressdialog")
158
159 self.w_main_window = w_tree_main.get_widget("mainwindow")
160 self.w_application_treeview = \
161 w_tree_main.get_widget("applicationtreeview")
162 self.w_categories_treeview = w_tree_main.get_widget("categoriestreeview")
163 self.w_generalinfo_textview = \
164 w_tree_main.get_widget("generalinfotextview")
165 self.w_installedfiles_textview = \
166 w_tree_main.get_widget("installedfilestextview")
167 self.w_dependencies_textview = \
168 w_tree_main.get_widget("dependenciestextview")
169 self.w_packagename_label = w_tree_main.get_widget("packagenamelabel")
170 self.w_shortdescription_label = \
171 w_tree_main.get_widget("shortdescriptionlabel")
172 self.w_searchentry_dialog = w_tree_main.get_widget("searchentry")
173 self.w_installupdate_button = \
174 w_tree_main.get_widget("install_update_button")
175 self.w_remove_button = w_tree_main.get_widget("remove_button")
176 self.w_updateall_button = w_tree_main.get_widget("update_all_button")
177 self.w_reload_button = w_tree_main.get_widget("reloadbutton")
178 self.w_repository_combobox = w_tree_main.get_widget("repositorycombobox")
179 self.w_sections_combobox = w_tree_main.get_widget("sectionscombobox")
180 self.w_filter_combobox = w_tree_main.get_widget("filtercombobox")
181 self.w_packageicon_image = w_tree_main.get_widget("packageimage")
182 self.w_main_statusbar = w_tree_main.get_widget("statusbar")
183 self.w_installupdate_menuitem = \
184 w_tree_main.get_widget("package_install_update")
185 self.w_remove_menuitem = w_tree_main.get_widget("package_remove")
186 self.w_updateall_menuitem = w_tree_main.get_widget("package_update_all")
187 self.w_cut_menuitem = w_tree_main.get_widget("edit_cut")
188 self.w_copy_menuitem = w_tree_main.get_widget("edit_copy")
189 self.w_paste_menuitem = w_tree_main.get_widget("edit_paste")
190 self.w_clear_menuitem = w_tree_main.get_widget("edit_clear")
191 self.w_selectall_menuitem = w_tree_main.get_widget("edit_select_all")
192 self.w_selectupdates_menuitem = \
193 w_tree_main.get_widget("edit_select_updates")
194 self.w_deselect_menuitem = w_tree_main.get_widget("edit_deselect")
195 self.w_main_clipboard = gtk.clipboard_get(gtk.gdk.SELECTION_CLIPBOARD)
196
197 self.w_progress_dialog = w_tree_progress.get_widget("progressdialog")
198 self.w_progress_dialog.set_title(self._("Update All"))
199 self.w_progressinfo_label = w_tree_progress.get_widget("progressinfo")
200 self.w_progressinfo_label.set_text(self._( \
201 "Checking SUNWipkg and SUNWipkg-gui versions\n\nPlease wait ..."))
202 self.w_progressbar = w_tree_progress.get_widget("progressbar")
203 self.w_progressbar.set_pulse_step(0.1)
204 self.w_progress_cancel = w_tree_progress.get_widget("progresscancel")
205 self.progress_canceled = False
206
207 self.__update_reload_button()
208 self.w_main_clipboard.request_text(self.__clipboard_text_received)
209 self.w_main_window.set_title(main_window_title)
210
211 try:
212 dic_mainwindow = \
213 {
214 "on_mainwindow_delete_event": \
215 self.__on_mainwindow_delete_event,
216 "on_searchentry_changed":self.__on_searchentry_changed,
217 "on_searchentry_focus_in_event": \
218 self.__on_searchentry_focus_in,
219 "on_searchentry_focus_out_event": \
220 self.__on_searchentry_focus_out,
221 "on_searchentry_event":self.__on_searchentry_event,
222 "on_sectionscombobox_changed": \
223 self.__on_sectionscombobox_changed,
224 "on_filtercombobox_changed": \
225 self.__on_filtercombobox_changed,
226 "on_repositorycombobox_changed": \
227 self.__on_repositorycombobox_changed,
228 #menu signals
229 "on_file_quit_activate":self.__on_file_quit_activate,
230 "on_file_be_activate":self.__on_file_be_activate,
231 "on_package_install_update_activate": \
232 self.__on_install_update,
233 "on_package_remove_activate":self.__on_remove,
234 "on_help_about_activate":self.__on_help_about,
235 "on_edit_paste_activate":self.__on_edit_paste,
236 "on_edit_clear_activate":self.__on_clear_paste,
237 "on_edit_copy_activate":self.__on_copy,
238 "on_edit_cut_activate":self.__on_cut,
239 "on_edit_select_all_activate":self.__on_select_all,
240 "on_edit_select_updates_activate": \
241 self.__on_select_updates,
242 "on_edit_deselect_activate":self.__on_deselect,
243 # XXX disabled until new API
244 "on_package_update_all_activate":self.__on_update_all,
245 #toolbar signals
246 # XXX disabled until new API
247 "on_update_all_button_clicked":self.__on_update_all,
248 "on_reload_button_clicked":self.__on_reload,
249 "on_install_update_button_clicked": \
250 self.__on_install_update,
251 "on_remove_button_clicked":self.__on_remove
252 }
253 dic_progress = \
254 {
255 "on_cancel_progressdialog_clicked": \
256 self.__on_cancel_progressdialog_clicked,
257 }
258 w_tree_main.signal_autoconnect(dic_mainwindow)
259 w_tree_progress.signal_autoconnect(dic_progress)
260 except AttributeError, error:
261 print self._( \
262 'GUI will not respond to any event! %s.' + \
263 'Check declare_signals()') \
264 % error
265
266 self.package_selection = None
267 self.category_list_filter = None
268 self.in_setup = True
269 self.w_main_window.show_all()
270
271 def __init_tree_views(self):
272 '''This function connects treeviews with their models and also applies
273 filters'''
274 ##APPLICATION MAIN TREEVIEW
275 application_list_sort = \
276 gtk.TreeModelSort(self.application_list_filter)
277 self.w_application_treeview.set_model(application_list_sort)
278 model = self.w_application_treeview.get_model()
279 toggle_renderer = gtk.CellRendererToggle()
280 toggle_renderer.connect('toggled', self.__active_pane_toggle, model)
281 column = gtk.TreeViewColumn("", toggle_renderer, \
282 active = enumerations.MARK_COLUMN)
283 column.set_sort_column_id(enumerations.MARK_COLUMN)
284 column.set_sort_indicator(True)
285 column.set_cell_data_func(toggle_renderer, self.cell_data_function, None)
286 self.w_application_treeview.append_column(column)
287 column = gtk.TreeViewColumn()
288 column.set_title("")
289 #Commented, since there was funny jumping of the icons
290 #column.set_sizing(gtk.TREE_VIEW_COLUMN_AUTOSIZE)
291 render_pixbuf = gtk.CellRendererPixbuf()
292 column.pack_start(render_pixbuf, expand = False)
293 column.add_attribute(render_pixbuf, "pixbuf", \
294 enumerations.STATUS_ICON_COLUMN)
295 column.set_fixed_width(32)
296 column.set_cell_data_func(render_pixbuf, self.cell_data_function, None)
297 self.w_application_treeview.append_column(column)
298 column = gtk.TreeViewColumn()
299 column.set_title("")
300 #Commented, since there was funny jumping of the icons
301 #column.set_sizing(gtk.TREE_VIEW_COLUMN_AUTOSIZE)
302 render_pixbuf = gtk.CellRendererPixbuf()
303 column.pack_start(render_pixbuf, expand = False)
304 column.add_attribute(render_pixbuf, "pixbuf", enumerations.ICON_COLUMN)
305 column.set_fixed_width(32)
306 column.set_cell_data_func(render_pixbuf, self.cell_data_function, None)
307 self.w_application_treeview.append_column(column)
308 name_renderer = gtk.CellRendererText()
309 column = gtk.TreeViewColumn(self._("Name"), name_renderer, \
310 text = enumerations.NAME_COLUMN)
311 column.set_sort_column_id(enumerations.NAME_COLUMN)
312 column.set_sort_indicator(True)
313 column.set_cell_data_func(name_renderer, self.cell_data_function, None)
314 self.w_application_treeview.append_column(column)
315 installed_version_renderer = gtk.CellRendererText()
316 column = gtk.TreeViewColumn(self._('Installed Version'), \
317 installed_version_renderer, \
318 text = enumerations.INSTALLED_VERSION_COLUMN)
319 column.set_sort_column_id(enumerations.INSTALLED_VERSION_COLUMN)
320 column.set_sort_indicator(True)
321 column.set_cell_data_func(installed_version_renderer, \
322 self.cell_data_function, None)
323 self.w_application_treeview.append_column(column)
324 latest_available_renderer = gtk.CellRendererText()
325 column = gtk.TreeViewColumn(self._('Latest Version'), \
326 latest_available_renderer, \
327 text = enumerations.LATEST_AVAILABLE_COLUMN)
328 column.set_sort_column_id(enumerations.LATEST_AVAILABLE_COLUMN)
329 column.set_sort_indicator(True)
330 column.set_cell_data_func(latest_available_renderer, \
331 self.cell_data_function, None)
332 self.w_application_treeview.append_column(column)
333 rating_renderer = gtk.CellRendererText()
334 column = gtk.TreeViewColumn(self._('Rating'), rating_renderer, \
335 text = enumerations.RATING_COLUMN)
336 column.set_cell_data_func(rating_renderer, self.cell_data_function, None)
337 description_renderer = gtk.CellRendererText()
338 column = gtk.TreeViewColumn(self._('Description'), \
339 description_renderer, text = enumerations.DESCRIPTION_COLUMN)
340 column.set_sort_column_id(enumerations.DESCRIPTION_COLUMN)
341 column.set_sort_indicator(True)
342 column.set_cell_data_func(description_renderer, \
343 self.cell_data_function, None)
344 self.w_application_treeview.append_column(column)
345 #Added selection listener
346 self.package_selection = self.w_application_treeview.get_selection()
347 self.package_selection.set_mode(gtk.SELECTION_SINGLE)
348 self.package_selection.connect("changed", \
349 self.__on_package_selection_changed, None)
350 ##CATEGORIES TREEVIEW
351 #enumerations.CATEGORY_NAME
352 self.category_list_filter = self.category_list.filter_new()
353 self.category_list_filter.set_visible_func(self.category_filter)
354 self.w_categories_treeview.set_model(self.category_list_filter)
355 enumerations.CATEGORY_NAME_renderer = gtk.CellRendererText()
356 column = gtk.TreeViewColumn(self._('Name'), \
357 enumerations.CATEGORY_NAME_renderer, \
358 text = enumerations.CATEGORY_NAME)
359 self.w_categories_treeview.append_column(column)
360 #Added selection listener
361 category_selection = self.w_categories_treeview.get_selection()
362 category_selection.set_mode(gtk.SELECTION_SINGLE)
363 category_selection.connect("changed", \
364 self.__on_category_selection_changed, None)
365 ##SECTION COMBOBOX
366 #enumerations.SECTION_NAME
367 self.w_sections_combobox.set_model(self.section_list)
368 cell = gtk.CellRendererText()
369 self.w_sections_combobox.pack_start(cell, True)
370 self.w_sections_combobox.add_attribute(cell, 'text', \
371 enumerations.SECTION_NAME)
372 self.w_sections_combobox.set_row_separator_func( \
373 self.combobox_id_separator)
374 ##FILTER COMBOBOX
375 #enumerations.FILTER_NAME
376 self.w_filter_combobox.set_model(self.filter_list)
377 cell = gtk.CellRendererText()
378 self.w_filter_combobox.pack_start(cell, True)
379 self.w_filter_combobox.add_attribute(cell, 'text', \
380 enumerations.FILTER_NAME)
381 self.w_filter_combobox.set_row_separator_func(self.combobox_id_separator)
382 ##FILTER COMBOBOX
383 #enumerations.FILTER_NAME
384 self.w_repository_combobox.set_model(self.repositories_list)
385 cell = gtk.CellRendererText()
386 self.w_repository_combobox.pack_start(cell, True)
387 self.w_repository_combobox.add_attribute(cell, 'text', \
388 enumerations.REPOSITORY_NAME)
389 self.w_repository_combobox.set_row_separator_func( \
390 self.combobox_id_separator)
391 self.w_filter_combobox.set_active(0)
392
393 def __init_sections(self):
394 '''This function is for initializing sections combo box, also adds "All"
395 Category. It sets active section combobox entry "All"'''
396 self.section_list.append([0, self._('All'), ])
397 self.section_list.append([-1, "", ])
398 self.section_list.append([2, self._('Meta Packages'), ])
399 self.section_list.append([3, self._('Applications Desktop'), ])
400 self.section_list.append([4, self._('Applications Web-Based'), ])
401 self.section_list.append([5, self._('Operating System'), ])
402 self.section_list.append([6, self._('User Environment'), ])
403 self.section_list.append([7, self._('Web Infrastructure'), ])
404
405 def __init_show_filter(self):
406 self.filter_list.append([0, self._('All Packages'), ])
407 self.filter_list.append([-1, "", ])
408 self.filter_list.append([2, self._('Installed Packages'), ])
409 self.filter_list.append([3, self._('Updates'), ])
410 self.filter_list.append([4, self._('Non-installed Packages'), ])
411 self.filter_list.append([-1, "", ])
412 # self.filter_list.append([self._('Locked Packages'), ])
413 # self.filter_list.append(["", ])
414 self.filter_list.append([6, self._('Selected Packages'), ])
415
416 def __on_cancel_progressdialog_clicked(self, widget):
417 self.progress_canceled = True
418 self.progress_stop_timer_thread = True
419
420 def __on_mainwindow_delete_event(self, widget, event):
421 ''' handler for delete event of the main window '''
422 if self.__check_if_something_was_changed() == True:
423 # XXX Change this to not quit and show dialog
424 # XXX if some changes were applied:
425 self.__main_application_quit()
426 return True
427 else:
428 self.__main_application_quit()
429
430 def __on_file_quit_activate(self, widget):
431 ''' handler for quit menu event '''
432 self.__on_mainwindow_delete_event(None, None)
433
434 def __on_file_be_activate(self, widget):
435 ''' handler for be menu event '''
436 beadm.Beadmin(self)
437
438 def __on_searchentry_changed(self, widget):
439 '''On text search field changed we should refilter the main view'''
440 Thread(target = self.__on_searchentry_threaded, args = ()).start()
441
442 def __on_searchentry_threaded(self):
443 gobject.idle_add(self.application_list_filter.refilter)
444 gobject.idle_add(self.__enable_disable_selection_menus)
445
446 def __on_edit_paste(self, widget):
447 self.w_searchentry_dialog.insert_text(self.main_clipboard_text, \
448 self.w_searchentry_dialog.get_position())
449
450 def __on_clear_paste(self, widget):
451 bounds = self.w_searchentry_dialog.get_selection_bounds()
452 self.w_searchentry_dialog.delete_text(bounds[0], bounds[1])
453 return
454
455 def __on_copy(self, widget):
456 bounds = self.w_searchentry_dialog.get_selection_bounds()
457 text = self.w_searchentry_dialog.get_chars(bounds[0], bounds[1])
458 self.w_main_clipboard.set_text(text)
459 return
460
461 def __on_cut(self, widget):
462 bounds = self.w_searchentry_dialog.get_selection_bounds()
463 text = self.w_searchentry_dialog.get_chars(bounds[0], bounds[1])
464 self.w_searchentry_dialog.delete_text(bounds[0], bounds[1])
465 self.w_main_clipboard.set_text(text)
466 return
467
468 def __on_select_all(self, widget):
469 sort_filt_model = \
470 self.w_application_treeview.get_model() #gtk.TreeModelSort
471 filt_model = sort_filt_model.get_model() #gtk.TreeModelFilter
472 model = filt_model.get_model() #gtk.ListStore
473 iter_next = sort_filt_model.get_iter_first()
474 list_of_paths = []
475 while iter_next != None:
476 sorted_path = sort_filt_model.get_path(iter_next)
477 filtered_path = \
478 sort_filt_model.convert_path_to_child_path(sorted_path)
479 path = filt_model.convert_path_to_child_path(filtered_path)
480 list_of_paths.append(path)
481 iter_next = sort_filt_model.iter_next(iter_next)
482 for path in list_of_paths:
483 itr = model.get_iter(path)
484 model.set_value(itr, enumerations.MARK_COLUMN, True)
485 self.__enable_disable_selection_menus()
486 self.update_statusbar()
487 self.__enable_disable_install_update()
488 self.__enable_disable_remove()
489
490 def __on_select_updates(self, widget):
491 sort_filt_model = \
492 self.w_application_treeview.get_model() #gtk.TreeModelSort
493 filt_model = sort_filt_model.get_model() #gtk.TreeModelFilter
494 model = filt_model.get_model() #gtk.ListStore
495 iter_next = sort_filt_model.get_iter_first()
496 list_of_paths = []
497 while iter_next != None:
498 sorted_path = sort_filt_model.get_path(iter_next)
499 filtered_iter = sort_filt_model.convert_iter_to_child_iter(None, \
500 iter_next)
501 app_iter = filt_model.convert_iter_to_child_iter(filtered_iter)
502
503 filtered_path = \
504 sort_filt_model.convert_path_to_child_path(sorted_path)
505 path = filt_model.convert_path_to_child_path(filtered_path)
506 if model.get_value(app_iter, \
507 enumerations.INSTALLED_VERSION_COLUMN):
508 if model.get_value(app_iter, \
509 enumerations.LATEST_AVAILABLE_COLUMN):
510 list_of_paths.append(path)
511 iter_next = sort_filt_model.iter_next(iter_next)
512 for path in list_of_paths:
513 itr = model.get_iter(path)
514 model.set_value(itr, enumerations.MARK_COLUMN, True)
515 self.__enable_disable_selection_menus()
516 self.update_statusbar()
517 self.__enable_disable_install_update()
518 self.__enable_disable_remove()
519
520 def __on_deselect(self, widget):
521 sort_filt_model = \
522 self.w_application_treeview.get_model() #gtk.TreeModelSort
523 filt_model = sort_filt_model.get_model() #gtk.TreeModelFilter
524 model = filt_model.get_model() #gtk.ListStore
525 iter_next = sort_filt_model.get_iter_first()
526 list_of_paths = []
527 while iter_next != None:
528 sorted_path = sort_filt_model.get_path(iter_next)
529 filtered_iter = sort_filt_model.convert_iter_to_child_iter(None, \
530 iter_next)
531 app_iter = filt_model.convert_iter_to_child_iter(filtered_iter)
532 filtered_path = \
533 sort_filt_model.convert_path_to_child_path(sorted_path)
534 path = filt_model.convert_path_to_child_path(filtered_path)
535 if model.get_value(app_iter, enumerations.MARK_COLUMN):
536 list_of_paths.append(path)
537 iter_next = sort_filt_model.iter_next(iter_next)
538 for path in list_of_paths:
539 itr = model.get_iter(path)
540 model.set_value(itr, enumerations.MARK_COLUMN, False)
541 self.__enable_disable_selection_menus()
542 self.update_statusbar()
543 self.__enable_disable_install_update()
544 self.__enable_disable_remove()
545
546 def __on_searchentry_focus_in(self, widget, event):
547 self.w_paste_menuitem.set_sensitive(True)
548
549 def __on_searchentry_focus_out(self, widget, event):
550 self.w_paste_menuitem.set_sensitive(False)
551
552 def __on_searchentry_event(self, widget, event):
553 self.w_main_clipboard.request_text(self.__clipboard_text_received)
554 if widget.get_selection_bounds():
555 #enable selection functions
556 self.w_cut_menuitem.set_sensitive(True)
557 self.w_copy_menuitem.set_sensitive(True)
558 self.w_clear_menuitem.set_sensitive(True)
559 else:
560 self.w_cut_menuitem.set_sensitive(False)
561 self.w_copy_menuitem.set_sensitive(False)
562 self.w_clear_menuitem.set_sensitive(False)
563
564 def __on_category_selection_changed(self, selection, widget):
565 '''This function is for handling category selection changes'''
566 self.application_list_filter.refilter()
567 self.__enable_disable_selection_menus()
568
569 def __on_package_selection_changed(self, selection, widget):
570 '''This function is for handling package selection changes'''
571 model, itr = selection.get_selected()
572 if itr:
573 pkg = model.get_value(itr, enumerations.INSTALLED_OBJECT_COLUMN)
574 if not pkg:
575 packages = model.get_value(itr, \
576 enumerations.PACKAGE_OBJECT_COLUMN)
577 pkg = max(packages)
578 self.pkginfo_thread = pkg
579 Thread(target = self.__show_package_info, \
580 args = (model, itr)).start()
581
582 def __on_filtercombobox_changed(self, widget):
583 '''On filter combobox changed'''
584 self.application_list_filter.refilter()
585 self.__enable_disable_selection_menus()
586
587 def __on_sectionscombobox_changed(self, widget):
588 '''On section combobox changed'''
589 selected_section = widget.get_active()
590 if selected_section == 0:
591 for category in self.category_list:
592 category[enumerations.CATEGORY_VISIBLE] = True
593 else:
594 for category in self.category_list:
595 if category[enumerations.CATEGORY_ID] == 0:
596 category[enumerations.CATEGORY_VISIBLE] = True
597 else:
598 category_list = \
599 category[enumerations.SECTION_LIST_OBJECT]
600 if not category_list:
601 category[enumerations.CATEGORY_VISIBLE] \
602 = False
603 else:
604 for section in category_list:
605 if section == selected_section:
606 category[enumerations. \
607 CATEGORY_VISIBLE] = \
608 True
609 else:
610 category[enumerations. \
611 CATEGORY_VISIBLE] = \
612 False
613 self.category_list_filter.refilter()
614 self.application_list_filter.refilter()
615 self.__enable_disable_selection_menus()
616
617 def __on_repositorycombobox_changed(self, widget):
618 '''On repository combobox changed'''
619 if self.in_setup:
620 return
621 self.application_list_filter.refilter()
622 self.__enable_disable_selection_menus()
623
624 def __on_install_update(self, widget):
625 installupdate.InstallUpdate(self.application_list, self, False)
626
627 def __on_update_all(self, widget):
628 opensolaris_image = True
629 fmris, notfound = self.__installed_fmris_from_args(self.image_o, \
630 ["SUNWipkg", "SUNWcs"])
631
632 if notfound:
633 opensolaris_image = False
634
635 if opensolaris_image:
636 # Load the catalogs from the repository, its a long
637 # running tasks so need a progress dialog
638 self.w_progress_dialog.set_title(self._("Update All"))
639 self.w_progressinfo_label.set_text(self._( \
640 "Checking SUNWipkg and SUNWipkg-gui versions\n" + \
641 "\nPlease wait ..."))
642
643 self.w_progress_dialog.show()
644 Thread(target = self.__progressdialog_progress_pulse).start()
645 Thread(target = self.__do_ips_uptodate_check).start()
646 self.w_progress_dialog.run()
647
648 if self.progress_canceled:
649 return
650 else:
651 self.ips_uptodate = True
652
653 #2790: Make sure ipkg and ipkg-gui are up to date, if not update them and
654 # prompt user to restart
655 if not self.ips_uptodate:
656 # Prompt user
657 msgbox = gtk.MessageDialog(parent = self.w_main_window, \
658 buttons = gtk.BUTTONS_YES_NO, \
659 flags = gtk.DIALOG_MODAL, type = gtk.MESSAGE_QUESTION, \
660 message_format = self._("Newer versions of SUNWipkg and" + \
661 "SUNWipkg-gui are available " + "and\nmust be updated" + \
662 "before running Update All.\n\n Do you want to update" + \
663 "them now?"))
664 msgbox.set_title(self._("Update All"))
665 result = msgbox.run()
666 msgbox.destroy()
667 if result == gtk.RESPONSE_YES:
668 pkg_list = [self.ipkg_fmri, self.ipkggui_fmri]
669 installupdate.InstallUpdate({self.image_o:pkg_list}, \
670 self, False, True)
671 else:
672 msgbox = gtk.MessageDialog(parent = self.w_main_window, \
673 buttons = gtk.BUTTONS_OK, \
674 flags = gtk.DIALOG_MODAL, type = gtk.MESSAGE_INFO, \
675 message_format = self._("Update All was not " + \
676 "run.\n\n It can not be run until SUNWipkg and " + \
677 "SUNWipkg-gui have been updated."))
678 msgbox.set_title(self._("Update All"))
679 result = msgbox.run()
680 msgbox.destroy()
681 else:
682 pkg_list = [ ipkg.get_pkg_stem() for ipkg in \
683 self.image_o.gen_installed_pkgs() ]
684 installupdate.InstallUpdate({self.image_o:pkg_list}, self, \
685 True, False)
686
687 def __on_help_about(self, widget):
688 wTreePlan = gtk.glade.XML(self.gladefile, "aboutdialog")
689 aboutdialog = wTreePlan.get_widget("aboutdialog")
690 aboutdialog.connect("response", lambda x = None, \
691 y = None: aboutdialog.destroy())
692 aboutdialog.run()
693
694 def __on_remove(self, widget):
695 remove.Remove(self.application_list, self)
696
697 def __on_reload(self, widget):
698 if self.description_thread_running:
699 self.cancelled = True
700 self.__catalog_refresh()
701 self.process_package_list_start(self.image_directory)
702 self.category_list_filter.refilter()
703 self.application_list_filter.refilter()
704 self.__enable_disable_selection_menus()
705 self.update_statusbar()
706 self.__update_install_update_button(None, True)
707 self.__update_remove_button(None, True)
708
709 def __clipboard_text_received(self, clipboard, text, data):
710 self.main_clipboard_text = text
711 return
712
713 def __main_application_quit(self, restart_app = False):
714 '''quits the main gtk loop'''
715 self.cancelled = True
716 if self.in_setup:
717 return
718
719 if restart_app:
720 if "image_dir_arg" in self.__dict__:
721 gobject.spawn_async([self.application_path, "-R", \
722 self.image_dir_arg])
723 else:
724 gobject.spawn_async([self.application_path])
725 gtk.main_quit()
726 sys.exit(0)
727 return True
728
729 def __check_if_something_was_changed(self):
730 ''' Returns True if any of the check boxes for package was changed, false
731 if not'''
732 for pkg in self.application_list:
733 if pkg[enumerations.MARK_COLUMN] == True:
734 return True
735 return False
736
737 def __setup_repositories_combobox(self, img):
738 if self.in_setup or img == None:
739 return
740
741 repositories = img.catalogs
742 default_authority = img.get_default_authority()
743 self.repositories_list.clear()
744 i = 0
745 active = 0
746 for repo in repositories:
747 if cmp(repo, default_authority) == 0:
748 active = i
749
750 self.repositories_list.append([i, repo, ])
751 i = i + 1
752 if default_authority:
753 self.w_repository_combobox.set_active(active)
754 else:
755 self.w_repository_combobox.set_active(0)
756
757 def __active_pane_toggle(self, cell, path, model_sort):
758 '''Toggle function for column enumerations.MARK_COLUMN'''
759 applicationModel = model_sort.get_model()
760 applicationPath = model_sort.convert_path_to_child_path(path)
761 filterModel = applicationModel.get_model()
762 child_path = applicationModel.convert_path_to_child_path(applicationPath)
763 itr = filterModel.get_iter(child_path)
764 if itr:
765 modified = filterModel.get_value(itr, enumerations.MARK_COLUMN)
766 filterModel.set_value(itr, enumerations.MARK_COLUMN, \
767 not modified)
768 latest_available = filterModel.get_value(itr, \
769 enumerations.LATEST_AVAILABLE_COLUMN)
770 installed_available = filterModel.get_value(itr, \
771 enumerations.INSTALLED_VERSION_COLUMN)
772 self.update_statusbar()
773 self.__update_install_update_button(latest_available, modified)
774 self.__update_remove_button(installed_available, modified)
775 self.__enable_disable_selection_menus()
776
777
778 def __update_install_update_button(self, latest_available, toggle_true):
779 if not toggle_true and self.user_rights:
780 if latest_available:
781 self.w_installupdate_button.set_sensitive(True)
782 self.w_installupdate_menuitem.set_sensitive(True)
783 else:
784 available = None
785 for row in self.application_list:
786 if row[enumerations.MARK_COLUMN]:
787 available = \
788 row[enumerations.LATEST_AVAILABLE_COLUMN]
789 if available:
790 return
791 if not available:
792 self.w_installupdate_button.set_sensitive(False)
793 self.w_installupdate_menuitem.set_sensitive(False)
794
795 def __update_reload_button(self):
796 if self.user_rights:
797 self.w_reload_button.set_sensitive(True)
798 else:
799 self.w_reload_button.set_sensitive(False)
800
801 def __update_remove_button(self, installed_available, toggle_true):
802 if not toggle_true and self.user_rights:
803 if installed_available:
804 self.w_remove_button.set_sensitive(True)
805 self.w_remove_menuitem.set_sensitive(True)
806 else:
807 available = None
808 for row in self.application_list:
809 if row[enumerations.MARK_COLUMN]:
810 installed = \
811 row[enumerations.INSTALLED_VERSION_COLUMN]
812 if installed:
813 return
814 if not available:
815 self.w_remove_button.set_sensitive(False)
816 self.w_remove_menuitem.set_sensitive(False)
817
818 def __update_package_info(self, pkg, icon, installed, manifest):
819 if icon and icon != pkg:
820 self.w_packageicon_image.set_from_pixbuf(icon)
821 else:
822 self.w_packageicon_image.set_from_pixbuf( \
823 self.__get_pixbuf_from_path("/usr/share/package-manager/", \
824 "PM_package_36x"))
825 self.w_packagename_label.set_markup("<b>" + pkg.get_name() + "</b>")
826 instbuffer = self.w_installedfiles_textview.get_buffer()
827 depbuffer = self.w_dependencies_textview.get_buffer()
828 infobuffer = self.w_generalinfo_textview.get_buffer()
829 if not manifest:
830 self.w_shortdescription_label.set_text( \
831 self._("Fetching description..."))
832 instbuffer.set_text(self._("Fetching information..."))
833 depbuffer.set_text(self._("Fetching information..."))
834 infobuffer.set_text(self._("Fetching information..."))
835 return
836 if manifest == "NotAvailable":
837 self.w_shortdescription_label.set_text( \
838 self._("Description not available for this package..."))
839 instbuffer.set_text( \
840 self._("Files Details not available for this package..."))
841 depbuffer.set_text(self._( \
842 "Dependencies info not available for this package..."))
843 infobuffer.set_text( \
844 self._("Information not available for this package..."))
845 return
846 self.w_shortdescription_label.set_text(manifest.get("description", ""))
847 instbuffer.set_text(self._("Root: %s\n") % manifest.img.get_root())
848 depbuffer.set_text(self._("Dependencies:\n"))
849 if installed:
850 infobuffer.set_text( \
851 self._("Information for installed package:\n\n"))
852 else:
853 infobuffer.set_text( \
854 self._("Information for latest available package:\n\n"))
855 depiter = depbuffer.get_end_iter()
856 institer = instbuffer.get_end_iter()
857 infoiter = infobuffer.get_end_iter()
858 #Name: SUNWckr
859 #FMRI: pkg://opensolaris.org/SUNWckr@0.5.11,5.11-0.75:20071114T203148Z
860 #Version: 0.5.11
861 #Branch: 0.75
862 #Packaging Date: 2007-11-14 20:31:48
863 #Size: 29369698
864 #Summary: Core Solaris Kernel (Root)
865 for a in manifest.actions:
866 if cmp(a.name, self.n_("depend")) == 0:
867 #Remove "depend: " -> [8:]
868 depbuffer.insert(depiter, "\t" + \
869 self.__locale_distinguished_name(a)[8:]+"\n")
870 elif cmp(a.name,self.n_("dir")) == 0:
871 instbuffer.insert(institer, "\t" + \
872 self.__locale_distinguished_name(a)+"\n")
873 elif cmp(a.name,self.n_("file")) == 0:
874 instbuffer.insert(institer, "\t" + \
875 self.__locale_distinguished_name(a)+"\n")
876 elif cmp(a.name,self.n_("hardlink")) == 0:
877 instbuffer.insert(institer, "\t" + \
878 self.__locale_distinguished_name(a)+"\n")
879 elif cmp(a.name,self.n_("link")) == 0:
880 instbuffer.insert(institer, "\t" + \
881 self.__locale_distinguished_name(a)+"\n")
882 elif cmp(a.name,self.n_("legacy")) == 0:
883 if cmp(a.attrlist(self.n_("pkg"))[0], \
884 pkg.get_name()) == 0:
885 desc = a.attrlist(self.n_("desc"))
886 infobuffer.insert(infoiter, \
887 self._(" Description:\t%s\n") % desc[0])
888 else:
889 pass
890 infobuffer.insert(infoiter, self._(" Name:\t\t%s\n") % pkg.get_name())
891 infobuffer.insert(infoiter, self._(" FMRI:\t\t%s\n") % pkg.get_fmri())
892 infobuffer.insert(infoiter, self._(" Version:\t\t%s\n") % \
893 pkg.version.get_short_version())
894 infobuffer.insert(infoiter, self._(" Packaged:\t%s\n") % \
895 self.get_datetime(pkg.version))
896
897 def __update_description(self, description, package):
898 '''workaround function'''
899 for pkg in self.application_list:
900 p = pkg[enumerations.PACKAGE_OBJECT_COLUMN][0]
901 if p == package:
902 pkg[enumerations.DESCRIPTION_COLUMN] = description
903 return
904
905 def __show_package_info(self, model, itr):
906 img = model.get_value(itr, enumerations.IMAGE_OBJECT_COLUMN)
907 pkg = model.get_value(itr, enumerations.INSTALLED_OBJECT_COLUMN)
908 icon = model.get_value(itr, enumerations.INSTALLED_OBJECT_COLUMN)
909 if not pkg:
910 packages = model.get_value(itr, \
911 enumerations.PACKAGE_OBJECT_COLUMN)
912 pkg = max(packages)
913 gobject.idle_add(self.__update_package_info, pkg, icon, False, \
914 None)
915 else:
916 gobject.idle_add(self.__update_package_info, pkg, icon,
917 True, None)
918 man = None
919 try:
920 man = img.get_manifest(pkg, filtered = True)
921 except IOError:
922 man = "NotAvailable"
923 if cmp(self.pkginfo_thread, pkg) == 0:
924 if not pkg:
925 gobject.idle_add(self.__update_package_info, pkg, icon, \
926 False, man)
927 else:
928 gobject.idle_add(self.__update_package_info, pkg, icon, \
929 True, man)
930 else:
931 return
932
933 # This function is ported from pkg.actions.generic.distinguished_name()
934 def __locale_distinguished_name(self, action):
935 if action.key_attr == None:
936 return str(action)
937 return "%s: %s" % \
938 (self._(action.name), action.attrs.get(action.key_attr, "???"))
939
940 def __application_filter(self, model, itr):
941 '''This function is used to filter content in the main
942 application view'''
943 if self.in_setup or self.cancelled:
944 return False
945 # XXX Show filter, chenge text to integers
946 selected_category = 0
947 selection = self.w_categories_treeview.get_selection()
948 category_model, category_iter = selection.get_selected()
949 if not category_iter: #no category was selected, so select "All"
950 selection.select_path(0)
951 category_model, category_iter = selection.get_selected()
952 if category_iter:
953 selected_category = category_model.get_value(category_iter, \
954 enumerations.CATEGORY_ID)
955 category_list_iter = model.get_value(itr, \
956 enumerations.CATEGORY_LIST_OBJECT)
957 category = False
958 repository = self.__is_pkg_repository_visible(model, itr)
959 if category_list_iter:
960 sel = False
961 for category_iter in category_list_iter:
962 if category != True:
963 category = \
964 self.category_filter(self.category_list, \
965 category_iter)
966 if selected_category != 0:
967 if selected_category == \
968 self.category_list.get_value(category_iter, \
969 enumerations.CATEGORY_ID):
970 sel = True
971 category = sel
972 else:
973 if selected_category == 0:
974 selected_section = self.w_sections_combobox.get_active()
975 if selected_section == 0:
976 category = True
977 if (model.get_value(itr, enumerations.IS_VISIBLE_COLUMN) == False):
978 return False
979 if self.w_searchentry_dialog.get_text() == "":
980 return (repository & category & \
981 self.__is_package_filtered(model, itr))
982 if not model.get_value(itr, enumerations.NAME_COLUMN) == None:
983 if self.w_searchentry_dialog.get_text().lower() in \
984 model.get_value \
985 (itr, enumerations.NAME_COLUMN).lower():
986 return (repository & category & \
987 self.__is_package_filtered(model, itr))
988 if not model.get_value(itr, enumerations.DESCRIPTION_COLUMN) == None:
989 if self.w_searchentry_dialog.get_text().lower() in \
990 model.get_value \
991 (itr, enumerations.DESCRIPTION_COLUMN).lower():
992 return (repository & category & \
993 self.__is_package_filtered(model, itr))
994 else:
995 return False
996
997 def __is_package_filtered(self, model, itr):
998 '''Function for filtercombobox'''
999 # XXX Instead of string comparison, we should do it through integers.
1000 # XXX It should be faster and better for localisations.
1001 filter_text = self.w_filter_combobox.get_active()
1002 if filter_text == 0:
1003 return True
1004 elif filter_text == 2:
1005 return model.get_value(itr, \
1006 enumerations.INSTALLED_VERSION_COLUMN) != None
1007 elif filter_text == 3:
1008 return (model.get_value(itr, \
1009 enumerations.INSTALLED_VERSION_COLUMN) != None) & \
1010 (model.get_value(itr, \
1011 enumerations.LATEST_AVAILABLE_COLUMN) != None)
1012 elif filter_text == 4:
1013 return not model.get_value(itr, \
1014 enumerations.INSTALLED_VERSION_COLUMN) != None
1015 elif filter_text == 6:
1016 return model.get_value(itr, enumerations.MARK_COLUMN)
1017 elif filter_text == 8:
1018 # XXX Locked support
1019 return False
1020
1021
1022 def __is_pkg_repository_visible(self, model, itr):
1023 if len(self.repositories_list) <= 1:
1024 return True
1025 else:
1026 auth_iter = self.w_repository_combobox.get_active_iter()
1027 authority = self.repositories_list.get_value(auth_iter, \
1028 enumerations.REPOSITORY_NAME)
1029 packages = model.get_value(itr, \
1030 enumerations.PACKAGE_OBJECT_COLUMN)
1031 if not packages:
1032 return False
1033 pkg = max(packages)
1034 if cmp(pkg.get_authority(), authority) == 0:
1035 return True
1036 else:
1037 return False
1038
1039 def __do_ips_uptodate_check(self):
1040 self.ips_uptodate = self.__ipkg_ipkgui_uptodate(self.image_o)
1041 self.progress_stop_timer_thread = True
1042
1043 def __ipkg_ipkgui_uptodate(self, img):
1044 if not img.is_liveroot():
1045 newimg = image.Image()
1046 cmdpath = os.path.join(os.getcwd(), sys.argv[0])
1047 cmdpath = os.path.realpath(cmdpath)
1048 cmddir = os.path.dirname(os.path.realpath(cmdpath))
1049 try:
1050 #
1051 # Find the path to ourselves, and use that
1052 # as a way to locate the image we're in. It's
1053 # not perfect-- we could be in a developer's
1054 # workspace, for example.
1055 #
1056 newimg.find_root(cmddir)
1057 except ValueError:
1058 # We can't answer in this case, so we return True to
1059 # let installation proceed.
1060 # TODO: log - msg(_("No image corresponding to '%s' was
1061 # located. " \ "Proceeding.") % cmdpath)
1062 return True
1063 newimg.load_config()
1064 img = newimg
1065
1066 try:
1067 img.retrieve_catalogs()
1068 except image.CatalogRefreshException:
1069 raise
1070 # Reload catalog. This picks up the update from retrieve_catalogs.
1071 img.load_catalogs(self.pr)
1072
1073 try:
1074 # We will use whatever the incorporation provides as the latest
1075 # version of ipkg and ipkg-gui
1076
1077 img.make_install_plan([self.ipkg_fmri, self.ipkggui_fmri], \
1078 self.pr, filters = [], noexecute = True)
1079 except RuntimeError:
1080 return True
1081
1082 if img.imageplan.nothingtodo():
1083 return True
1084
1085 return False
1086
1087
1088 def __enable_disable_selection_menus(self):
1089
1090 if self.in_setup:
1091 return
1092 self.__enable_disable_select_all()
1093 self.__enable_disable_select_updates()
1094 self.__enable_disable_deselect()
1095 # XXX disabled until new API
1096 self.__enable_disable_update_all()
1097
1098 def __enable_disable_select_all(self):
1099
1100 if self.in_setup:
1101 return
1102 if len(self.w_application_treeview.get_model()) > 0:
1103 for row in self.w_application_treeview.get_model():
1104 if not row[enumerations.MARK_COLUMN]:
1105 self.w_selectall_menuitem.set_sensitive(True)
1106 return
1107 self.w_selectall_menuitem.set_sensitive(False)
1108 else:
1109 self.w_selectall_menuitem.set_sensitive(False)
1110
1111 def __enable_disable_install_update(self):
1112 for row in self.application_list:
1113 if row[enumerations.MARK_COLUMN]:
1114 if row[enumerations.LATEST_AVAILABLE_COLUMN] and \
1115 self.user_rights:
1116 self.w_installupdate_button.set_sensitive(True)
1117 self.w_installupdate_menuitem.set_sensitive(True)
1118 return
1119 self.w_installupdate_button.set_sensitive(False)
1120 self.w_installupdate_menuitem.set_sensitive(False)
1121
1122 def __enable_disable_remove(self):
1123 for row in self.application_list:
1124 if row[enumerations.MARK_COLUMN]:
1125 if row[enumerations.INSTALLED_VERSION_COLUMN] and \
1126 self.user_rights:
1127 self.w_remove_button.set_sensitive(True)
1128 self.w_remove_menuitem.set_sensitive(True)
1129 return
1130 self.w_remove_button.set_sensitive(False)
1131 self.w_remove_menuitem.set_sensitive(False)
1132
1133 def __enable_disable_select_updates(self):
1134 for row in self.w_application_treeview.get_model():
1135 if row[enumerations.INSTALLED_VERSION_COLUMN]:
1136 if row[enumerations.LATEST_AVAILABLE_COLUMN]:
1137 if not row[enumerations.MARK_COLUMN]:
1138 self.w_selectupdates_menuitem. \
1139 set_sensitive(True)
1140 return
1141 self.w_selectupdates_menuitem.set_sensitive(False)
1142 return
1143
1144 def __enable_disable_update_all(self):
1145 for row in self.application_list:
1146 if self.__is_pkg_repository_visible(self.application_list, \
1147 row.iter):
1148 if self.application_list.get_value(row.iter, \
1149 enumerations.INSTALLED_VERSION_COLUMN):
1150 if self.application_list.get_value(row.iter, \
1151 enumerations.LATEST_AVAILABLE_COLUMN) and \
1152 self.user_rights:
1153 self.w_updateall_menuitem. \
1154 set_sensitive(True)
1155 self.w_updateall_button. \
1156 set_sensitive(True)
1157 return
1158 self.w_updateall_button.set_sensitive(False)
1159 self.w_updateall_menuitem.set_sensitive(False)
1160
1161 def __enable_disable_deselect(self):
1162 for row in self.w_application_treeview.get_model():
1163 if row[enumerations.MARK_COLUMN]:
1164 self.w_deselect_menuitem.set_sensitive(True)
1165 return
1166 self.w_deselect_menuitem.set_sensitive(False)
1167 return
1168
1169
1170 def __catalog_refresh(self):
1171 """Update image's catalogs."""
1172 images = self.__get_images_from_model()
1173 full_refresh = False
1174 for img in images:
1175 # Ensure Image directory structure is valid.
1176 if not os.path.isdir("%s/catalog" % img.imgdir):
1177 img.mkdirs()
1178 # Loading catalogs allows us to perform incremental update
1179 img.retrieve_catalogs(full_refresh)
1180
1181 def __get_images_from_model(self):
1182 images = []
1183 for row in self.application_list:
1184 img = row[enumerations.IMAGE_OBJECT_COLUMN]
1185 if img:
1186 if not img in images:
1187 images.append(img)
1188 return images
1189
1190 def __get_image_obj_from_directory(self, image_directory):
1191 image_obj = image.Image()
1192 dr = "/"
1193 try:
1194 image_obj.find_root(image_directory)
1195 image_obj.load_config()
1196 image_obj.load_catalogs(self.pr)
1197 except ValueError:
1198 print self._('%s is not valid image, trying root image') \
1199 % image_directory
1200 try:
1201 dr = os.environ["PKG_IMAGE"]
1202 except KeyError:
1203 print
1204 try:
1205 image_obj.find_root(dr)
1206 image_obj.load_config()
1207 image_obj.load_catalogs(self.pr)
1208 except ValueError:
1209 print self._('%s is not valid root image, return None') \
1210 % dr
1211 image_obj = None
1212 return image_obj
1213
1214
1215
1216 def __get_image_from_directory(self, image_obj, progressdialog_progress):
1217 """ This method set up image from the given directory and
1218 returns the image object or None"""
1219 # XXX Convert timestamp to some nice date :)
1220 self.application_list.clear()
1221 self.category_list.clear()
1222 self.application_list_filter.refilter()
1223 try:
1224 pkgs_known = [ pf[0] for pf in
1225 sorted(image_obj.inventory(all_known = True)) ]
1226 except image.InventoryException, e:
1227 # Can't happen when all_known is true and no args,
1228 # but here for completeness.
1229 raise
1230 #Only one instance of those icons should be in memory
1231 update_available_icon = self.get_icon_pixbuf("new_update")
1232 #Imageinfo for categories
1233 imginfo = imageinfo.ImageInfo()
1234 sectioninfo = imageinfo.ImageInfo()
1235 catalogs = image_obj.catalogs
1236 categories = {}
1237 sections = {}
1238 self.__setup_repositories_combobox(image_obj)
1239 for cat in catalogs:
1240 category = imginfo.read(self.application_dir + \
1241 "/usr/share/package-manager/data/" + cat)
1242 categories[cat] = category
1243 section = sectioninfo.read(self.application_dir + \
1244 "/usr/share/package-manager/data/" + cat + ".sections")
1245 sections[cat] = section
1246 # Speedup, instead of checking if the pkg is already in the list,
1247 # iterating through all elements, we will only compare to the previous
1248 # package and if the package is the same (version difference) then we
1249 # are adding to the first iterator for the set of those packages.
1250 # We can do that, since the list pkgs_known is sorted
1251 # This will give a sppedup from 18sec to ~3!!!
1252 p_pkg_iter = None
1253 p_pkg = None
1254 insert_count = 0
1255 icon_path = self.application_dir + \
1256 "/usr/share/package-manager/data/pixmaps/"
1257
1258 pkg_count = 0
1259 progress_percent = INITIAL_PROGRESS_TOTAL_PERCENTAGE
1260 total_pkg_count = len(pkgs_known)
1261 progress_increment = \
1262 total_pkg_count / PACKAGE_PROGRESS_TOTAL_INCREMENTS
1263
1264 self.progress_stop_timer_thread = True
1265 while gtk.events_pending():
1266 gtk.main_iteration(False)
1267 for pkg in pkgs_known:
1268 if pkg_count % progress_increment == 0:
1269 progress_percent += PACKAGE_PROGRESS_PERCENT_INCREMENT
1270 if progress_percent <= PACKAGE_PROGRESS_PERCENT_TOTAL:
1271 gobject.idle_add(progressdialog_progress,
1272 progress_percent, pkg_count, total_pkg_count)
1273 while gtk.events_pending():
1274 gtk.main_iteration(False)
1275 pkg_count += 1
1276
1277 #speedup hack, check only last package
1278 already_in_model = \
1279 self.check_if_pkg_have_row_in_model(pkg, p_pkg)
1280 if not already_in_model: #Create new row
1281 available_version = None
1282 version_installed = None
1283 status_icon = None
1284 fmris = [pkg, ]
1285 package_installed = \
1286 self.get_installed_version(image_obj, pkg)
1287 if package_installed:
1288 version_installed = \
1289 package_installed.version.get_short_version()
1290 #HACK, sometimes the package is installed but
1291 #it's not in the pkgs_known
1292 if package_installed != pkg:
1293 fmris.append(package_installed)
1294 else:
1295 dt = self.get_datetime(pkg.version)
1296 dt_str = (":%02d%02d") % (dt.month, dt.day)
1297 available_version = \
1298 pkg.version.get_short_version() + dt_str
1299 package_icon = self.__get_pixbuf_from_path(icon_path, \
1300 pkg.get_name())
1301 app = \
1302 [
1303 False, status_icon, package_icon, pkg.get_name(),
1304 version_installed, package_installed,
1305 available_version, -1, '...', fmris,
1306 image_obj, True, None
1307 ]
1308 # XXX Small hack, if this is not applied, first package
1309 # is listed twice. Insert is ~0.5 sec faster than append
1310 if insert_count == 0:
1311 row_iter = self.application_list.append(app)
1312 else:
1313 row_iter = \
1314 self.application_list.insert(insert_count, \
1315 app)
1316 # XXX Do not iterate through all the catalogs. Package
1317 # should know what is package fmri prefix?
1318 apc = self.__add_package_to_category
1319 for cat in categories:
1320 if cat in categories:
1321 name = pkg.get_name()
1322 if name in categories[cat]:
1323 pkg_categories = \
1324 categories[cat][ \
1325 name]
1326 for pcat in \
1327 pkg_categories.split(","):
1328 if pcat:
1329 apc(self._( \
1330 pcat), None \
1331 , None, \
1332 row_iter)
1333 insert_count = insert_count + 1
1334 p_pkg_iter = row_iter
1335 p_pkg = pkg #The current become previous
1336 else:
1337 # XXX check versions in here. For all installed/not
1338 # installed:
1339 # if there is newer version, put it in the available
1340 # field.
1341 #
1342 # XXXhack, since image_get_version_installed(pkg) is not
1343 # working,as it should. For example package:
1344 # SUNWarc@0.5.11,5.11-0.79:20080205T152309Z
1345 # is not installed and it's newer version of installed
1346 # package:
1347 # SUNWarc@0.5.11,5.11-0.75:20071114T201151Z
1348 # the function returns only proper installed version for
1349 # the older package and None for the newer.
1350 # The hack is a little bit slow since we are iterating
1351 # for all known packages
1352 list_of_pkgs = \
1353 self.application_list.get_value(p_pkg_iter, \
1354 enumerations.PACKAGE_OBJECT_COLUMN)
1355 if pkg not in list_of_pkgs:
1356 list_of_pkgs.append(pkg)
1357 installed = self.application_list.get_value(p_pkg_iter, \
1358 enumerations.INSTALLED_OBJECT_COLUMN)
1359 latest = max(list_of_pkgs)
1360 dt = self.get_datetime(latest.version)
1361 dt_str = (":%02d%02d") % (dt.month, dt.day)
1362 if not installed:
1363 self.application_list.set_value(p_pkg_iter, \
1364 enumerations.LATEST_AVAILABLE_COLUMN, \
1365 latest.version.get_short_version() + \
1366 dt_str)
1367 else:
1368 if installed < latest:
1369 self.application_list.set_value( \
1370 p_pkg_iter, \
1371 enumerations. \
1372 LATEST_AVAILABLE_COLUMN, \
1373 latest.version.get_short_version() + \
1374 dt_str)
1375 self.application_list.set_value(\
1376 p_pkg_iter, \
1377 enumerations.STATUS_ICON_COLUMN, \
1378 update_available_icon)
1379 # XXX How to get descriptions without manifest?
1380 # XXX Downloading manifest is slow and can not work without
1381 # XXX Network connection
1382 #if not image_obj.has_manifest(pkg):
1383 # image_obj.get_manifest(pkg)#verify(pkg, pr)
1384 #installed_version = None
1385 #package_iter = None #the iterator which points for other package
1386 for authority in sections:
1387 for section in sections[authority]:
1388 for category in sections[authority][section].split(","):
1389 self.__add_category_to_section(self._(category), \
1390 self._(section))
1391
1392 #1915 Sort the Categories into alphabetical order and prepend All Category
1393 if len(self.category_list) > 0:
1394 rows = [tuple(r) + (i,) for i, r in enumerate(self.category_list)]
1395 rows.sort(self.__sort)
1396 self.category_list.reorder([r[-1] for r in rows])
1397 self.category_list.prepend([0, self._('All'), None, None, True, None])
1398
1399 gobject.idle_add(progressdialog_progress, PACKAGE_PROGRESS_PERCENT_TOTAL,
1400 pkg_count, total_pkg_count)
1401
1402 def __add_package_to_category(self, category_name, category_description, \
1403 category_icon, package):
1404 if not package or category_name == self._('All'):
1405 return
1406 if not category_name:
1407 return
1408 # XXX check if needed
1409 # category_name = self._('All')
1410 # category_description = self._('All packages')
1411 # category_icon = None
1412 category_ref = None
1413 for category in self.category_list:
1414 if category[enumerations.CATEGORY_NAME] == category_name:
1415 category_ref = category.iter
1416 if not category_ref: # Category not exists
1417 category_ref = self.category_list.append([len( \
1418 self.category_list), category_name, category_description, \
1419 category_icon, True, None])
1420 if category_ref:
1421 if self.application_list.get_value(package, \
1422 enumerations.CATEGORY_LIST_OBJECT):
1423 a = self.application_list.get_value(package, \
1424 enumerations.CATEGORY_LIST_OBJECT)
1425 a.append(category_ref)
1426 else:
1427 category_list = []
1428 category_list.append(category_ref)
1429 self.application_list.set(package, \
1430 enumerations.CATEGORY_LIST_OBJECT, category_list)
1431
1432 def __add_category_to_section(self, category_name, section_name):
1433 '''Adds the section to section list in category. If there is no such
1434 section, than it is not added. If there was already section than it
1435 is skipped. Sections must be case sensitive'''
1436 if not category_name:
1437 return
1438 for section in self.section_list:
1439 if section[enumerations.SECTION_NAME] == section_name:
1440 for category in self.category_list:
1441 if category[enumerations.CATEGORY_NAME] == \
1442 category_name:
1443 if not category[ \
1444 enumerations.SECTION_LIST_OBJECT]:
1445 category[ \
1446 enumerations. \
1447 SECTION_LIST_OBJECT] = \
1448 [section[ \
1449 enumerations.SECTION_ID], ]
1450 else:
1451 if not section_name in \
1452 category[ \
1453 enumerations. \
1454 SECTION_LIST_OBJECT]:
1455 category[enumerations. \
1456 SECTION_LIST_OBJECT \
1457 ].append(section[ \
1458 enumerations. \
1459 SECTION_ID])
1460
1461 def __get_pixbuf_from_path(self, path, icon_name):
1462 icon = icon_name.replace(' ', '_')
1463
1464 # Performance: Faster to check if files exist rather than catching
1465 # exceptions when they do not. Picked up open failures using dtrace
1466 png_exists = os.path.exists(self.application_dir + path + icon + ".png")
1467 svg_exists = os.path.exists(self.application_dir + path + icon + ".svg")
1468
1469 if not png_exists and not svg_exists:
1470 return None
1471 try:
1472 return gtk.gdk.pixbuf_new_from_file( \
1473 self.application_dir + path + icon + ".png")
1474 except gobject.GError:
1475 try:
1476 return gtk.gdk.pixbuf_new_from_file( \
1477 self.application_dir + path + icon + ".svg")
1478 except gobject.GError:
1479 iconview = gtk.IconView()
1480 icon = iconview.render_icon(getattr(gtk, \
1481 "STOCK_MISSING_IMAGE"), \
1482 size = gtk.ICON_SIZE_MENU,
1483 detail = None)
1484 # XXX Could return image-we don't want to show ugly icon.
1485 return None
1486
1487 def __installed_fmris_from_args(self, img, args):
1488 found = []
1489 notfound = []
1490 try:
1491 for m in img.inventory(args):
1492 found.append(m[0])
1493 except image.InventoryException, e:
1494 notfound = e.notfound
1495
1496 return found, notfound
1497
1498 def __progressdialog_progress_pulse(self):
1499 while not self.progress_stop_timer_thread:
1500 gobject.idle_add(self.w_progressbar.pulse)
1501 time.sleep(0.1)
1502 gobject.idle_add(self.w_progress_dialog.hide)
1503 self.progress_stop_timer_thread = False
1504
1505 # For initial setup before loading package entries allow 5% of progress bar
1506 # update it on a time base as we have no other way to judge progress at this point
1507 def __progressdialog_progress_time(self):
1508 while not self.progress_stop_timer_thread and \
1509 self.progress_fraction_time_count <= \
1510 INITIAL_PROGRESS_TOTAL_PERCENTAGE:
1511
1512 gobject.idle_add(self.w_progressbar.set_fraction, \
1513 self.progress_fraction_time_count)
1514 self.progress_fraction_time_count += \
1515 INITIAL_PROGRESS_TIME_PERCENTAGE
1516 time.sleep(INITIAL_PROGRESS_TIME_INTERVAL)
1517 self.progress_stop_timer_thread = False
1518 self.progress_fraction_time_count = 0
1519
1520 def __progressdialog_progress_percent(self, fraction, count, total):
1521 gobject.idle_add(self.w_progressinfo_label.set_text, self._( \
1522 "Processing package entries: %d of %d" % (count, total) ))
1523 gobject.idle_add(self.w_progressbar.set_fraction, fraction)
1524
1525 def __setup_data_finished(self):
1526 gobject.idle_add(self.w_progress_dialog.hide)
1527 self.in_setup = False
1528
1529 #-----------------------------------------------------------------------------#
1530 # Static Methods
1531 #-----------------------------------------------------------------------------#
1532
1533 @staticmethod
1534 def n_(message):
1535 return message
1536
1537 @staticmethod
1538 def __sort(a, b):
1539 return cmp(a[1], b[1])
1540
1541 @staticmethod
1542 def cell_data_function(column, renderer, model, itr, data):
1543 '''Function which sets the background colour to black if package is
1544 selected'''
1545 if itr:
1546 if model.get_value(itr, enumerations.MARK_COLUMN):
1547 renderer.set_property("cell-background", "#ffe5cc")
1548 renderer.set_property("cell-background-set", True)
1549 else:
1550 renderer.set_property("cell-background-set", False)
1551
1552 @staticmethod
1553 def combobox_separator(model, itr):
1554 return model.get_value(itr, enumerations.FILTER_NAME) == ""
1555
1556 @staticmethod
1557 def combobox_id_separator(model, itr):
1558 return model.get_value(itr, 0) == -1
1559
1560 @staticmethod
1561 def check_if_pkg_have_row_in_model(pkg, p_pkg):
1562 """Returns True if package is already in model or False if not"""
1563 if p_pkg:
1564 if pkg.is_same_pkg(p_pkg):
1565 return True
1566 else:
1567 return False
1568 return False
1569
1570 @staticmethod
1571 def category_filter(model, itr):
1572 '''This function filters category in the main application view'''
1573 return model.get_value(itr, enumerations.CATEGORY_VISIBLE)
1574
1575 @staticmethod
1576 def get_datetime(version):
1577 dt = None
1578 try:
1579 dt = version.get_datetime()
1580 except AttributeError:
1581 dt = version.get_timestamp()
1582 return dt
1583
1584 @staticmethod
1585 def get_installed_version(img, pkg):
1586 if not img.has_version_installed(pkg):
1587 return None
1588 else:
1589 img_ret = None
1590 try:
1591 img_ret = img.get_version_installed(pkg)
1592 except AttributeError:
1593 img_ret = img._get_version_installed(pkg)
1594 return img_ret
1595
1596 @staticmethod
1597 def get_manifest(img, package, filtered = True):
1598 '''helper function'''
1599 # XXX Should go to the -> imageinfo.py
1600 manifest = None
1601
1602 # 3087 shutdown time is too long when closing down soon after startup
1603 if packagemanager.cancelled:
1604 return manifest
1605 try:
1606 manifest = img.get_manifest(package, filtered)
1607 except OSError:
1608 # XXX It is possible here that the user doesn't have network con,
1609 # XXX proper permissions to save manifest, should we do something
1610 # XXX and popup information dialog?
1611 pass
1612 except NameError:
1613 pass
1614 return manifest
1615
1616 @staticmethod
1617 def update_desc(description, pkg, package):
1618 p = pkg[enumerations.PACKAGE_OBJECT_COLUMN][0]
1619 if p == package:
1620 pkg[enumerations.DESCRIPTION_COLUMN] = description
1621 return
1622
1623 #-----------------------------------------------------------------------------#
1624 # Public Methods
1625 #-----------------------------------------------------------------------------#
1626 def setup_progressdialog_show(self):
1627 self.w_progress_dialog.set_title(self._("Loading Repository Information"))
1628 self.w_progressinfo_label.set_text(
1629 self._( "Fetching package entries ..."))
1630 self.w_progress_cancel.hide()
1631
1632 Thread(target = self.w_progress_dialog.run).start()
1633 Thread(target = self.__progressdialog_progress_time).start()
1634
1635 def init_sections(self):
1636 self.__init_sections() #Initiates sections
1637
1638 def process_package_list_start(self, image_directory):
1639 self.image_directory = image_directory
1640 # Create our image object based on image directory.
1641 image_obj = self.__get_image_obj_from_directory(image_directory)
1642 self.image_o = image_obj
1643
1644 # Acquire image contents and update progress bar as you do so.
1645 self.__get_image_from_directory(image_obj,
1646 self.__progressdialog_progress_percent)
1647 while gtk.events_pending():
1648 gtk.main_iteration(False)
1649
1650 def init_package_view(self):
1651 self.__init_show_filter()
1652 self.__setup_data_finished()
1653 self.__init_tree_views()
1654
1655 self.w_filter_combobox.set_active(0)
1656 self.w_sections_combobox.set_active(0)
1657 self.application_list_filter.set_visible_func(self.__application_filter)
1658 self.__setup_repositories_combobox(self.image_o)
1659
1660 def get_icon_pixbuf(self, icon_name):
1661 #2821: The get_icon_pixbuf should use PACKAGE_MANAGER_ROOT
1662 return self.__get_pixbuf_from_path(self.application_dir + \
1663 "/usr/share/icons/package-manager/", icon_name)
1664
1665 def get_manifests_for_packages(self):
1666 ''' Function, which get's manifest for packages. If the manifest is not
1667 locally tries to retrieve it. For installed packages gets manifest
1668 for the particular version (local operation only), if the package is
1669 not installed than the newest one'''
1670 self.description_thread_running = True
1671 for pkg in self.application_list:
1672 if self.cancelled:
1673 self.description_thread_running = False
1674 return
1675 info = None
1676 img = pkg[enumerations.IMAGE_OBJECT_COLUMN]
1677 package = pkg[enumerations.PACKAGE_OBJECT_COLUMN][0]
1678 if (img and package):
1679 version = img.has_version_installed(package)
1680 if version:
1681 version = self.get_installed_version(img, \
1682 package)
1683 man = self.get_manifest(img, version, \
1684 filtered = True)
1685 if man:
1686 info = man.get("description", "")
1687 else:
1688 newest = max( \
1689 pkg[enumerations.PACKAGE_OBJECT_COLUMN])
1690 man = self.get_manifest(img, newest, \
1691 filtered = True)
1692 if man:
1693 info = man.get("description", "")
1694 # XXX workaround, this should be done nicer
1695 gobject.idle_add(self.update_desc, info, pkg, package)
1696 time.sleep(0.01)
1697 self.description_thread_running = False
1698
1699 def update_statusbar(self):
1700 '''Function which updates statusbar'''
1701 installed = 0
1702 selected = 0
1703 broken = 0
1704 for pkg in self.application_list:
1705 if pkg[enumerations.INSTALLED_VERSION_COLUMN]:
1706 installed = installed + 1
1707 if pkg[enumerations.MARK_COLUMN]:
1708 selected = selected + 1
1709 listed_str = self._('%d packages listed') % len(self.application_list)
1710 inst_str = self._('%d installed') % installed
1711 sel_str = self._('%d selected') % selected
1712 broken_str = self._('%d broken') % broken
1713 self.w_main_statusbar.push(0, listed_str + ', ' + inst_str + ', ' + \
1714 sel_str + ', ' + broken_str + '.')
1715
1716
1717 def update_package_list(self):
1718 for row in self.application_list:
1719 if row[enumerations.MARK_COLUMN]:
1720 img = row[enumerations.IMAGE_OBJECT_COLUMN]
1721 pkg = row[enumerations.PACKAGE_OBJECT_COLUMN][0]
1722 package_installed = self.get_installed_version(img, pkg)
1723 version_installed = None
1724 if package_installed:
1725 version_installed = \
1726 package_installed.version.get_short_version()
1727 row[enumerations.MARK_COLUMN] = False
1728 row[enumerations.STATUS_ICON_COLUMN] = None
1729 row[enumerations.INSTALLED_VERSION_COLUMN] = \
1730 version_installed
1731 row[enumerations.INSTALLED_OBJECT_COLUMN] = \
1732 package_installed
1733 if not package_installed:
1734 pkg = max(row[enumerations.PACKAGE_OBJECT_COLUMN])
1735 dt = self.get_datetime(pkg.version)
1736 dt_str = (":%02d%02d") % (dt.month, dt.day)
1737 available_version = \
1738 pkg.version.get_short_version() + dt_str
1739 row[enumerations.LATEST_AVAILABLE_COLUMN] = \
1740 available_version
1741 else:
1742 row[enumerations.LATEST_AVAILABLE_COLUMN] = None
1743 self.w_installupdate_button.set_sensitive(False)
1744 self.w_installupdate_menuitem.set_sensitive(False)
1745 self.w_remove_button.set_sensitive(False)
1746 self.w_remove_menuitem.set_sensitive(False)
1747 self.__enable_disable_selection_menus()
1748 self.update_statusbar()
1749
1750 def shutdown_after_ips_update(self):
1751
1752 # 2790: As IPS and IPS-GUI have been updated the IPS GUI must be shutdown
1753 # and restarted
1754 msgbox = gtk.MessageDialog(parent = self.w_main_window, \
1755 buttons = gtk.BUTTONS_OK, \
1756 flags = gtk.DIALOG_MODAL, type = gtk.MESSAGE_INFO, \
1757 message_format = self._("SUNWipkg and SUNWipkg-gui have been" + \
1758 "updated and Package Manager will now be restarted.\n\nAfter" + \
1759 "restart select Update All to continue."))
1760 msgbox.set_title(self._("Update All"))
1761 msgbox.run()
1762 msgbox.destroy()
1763 self.__main_application_quit(restart_app = True)
1764
1765 def shutdown_after_image_update(self):
1766
1767 msgbox = gtk.MessageDialog(parent = self.w_main_window, \
1768 buttons = gtk.BUTTONS_OK, \
1769 flags = gtk.DIALOG_MODAL, type = gtk.MESSAGE_INFO, \
1770 message_format = self._("Update All has completed and Package" + \
1771 "Manager will now exit.\n\nPlease review posted release notes" + \
1772 "before rebooting:\n\n" + \
1773 " http://opensolaris.org/os/project/indiana/resources/rn3/"))
1774 msgbox.set_title(self._("Update All"))
1775 msgbox.run()
1776 msgbox.destroy()
1777 self.__main_application_quit()
1778
1779 ###############################################################################
1780 #-----------------------------------------------------------------------------#
1781 # Test functions
1782 #-----------------------------------------------------------------------------#
1783 def fill_with_fake_data(self):
1784 '''test data for gui'''
1785 app1 = [False, self.get_icon_pixbuf("locked"), \
1786 self.get_icon_pixbuf("None"), "acc", None, None, None, 4, "desc6", \
1787 "Object Name1", None, True, None]
1788 app2 = [False, self.get_icon_pixbuf("update_available"), \
1789 self.get_icon_pixbuf(self._('All')), "acc_gam", \
1790 "2.3", None, "2.8", \
1791 4, "desc7", "Object Name2", None, True, None]
1792 app3 = [False, self.get_icon_pixbuf("None"), \
1793 self.get_icon_pixbuf("Other"), "gam_grap", "2.3", None, None, 4, \
1794 "desc8", "Object Name3", None, True, None]
1795 app4 = [False, self.get_icon_pixbuf("update_locked"), \
1796 self.get_icon_pixbuf("Office"), "grap_gam", "2.3", None, "2.8", 4, \
1797 "desc9", "Object Name2", None, True, None]
1798 app5 = [False, self.get_icon_pixbuf("update_available"), \
1799 self.get_icon_pixbuf("None"), "grap", "2.3", None, "2.8", 4, \
1800 "desc0", "Object Name3", None, True, None]
1801 itr1 = self.application_list.append(app1)
1802 itr2 = self.application_list.append(app2)
1803 itr3 = self.application_list.append(app3)
1804 itr4 = self.application_list.append(app4)
1805 itr5 = self.application_list.append(app5)
1806 # self.__add_package_to_category(_("All"),None,None,None);
1807 self.__add_package_to_category(self._("Accessories"), None, None, itr1)
1808 self.__add_package_to_category(self._("Accessories"), None, None, itr2)
1809 self.__add_package_to_category(self._("Games"), None, None, itr3)
1810 self.__add_package_to_category(self._("Graphics"), None, None, itr3)
1811 self.__add_package_to_category(self._("Games"), None, None, itr2)
1812 self.__add_package_to_category(self._("Graphics"), None, None, itr4)
1813 self.__add_package_to_category(self._("Games"), None, None, itr4)
1814 self.__add_package_to_category(self._("Graphics"), None, None, itr5)
1815
1816 # Category names until xdg is imported.
1817 # from xdg.DesktopEntry import *
1818 # entry = DesktopEntry ()
1819 # directory = '/usr/share/desktop-directories'
1820 # for root, dirs, files in os.walk (directory):
1821 # for name in files:
1822 # entry.parse (os.path.join (root, name))
1823 # self.__add_category_to_section (entry.getName (), \
1824 # self._('Applications Desktop'))
1825
1826 self.__add_category_to_section(self._("Accessories"), \
1827 self._('Applications Desktop'))
1828 self.__add_category_to_section(self._("Games"), \
1829 self._('Applications Desktop'))
1830 self.__add_category_to_section(self._("Graphics"), \
1831 self._('Applications Desktop'))
1832 self.__add_category_to_section(self._("Internet"), \
1833 self._('Applications Desktop'))
1834 self.__add_category_to_section(self._("Office"), \
1835 self._('Applications Desktop'))
1836 self.__add_category_to_section(self._("Sound & Video"), \
1837 self._('Applications Desktop'))
1838 self.__add_category_to_section(self._("System Tools"), \
1839 self._('Applications Desktop'))
1840 self.__add_category_to_section(self._("Universal Access"), \
1841 self._('Applications Desktop'))
1842 self.__add_category_to_section(self._("Developer Tools"), \
1843 self._('Applications Desktop'))
1844 self.__add_category_to_section(self._("Core"), self._('Operating System'))
1845 self.__add_category_to_section(self._("Graphics"), \
1846 self._('Operating System'))
1847 self.__add_category_to_section(self._("Media"), \
1848 self._('Operating System'))
1849 #Can be twice :)
1850 self.__add_category_to_section(self._("Developer Tools"), \
1851 self._('Operating System'))
1852 self.__add_category_to_section(self._("Office"), "Progs")
1853 self.__add_category_to_section(self._("Office2"), "Progs")
1854 self.__setup_repositories_combobox(self.image_o)
1855 self.in_setup = False
1856
1857 ###############################################################################
1858 #-----------------------------------------------------------------------------#
1859 # Main
1860 #-----------------------------------------------------------------------------#
1861
1862 def main():
1863 gtk.main()
1864 return 0
1865
1866 if __name__ == '__main__':
1867 packagemanager = PackageManager()
1868 passed_test_arg = False
1869 passed_imagedir_arg = False
1870
1871 try:
1872 opts, args = getopt.getopt(sys.argv[1:], "htR:", \
1873 ["help", "test-gui", "image-dir="])
1874 except getopt.error, msg:
1875 print "%s, for help use --help" % msg
1876 sys.exit(2)
1877
1878 cmd = os.path.join(os.getcwd(), sys.argv[0])
1879 cmd = os.path.realpath(cmd)
1880 packagemanager.application_path = cmd
1881
1882 for option, argument in opts:
1883 if option in ("-h", "--help"):
1884 print """\
1885 Use -R (--image-dir) to specify image directory.
1886 Use -t (--test-gui) to work on fake data."""
1887 sys.exit(0)
1888 if option in ("-t", "--test-gui"):
1889 passed_test_arg = True
1890 if option in ("-R", "--image-dir"):
1891 packagemanager.image_dir_arg = argument
1892 image_dir = argument
1893 passed_imagedir_arg = True
1894
1895 if passed_test_arg and passed_imagedir_arg:
1896 print "Options -R and -t can not be used together."
1897 sys.exit(2)
1898 if not passed_imagedir_arg:
1899 try:
1900 image_dir = os.environ["PKG_IMAGE"]
1901 except KeyError:
1902 image_dir = os.getcwd()
1903
1904 if not passed_test_arg:
1905 packagemanager.setup_progressdialog_show()
1906 packagemanager.init_sections()
1907 packagemanager.process_package_list_start(image_dir)
1908 else:
1909 packagemanager.init_sections()
1910 packagemanager.fill_with_fake_data()
1911
1912 packagemanager.init_package_view()
1913 packagemanager.update_statusbar()
1914 while gtk.events_pending():
1915 gtk.main_iteration(False)
1916
1917 # Performance: Start this background thread after progress dialog thread has
1918 # completed in init_package_view()->self.__setup_data_finished() or GUI will block
1919 if not passed_test_arg:
1920 Thread(target = packagemanager.get_manifests_for_packages,
1921 args = ()).start()
1922 main()