21 # |
21 # |
22 # Copyright 2009 Sun Microsystems, Inc. All rights reserved. |
22 # Copyright 2009 Sun Microsystems, Inc. All rights reserved. |
23 # Use is subject to license terms. |
23 # Use is subject to license terms. |
24 # |
24 # |
25 |
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 # 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 MAX_DESC_LEN = 60 # Max length of the description |
26 MAX_DESC_LEN = 60 # Max length of the description |
41 MAX_INFO_CACHE_LIMIT = 100 # Max number of package descriptions to cache |
27 MAX_INFO_CACHE_LIMIT = 100 # Max number of package descriptions to cache |
42 NOTEBOOK_PACKAGE_LIST_PAGE = 0 # Main Package List page index |
28 NOTEBOOK_PACKAGE_LIST_PAGE = 0 # Main Package List page index |
43 NOTEBOOK_START_PAGE = 1 # Main View Start page index |
29 NOTEBOOK_START_PAGE = 1 # Main View Start page index |
44 INFO_NOTEBOOK_LICENSE_PAGE = 3 # License Tab index |
30 INFO_NOTEBOOK_LICENSE_PAGE = 3 # License Tab index |
216 self.application_dir, |
202 self.application_dir, |
217 "usr/share/locale")) |
203 "usr/share/locale")) |
218 module.textdomain("pkg") |
204 module.textdomain("pkg") |
219 gui_misc.init_for_help(self.application_dir) |
205 gui_misc.init_for_help(self.application_dir) |
220 self.main_window_title = _('Package Manager') |
206 self.main_window_title = _('Package Manager') |
|
207 self.gdk_window = None |
221 self.user_rights = portable.is_admin() |
208 self.user_rights = portable.is_admin() |
222 self.cancelled = False # For background processes |
209 self.cancelled = False # For background processes |
223 self.image_directory = None |
210 self.image_directory = None |
224 self.description_thread_running = False # For background processes |
211 self.description_thread_running = False # For background processes |
225 gtk.rc_parse('~/.gtkrc-1.2-gnome2') # Load gtk theme |
212 gtk.rc_parse('~/.gtkrc-1.2-gnome2') # Load gtk theme |
226 self.progress_stop_timer_thread = False |
213 self.progress_stop_thread = True |
227 self.progress_fraction_time_count = 0 |
|
228 self.progress_canceled = False |
|
229 self.catalog_loaded = False |
214 self.catalog_loaded = False |
230 self.image_dir_arg = None |
215 self.image_dir_arg = None |
231 self.update_all_proceed = False |
216 self.update_all_proceed = False |
232 self.ua_be_name = None |
217 self.ua_be_name = None |
233 self.application_path = None |
218 self.application_path = None |
299 |
284 |
300 # Create Widgets and show gui |
285 # Create Widgets and show gui |
301 self.gladefile = os.path.join(self.application_dir, |
286 self.gladefile = os.path.join(self.application_dir, |
302 "usr/share/package-manager/packagemanager.glade") |
287 "usr/share/package-manager/packagemanager.glade") |
303 w_tree_main = gtk.glade.XML(self.gladefile, "mainwindow") |
288 w_tree_main = gtk.glade.XML(self.gladefile, "mainwindow") |
304 w_tree_progress = gtk.glade.XML(self.gladefile, "progressdialog") |
|
305 w_tree_preferences = gtk.glade.XML(self.gladefile, "preferencesdialog") |
289 w_tree_preferences = gtk.glade.XML(self.gladefile, "preferencesdialog") |
306 w_tree_api_search_error = gtk.glade.XML(self.gladefile, |
290 w_tree_api_search_error = gtk.glade.XML(self.gladefile, |
307 "api_search_error") |
291 "api_search_error") |
308 self.w_preferencesdialog = \ |
292 self.w_preferencesdialog = \ |
309 w_tree_preferences.get_widget("preferencesdialog") |
293 w_tree_preferences.get_widget("preferencesdialog") |
352 w_tree_main.get_widget("startpage_eventbox") |
336 w_tree_main.get_widget("startpage_eventbox") |
353 self.w_startpage_eventbox.modify_bg(gtk.STATE_NORMAL, |
337 self.w_startpage_eventbox.modify_bg(gtk.STATE_NORMAL, |
354 gtk.gdk.color_parse("white")) |
338 gtk.gdk.color_parse("white")) |
355 |
339 |
356 self.w_main_statusbar = w_tree_main.get_widget("statusbar") |
340 self.w_main_statusbar = w_tree_main.get_widget("statusbar") |
|
341 self.w_statusbar_hbox = w_tree_main.get_widget("statusbar_hbox") |
357 self.w_infosearch_frame = w_tree_main.get_widget("infosearch_frame") |
342 self.w_infosearch_frame = w_tree_main.get_widget("infosearch_frame") |
358 self.w_infosearch_button = w_tree_main.get_widget("infosearch_button") |
343 self.w_infosearch_button = w_tree_main.get_widget("infosearch_button") |
|
344 |
|
345 self.w_progress_frame = w_tree_main.get_widget("progress_frame") |
|
346 self.w_status_progressbar = w_tree_main.get_widget("status_progressbar") |
|
347 self.w_status_progressbar.set_pulse_step(0.1) |
|
348 self.w_progress_frame.hide() |
359 |
349 |
360 self.w_main_view_notebook = \ |
350 self.w_main_view_notebook = \ |
361 w_tree_main.get_widget("main_view_notebook") |
351 w_tree_main.get_widget("main_view_notebook") |
362 self.w_searchentry = w_tree_main.get_widget("searchentry") |
352 self.w_searchentry = w_tree_main.get_widget("searchentry") |
363 self.entry_embedded_icons_supported = True |
353 self.entry_embedded_icons_supported = True |
387 self.w_selectupdates_menuitem = \ |
377 self.w_selectupdates_menuitem = \ |
388 w_tree_main.get_widget("edit_select_updates") |
378 w_tree_main.get_widget("edit_select_updates") |
389 self.w_deselect_menuitem = w_tree_main.get_widget("edit_deselect") |
379 self.w_deselect_menuitem = w_tree_main.get_widget("edit_deselect") |
390 self.w_clear_search_menuitem = w_tree_main.get_widget("clear") |
380 self.w_clear_search_menuitem = w_tree_main.get_widget("clear") |
391 self.w_main_clipboard = gtk.clipboard_get(gtk.gdk.SELECTION_CLIPBOARD) |
381 self.w_main_clipboard = gtk.clipboard_get(gtk.gdk.SELECTION_CLIPBOARD) |
392 self.w_progress_dialog = w_tree_progress.get_widget("progressdialog") |
|
393 self.w_progress_dialog.connect('delete-event', lambda stub1, stub2: True) |
|
394 self.w_progress_dialog.set_title(_("Update All")) |
|
395 self.w_progressinfo_label = w_tree_progress.get_widget("progressinfo") |
|
396 self.w_progressinfo_label.set_text(_( |
|
397 "Checking SUNWipkg and SUNWipkg-gui versions\n\nPlease wait ...")) |
|
398 self.w_progressbar = w_tree_progress.get_widget("progressbar") |
|
399 self.w_progressbar.set_pulse_step(0.1) |
|
400 self.w_progress_cancel = w_tree_progress.get_widget("progresscancel") |
|
401 self.progress_canceled = False |
|
402 self.saved_filter_combobox_active = self.initial_show_filter |
382 self.saved_filter_combobox_active = self.initial_show_filter |
403 self.search_image = w_tree_main.get_widget("search_image") |
383 self.search_image = w_tree_main.get_widget("search_image") |
404 self.search_button = w_tree_main.get_widget("do_search") |
384 self.search_button = w_tree_main.get_widget("do_search") |
|
385 self.progress_cancel = w_tree_main.get_widget("progress_cancel") |
405 self.is_all_publishers = False |
386 self.is_all_publishers = False |
406 self.search_image.set_from_pixbuf(gui_misc.get_icon(self.icon_theme, |
387 self.search_image.set_from_pixbuf(gui_misc.get_icon(self.icon_theme, |
407 'search', 20)) |
388 'search', 20)) |
408 self.saved_repository_combobox_active = 0 |
389 self.saved_repository_combobox_active = 0 |
409 self.saved_sections_combobox_active = 0 |
390 self.saved_sections_combobox_active = 0 |
445 try: |
426 try: |
446 dic_mainwindow = \ |
427 dic_mainwindow = \ |
447 { |
428 { |
448 "on_mainwindow_delete_event": \ |
429 "on_mainwindow_delete_event": \ |
449 self.__on_mainwindow_delete_event, |
430 self.__on_mainwindow_delete_event, |
|
431 "on_mainwindow_check_resize": \ |
|
432 self.__on_mainwindow_check_resize, |
450 "on_mainwindow_key_press_event": \ |
433 "on_mainwindow_key_press_event": \ |
451 self.__on_mainwindow_key_press_event, |
434 self.__on_mainwindow_key_press_event, |
452 "on_searchentry_changed":self.__on_searchentry_changed, |
435 "on_searchentry_changed":self.__on_searchentry_changed, |
453 "on_searchentry_focus_in_event": \ |
436 "on_searchentry_focus_in_event": \ |
454 self.__on_searchentry_focus_in, |
437 self.__on_searchentry_focus_in, |
479 "on_edit_search_activate":self.__on_edit_search_clicked, |
462 "on_edit_search_activate":self.__on_edit_search_clicked, |
480 "on_clear_search_activate":self.__on_clear_search, |
463 "on_clear_search_activate":self.__on_clear_search, |
481 "on_clear_search_clicked":self.__on_clear_search, |
464 "on_clear_search_clicked":self.__on_clear_search, |
482 "on_do_search_clicked":self.__do_search, |
465 "on_do_search_clicked":self.__do_search, |
483 "on_do_search_button_press_event":self.__do_search, |
466 "on_do_search_button_press_event":self.__do_search, |
|
467 "on_progress_cancel_clicked": \ |
|
468 self.__on_progress_cancel_clicked, |
484 "on_edit_select_all_activate":self.__on_select_all, |
469 "on_edit_select_all_activate":self.__on_select_all, |
485 "on_edit_select_updates_activate": \ |
470 "on_edit_select_updates_activate": \ |
486 self.__on_select_updates, |
471 self.__on_select_updates, |
487 "on_edit_deselect_activate":self.__on_deselect, |
472 "on_edit_deselect_activate":self.__on_deselect, |
488 "on_edit_preferences_activate":self.__on_preferences, |
473 "on_edit_preferences_activate":self.__on_preferences, |
498 "on_help_start_page_activate":self.__on_startpage, |
483 "on_help_start_page_activate":self.__on_startpage, |
499 "on_details_notebook_switch_page": \ |
484 "on_details_notebook_switch_page": \ |
500 self.__on_notebook_change, |
485 self.__on_notebook_change, |
501 "on_infosearch_button_clicked": \ |
486 "on_infosearch_button_clicked": \ |
502 self.__on_infosearch_button_clicked, |
487 self.__on_infosearch_button_clicked, |
503 } |
|
504 dic_progress = \ |
|
505 { |
|
506 "on_cancel_progressdialog_clicked": \ |
|
507 self.__on_cancel_progressdialog_clicked, |
|
508 } |
488 } |
509 dic_preferences = \ |
489 dic_preferences = \ |
510 { |
490 { |
511 "on_startpage_checkbutton_toggled": \ |
491 "on_startpage_checkbutton_toggled": \ |
512 self.__on_startpage_checkbutton_toggled, |
492 self.__on_startpage_checkbutton_toggled, |
533 } |
513 } |
534 w_xmltree_ua_completed.signal_autoconnect(dic_completed) |
514 w_xmltree_ua_completed.signal_autoconnect(dic_completed) |
535 |
515 |
536 |
516 |
537 w_tree_main.signal_autoconnect(dic_mainwindow) |
517 w_tree_main.signal_autoconnect(dic_mainwindow) |
538 w_tree_progress.signal_autoconnect(dic_progress) |
|
539 w_tree_preferences.signal_autoconnect(dic_preferences) |
518 w_tree_preferences.signal_autoconnect(dic_preferences) |
540 w_tree_api_search_error.signal_autoconnect( |
519 w_tree_api_search_error.signal_autoconnect( |
541 dic_api_search_error) |
520 dic_api_search_error) |
542 except AttributeError, error: |
521 except AttributeError, error: |
543 print _( |
522 print _( |
568 self.w_main_window.show_all() |
547 self.w_main_window.show_all() |
569 gdk_win = self.w_main_window.get_window() |
548 gdk_win = self.w_main_window.get_window() |
570 self.gdk_window = gtk.gdk.Window(gdk_win, gtk.gdk.screen_width(), |
549 self.gdk_window = gtk.gdk.Window(gdk_win, gtk.gdk.screen_width(), |
571 gtk.gdk.screen_height(), gtk.gdk.WINDOW_CHILD, 0, gtk.gdk.INPUT_ONLY) |
550 gtk.gdk.screen_height(), gtk.gdk.WINDOW_CHILD, 0, gtk.gdk.INPUT_ONLY) |
572 gdk_cursor = gtk.gdk.Cursor(gtk.gdk.WATCH) |
551 gdk_cursor = gtk.gdk.Cursor(gtk.gdk.WATCH) |
|
552 |
573 self.gdk_window.set_cursor(gdk_cursor) |
553 self.gdk_window.set_cursor(gdk_cursor) |
574 # Until package icons become available hide Package Icon Panel |
554 # Until package icons become available hide Package Icon Panel |
575 w_package_hbox.hide() |
555 w_package_hbox.hide() |
576 if self.show_startpage: |
556 if self.show_startpage: |
577 self.w_main_view_notebook.set_current_page(NOTEBOOK_START_PAGE) |
557 self.w_main_view_notebook.set_current_page(NOTEBOOK_START_PAGE) |
786 if link == None or link == "": |
766 if link == None or link == "": |
787 self.update_statusbar() |
767 self.update_statusbar() |
788 else: |
768 else: |
789 display_link = self.__handle_link(None, link, DISPLAY_LINK) |
769 display_link = self.__handle_link(None, link, DISPLAY_LINK) |
790 if display_link != None: |
770 if display_link != None: |
791 self.w_main_statusbar.push(0, display_link) |
771 self.__update_statusbar_message(display_link) |
792 else: |
772 else: |
793 self.update_statusbar() |
773 self.update_statusbar() |
794 |
774 |
795 @staticmethod |
775 @staticmethod |
796 def __is_relative_to_server(url): |
776 def __is_relative_to_server(url): |
816 # Stub handler required by GtkHtml widget or widget will assert |
796 # Stub handler required by GtkHtml widget or widget will assert |
817 def __stream_cancel(self, *vargs): |
797 def __stream_cancel(self, *vargs): |
818 pass |
798 pass |
819 |
799 |
820 def __load_uri(self, document, link): |
800 def __load_uri(self, document, link): |
821 self.w_main_statusbar.push(0, _("Loading... " + link)) |
801 self.__update_statusbar_message(_("Loading... " + link)) |
822 try: |
802 try: |
823 f = self.__open_url(link) |
803 f = self.__open_url(link) |
824 except (IOError, OSError), err: |
804 except (IOError, OSError), err: |
825 if debug: |
805 if debug: |
826 print "err: %s" % (err) |
806 print "err: %s" % (err) |
827 self.w_main_statusbar.push(0, _("Stopped")) |
807 self.__update_statusbar_message(_("Stopped")) |
828 return False |
808 return False |
829 self.current_url = self.__resolve_uri(link) |
809 self.current_url = self.__resolve_uri(link) |
830 |
810 |
831 self.document.clear() |
811 self.document.clear() |
832 headers = f.info() |
812 headers = f.info() |
836 else: |
816 else: |
837 self.document.open_stream('text/plain') |
817 self.document.open_stream('text/plain') |
838 |
818 |
839 self.document.write_stream(f.read()) |
819 self.document.write_stream(f.read()) |
840 self.document.close_stream() |
820 self.document.close_stream() |
841 self.w_main_statusbar.push(0, _("Done")) |
821 self.__update_statusbar_message(_("Done")) |
842 return True |
822 return True |
843 |
823 |
844 def __link_load_error(self, link): |
824 def __link_load_error(self, link): |
845 self.document.clear() |
825 self.document.clear() |
846 self.document.open_stream('text/html') |
826 self.document.open_stream('text/html') |
1400 pkg_descriptions_for_update, orig_model) |
1380 pkg_descriptions_for_update, orig_model) |
1401 |
1381 |
1402 def __update_description_from_iter(self, pkg_descriptions_for_update, orig_model): |
1382 def __update_description_from_iter(self, pkg_descriptions_for_update, orig_model): |
1403 sort_filt_model = \ |
1383 sort_filt_model = \ |
1404 self.w_application_treeview.get_model() #gtk.TreeModelSort |
1384 self.w_application_treeview.get_model() #gtk.TreeModelSort |
|
1385 if not sort_filt_model: |
|
1386 return |
1405 filt_model = sort_filt_model.get_model() #gtk.TreeModelFilter |
1387 filt_model = sort_filt_model.get_model() #gtk.TreeModelFilter |
1406 model = filt_model.get_model() #gtk.ListStore |
1388 model = filt_model.get_model() #gtk.ListStore |
1407 |
1389 |
1408 #If model has changed abandon description updates |
1390 #If model has changed abandon description updates |
1409 if orig_model != model: |
1391 if orig_model != model: |
1518 if current_length > length_to_check: |
1500 if current_length > length_to_check: |
1519 return current_length |
1501 return current_length |
1520 else: |
1502 else: |
1521 return length_to_check |
1503 return length_to_check |
1522 |
1504 |
1523 def __on_cancel_progressdialog_clicked(self, widget): |
|
1524 self.progress_canceled = True |
|
1525 self.progress_stop_timer_thread = True |
|
1526 |
|
1527 def __on_mainwindow_key_press_event(self, widget, event): |
1505 def __on_mainwindow_key_press_event(self, widget, event): |
1528 if self.is_busy_cursor_set(): |
1506 if self.is_busy_cursor_set(): |
1529 return True |
1507 return True |
1530 else: |
1508 else: |
1531 return False |
1509 return False |
1537 # XXX if some changes were applied: |
1515 # XXX if some changes were applied: |
1538 self.__main_application_quit() |
1516 self.__main_application_quit() |
1539 return True |
1517 return True |
1540 else: |
1518 else: |
1541 self.__main_application_quit() |
1519 self.__main_application_quit() |
|
1520 |
|
1521 def __on_mainwindow_check_resize(self, widget): |
|
1522 if widget and self.gdk_window: |
|
1523 status_height = self.w_statusbar_hbox.get_allocation().height |
|
1524 self.gdk_window.move_resize(0, 0, widget.get_size()[0], |
|
1525 widget.get_size()[1]-status_height) |
1542 |
1526 |
1543 def __on_api_search_error_delete_event(self, widget, event): |
1527 def __on_api_search_error_delete_event(self, widget, event): |
1544 self.__on_api_search_button_clicked(None) |
1528 self.__on_api_search_button_clicked(None) |
1545 |
1529 |
1546 def __on_api_search_button_clicked(self, widget): |
1530 def __on_api_search_button_clicked(self, widget): |
1612 |
1596 |
1613 def __restore_setup_for_browse(self): |
1597 def __restore_setup_for_browse(self): |
1614 self.in_search_mode = False |
1598 self.in_search_mode = False |
1615 self.is_all_publishers = False |
1599 self.is_all_publishers = False |
1616 self.w_infosearch_frame.hide() |
1600 self.w_infosearch_frame.hide() |
1617 |
|
1618 self.set_busy_cursor() |
1601 self.set_busy_cursor() |
1619 self.w_repository_combobox.set_active( |
1602 self.w_repository_combobox.set_active( |
1620 self.saved_repository_combobox_active) |
1603 self.saved_repository_combobox_active) |
1621 self.set_section = self.saved_sections_combobox_active |
1604 self.set_section = self.saved_sections_combobox_active |
1622 if self.saved_category_list == self.category_list: |
1605 if self.saved_category_list == self.category_list: |
1741 sort_col = enumerations.NAME_COLUMN |
1724 sort_col = enumerations.NAME_COLUMN |
1742 try: |
1725 try: |
1743 for query_num, pub, (v, return_type, tmp) in \ |
1726 for query_num, pub, (v, return_type, tmp) in \ |
1744 itertools.chain(*searches): |
1727 itertools.chain(*searches): |
1745 if v < 1 or return_type != api.Query.RETURN_PACKAGES: |
1728 if v < 1 or return_type != api.Query.RETURN_PACKAGES: |
1746 gobject.idle_add(self.w_progress_dialog.hide) |
|
1747 self.__process_after_search_failure() |
1729 self.__process_after_search_failure() |
1748 return |
1730 return |
1749 |
1731 |
1750 active_pub = None |
1732 active_pub = None |
1751 if pub is not None \ |
1733 if pub is not None \ |
1768 sort_col) |
1750 sort_col) |
1769 last_name = name |
1751 last_name = name |
1770 self.pylintstub = query_num |
1752 self.pylintstub = query_num |
1771 except api_errors.ProblematicSearchServers, ex: |
1753 except api_errors.ProblematicSearchServers, ex: |
1772 self.__process_api_search_error(ex) |
1754 self.__process_api_search_error(ex) |
1773 gobject.idle_add(self.w_progress_dialog.hide) |
|
1774 gobject.idle_add(self.__handle_api_search_error) |
1755 gobject.idle_add(self.__handle_api_search_error) |
1775 if len(result) == 0: |
1756 if len(result) == 0: |
1776 self.__process_after_search_with_zero_results() |
1757 self.__process_after_search_with_zero_results() |
1777 return |
1758 return |
|
1759 except api_errors.CanceledException: |
|
1760 # TBD. Currently search is not cancelable |
|
1761 # so this should not happen, but the logic is in place |
|
1762 # to support cancelable search. |
|
1763 self.unset_busy_cursor() |
|
1764 return |
1778 except Exception, ex: |
1765 except Exception, ex: |
1779 # We are not interested in this error |
1766 # We are not interested in this error |
1780 gobject.idle_add(self.w_progress_dialog.hide) |
|
1781 self.__process_after_search_failure() |
1767 self.__process_after_search_failure() |
1782 return |
1768 return |
1783 if debug: |
1769 if debug: |
1784 print "Number of search results:", len(result) |
1770 print "Number of search results:", len(result) |
1785 if len(result) == 0: |
1771 if len(result) == 0: |
1848 except api_errors.InventoryException: |
1834 except api_errors.InventoryException: |
1849 # This can happen if load_catalogs has not been run |
1835 # This can happen if load_catalogs has not been run |
1850 err = _("Unable to get status for search results.\n" |
1836 err = _("Unable to get status for search results.\n" |
1851 "The catalogs have not been loaded.\n" |
1837 "The catalogs have not been loaded.\n" |
1852 "Please try after few seconds.\n") |
1838 "Please try after few seconds.\n") |
1853 gobject.idle_add(self.w_progress_dialog.hide) |
|
1854 gobject.idle_add(self.error_occurred, err) |
1839 gobject.idle_add(self.error_occurred, err) |
1855 return |
1840 return |
1856 return self.__add_pkgs_to_lists(pkgs_known, application_list, |
1841 return self.__add_pkgs_to_lists(pkgs_known, application_list, |
1857 None, None) |
1842 None, None) |
1858 |
1843 |
1911 # Only clear out search results |
1896 # Only clear out search results |
1912 if self.in_search_mode or self.is_all_publishers: |
1897 if self.in_search_mode or self.is_all_publishers: |
1913 self.__clear_before_search() |
1898 self.__clear_before_search() |
1914 self.__update_statusbar_message(_("Search cleared")) |
1899 self.__update_statusbar_message(_("Search cleared")) |
1915 return |
1900 return |
|
1901 |
|
1902 def __on_progress_cancel_clicked(self, widget): |
|
1903 Thread(target = self.api_o.cancel, args = ()).start() |
1916 |
1904 |
1917 def __on_startpage(self, widget): |
1905 def __on_startpage(self, widget): |
1918 self.__load_startpage() |
1906 self.__load_startpage() |
1919 self.w_main_view_notebook.set_current_page(NOTEBOOK_START_PAGE) |
1907 self.w_main_view_notebook.set_current_page(NOTEBOOK_START_PAGE) |
1920 |
1908 |
2415 |
2403 |
2416 def __get_application_categories_lists(self, publishers): |
2404 def __get_application_categories_lists(self, publishers): |
2417 application_list = self.__get_new_application_liststore() |
2405 application_list = self.__get_new_application_liststore() |
2418 category_list = self.__get_new_category_liststore() |
2406 category_list = self.__get_new_category_liststore() |
2419 section_list = self.__get_new_section_liststore() |
2407 section_list = self.__get_new_section_liststore() |
2420 first_loop = True |
|
2421 for pub in publishers: |
2408 for pub in publishers: |
2422 uptodate = False |
2409 uptodate = False |
2423 try: |
2410 try: |
2424 uptodate = self.__check_if_cache_uptodate(pub) |
2411 uptodate = self.__check_if_cache_uptodate(pub) |
2425 if uptodate: |
2412 if uptodate: |
2431 #from api. |
2418 #from api. |
2432 application_list = self.__get_new_application_liststore() |
2419 application_list = self.__get_new_application_liststore() |
2433 category_list = self.__get_new_category_liststore() |
2420 category_list = self.__get_new_category_liststore() |
2434 uptodate = False |
2421 uptodate = False |
2435 if not uptodate: |
2422 if not uptodate: |
2436 if first_loop == True: |
2423 status_str = _("Refreshing package catalog information") |
2437 first_loop = False |
2424 gobject.idle_add(self.__update_statusbar_message, |
2438 gobject.idle_add(self.setup_progressdialog_show) |
2425 status_str) |
2439 self.api_o.refresh(pubs=[pub]) |
2426 self.api_o.refresh(pubs=[pub]) |
2440 self.__add_pkgs_to_lists_from_api(pub, |
2427 self.__add_pkgs_to_lists_from_api(pub, |
2441 application_list, category_list, section_list) |
2428 application_list, category_list, section_list) |
2442 category_list.prepend([0, _('All'), None, None, False, |
2429 category_list.prepend([0, _('All'), None, None, False, |
2443 True, None]) |
2430 True, None]) |
2444 if self.application_list and self.category_list and \ |
2431 if self.application_list and self.category_list and \ |
2445 not self.last_visible_publisher_uptodate: |
2432 not self.last_visible_publisher_uptodate: |
|
2433 status_str = _("Loading package list") |
|
2434 gobject.idle_add(self.__update_statusbar_message, |
|
2435 status_str) |
2446 if self.last_visible_publisher: |
2436 if self.last_visible_publisher: |
2447 dump_list = self.application_list |
2437 dump_list = self.application_list |
2448 if self.saved_application_list != None: |
2438 if self.saved_application_list != None: |
2449 dump_list = \ |
2439 dump_list = \ |
2450 self.saved_application_list |
2440 self.saved_application_list |
2454 self.last_visible_publisher_uptodate = uptodate |
2444 self.last_visible_publisher_uptodate = uptodate |
2455 return application_list, category_list, section_list |
2445 return application_list, category_list, section_list |
2456 |
2446 |
2457 def __check_if_cache_uptodate(self, pub): |
2447 def __check_if_cache_uptodate(self, pub): |
2458 if self.cache_o: |
2448 if self.cache_o: |
2459 return self.cache_o.check_if_cache_uptodate(pub) |
2449 uptodate = self.cache_o.check_if_cache_uptodate(pub) |
|
2450 # We need to reset the state of the api, otherwise |
|
2451 # method api.can_be_canceled() will return True |
|
2452 self.api_o.reset() |
|
2453 return uptodate |
2460 return False |
2454 return False |
2461 |
2455 |
2462 def __dump_datamodels(self, pub, application_list, category_list, |
2456 def __dump_datamodels(self, pub, application_list, category_list, |
2463 section_list): |
2457 section_list): |
2464 #Consistency check - only dump models if publisher passed in matches |
2458 #Consistency check - only dump models if publisher passed in matches |
2575 installupdate.InstallUpdate(remove_list, self, |
2569 installupdate.InstallUpdate(remove_list, self, |
2576 self.api_o, ips_update = False, |
2570 self.api_o, ips_update = False, |
2577 action = enumerations.REMOVE) |
2571 action = enumerations.REMOVE) |
2578 |
2572 |
2579 def __on_reload(self, widget): |
2573 def __on_reload(self, widget): |
|
2574 self.w_searchentry.grab_focus() |
2580 if self.description_thread_running: |
2575 if self.description_thread_running: |
2581 self.cancelled = True |
2576 self.cancelled = True |
2582 if self.in_search_mode or self.is_all_publishers: |
2577 if self.in_search_mode or self.is_all_publishers: |
2583 self.__unset_search(False) |
2578 self.__unset_search(False) |
2584 self.__set_empty_details_panel() |
2579 self.__set_empty_details_panel() |
2585 self.in_setup = True |
2580 self.in_setup = True |
2586 self.last_visible_publisher = None |
2581 self.last_visible_publisher = None |
2587 if widget != None: |
2582 if widget != None: |
2588 self.__remove_cache() |
2583 self.__remove_cache() |
2589 self.w_progress_dialog.set_title(_("Refreshing catalogs")) |
2584 self.set_busy_cursor() |
2590 self.w_progressinfo_label.set_text(_("Refreshing catalogs...")) |
2585 status_str = _("Refreshing package catalog information") |
2591 self.progress_stop_timer_thread = False |
2586 self.__update_statusbar_message(status_str) |
2592 Thread(target = self.__progressdialog_progress_pulse).start() |
|
2593 self.w_progress_dialog.show() |
|
2594 self.w_progress_cancel.hide() |
|
2595 self.__disconnect_models() |
2587 self.__disconnect_models() |
2596 self.in_reload = True |
2588 self.in_reload = True |
2597 Thread(target = self.__catalog_refresh).start() |
2589 Thread(target = self.__catalog_refresh).start() |
2598 |
2590 |
2599 def __catalog_refresh_done(self): |
2591 def __catalog_refresh_done(self): |
2600 self.progress_stop_timer_thread = True |
|
2601 #Let the progress_pulse finish. This should be done other way, but at |
|
2602 #The moment this works fine |
|
2603 time.sleep(0.2) |
|
2604 gobject.idle_add(self.w_progress_cancel.show) |
|
2605 gobject.idle_add(self.process_package_list_start, |
2592 gobject.idle_add(self.process_package_list_start, |
2606 self.image_directory) |
2593 self.image_directory) |
2607 |
2594 |
2608 def __main_application_quit(self, be_name = None): |
2595 def __main_application_quit(self, be_name = None): |
2609 '''quits the main gtk loop''' |
2596 '''quits the main gtk loop''' |
3409 True, True) |
3396 True, True) |
3410 except api_errors.InventoryException: |
3397 except api_errors.InventoryException: |
3411 # This can happen if the repository does not |
3398 # This can happen if the repository does not |
3412 # contain any packages |
3399 # contain any packages |
3413 err = _("Selected repository does not contain any packages.") |
3400 err = _("Selected repository does not contain any packages.") |
3414 gobject.idle_add(self.w_progress_dialog.hide) |
|
3415 gobject.idle_add(self.error_occurred, err, None, |
3401 gobject.idle_add(self.error_occurred, err, None, |
3416 gtk.MESSAGE_INFO) |
3402 gtk.MESSAGE_INFO) |
3417 self.unset_busy_cursor() |
3403 self.unset_busy_cursor() |
3418 pkgs_known = [] |
3404 pkgs_known = [] |
3419 |
3405 |
3446 section = sectioninfo.read(self.application_dir + |
3432 section = sectioninfo.read(self.application_dir + |
3447 share_path + "opensolaris.org.sections") |
3433 share_path + "opensolaris.org.sections") |
3448 sections[pub] = section |
3434 sections[pub] = section |
3449 pkg_count = 0 |
3435 pkg_count = 0 |
3450 pkg_add = 0 |
3436 pkg_add = 0 |
3451 progress_percent = INITIAL_PROGRESS_TOTAL_PERCENTAGE |
|
3452 total_pkg_count = len(pkgs_known) |
3437 total_pkg_count = len(pkgs_known) |
3453 progress_increment = \ |
3438 status_str = _("Loading package list") |
3454 total_pkg_count / PACKAGE_PROGRESS_TOTAL_INCREMENTS |
3439 gobject.idle_add(self.__update_statusbar_message, status_str) |
3455 self.progress_stop_timer_thread = True |
|
3456 while gtk.events_pending(): |
|
3457 gtk.main_iteration(False) |
|
3458 prev_stem = "" |
3440 prev_stem = "" |
3459 prev_pfmri_str = "" |
3441 prev_pfmri_str = "" |
3460 next_app = None |
3442 next_app = None |
3461 pkg_name = None |
3443 pkg_name = None |
3462 pkg_publisher = None |
3444 pkg_publisher = None |
3482 pkg_add += 1 |
3464 pkg_add += 1 |
3483 prev_stem = pkg.get_pkg_stem() |
3465 prev_stem = pkg.get_pkg_stem() |
3484 prev_pfmri_str = pkg.get_short_fmri() |
3466 prev_pfmri_str = pkg.get_short_fmri() |
3485 prev_state = state |
3467 prev_state = state |
3486 |
3468 |
3487 if progress_increment > 0 and pkg_count % progress_increment == 0: |
3469 gobject.idle_add(self.__progress_set_fraction, |
3488 progress_percent += PACKAGE_PROGRESS_PERCENT_INCREMENT |
3470 pkg_count, total_pkg_count) |
3489 if progress_percent <= PACKAGE_PROGRESS_PERCENT_TOTAL: |
|
3490 self.__progressdialog_progress_percent( |
|
3491 progress_percent, pkg_count, total_pkg_count) |
|
3492 while gtk.events_pending(): |
|
3493 gtk.main_iteration(False) |
|
3494 |
|
3495 status_icon = None |
3471 status_icon = None |
3496 category_icon = None |
3472 category_icon = None |
3497 pkg_name = pkg.get_name() |
3473 pkg_name = pkg.get_name() |
3498 pkg_name = gui_misc.get_pkg_name(pkg_name) |
3474 pkg_name = gui_misc.get_pkg_name(pkg_name) |
3499 pkg_stem = pkg.get_pkg_stem() |
3475 pkg_stem = pkg.get_pkg_stem() |
3528 category_list, pkg_publisher) |
3504 category_list, pkg_publisher) |
3529 pkg_add += 1 |
3505 pkg_add += 1 |
3530 if category_list != None: |
3506 if category_list != None: |
3531 self.__add_categories_to_sections(sections, |
3507 self.__add_categories_to_sections(sections, |
3532 category_list, section_list) |
3508 category_list, section_list) |
3533 self.__progressdialog_progress_percent(PACKAGE_PROGRESS_PERCENT_TOTAL, |
3509 gobject.idle_add(self.__progress_set_fraction, |
3534 total_pkg_count, total_pkg_count) |
3510 pkg_count, total_pkg_count) |
3535 return |
3511 return |
3536 |
3512 |
3537 def __add_categories_to_sections(self, sections, category_list, section_list): |
3513 def __add_categories_to_sections(self, sections, category_list, section_list): |
3538 for pub in sections: |
3514 for pub in sections: |
3539 for section in sections[pub]: |
3515 for section in sections[pub]: |
3624 if not section_name in \ |
3600 if not section_name in \ |
3625 section_lst: |
3601 section_lst: |
3626 section_lst.append( |
3602 section_lst.append( |
3627 section_id) |
3603 section_id) |
3628 |
3604 |
3629 def __progressdialog_progress_pulse(self): |
3605 |
3630 while not self.progress_stop_timer_thread: |
3606 def __progress_set_fraction(self, count, total): |
3631 gobject.idle_add(self.w_progressbar.pulse) |
3607 self.__progress_pulse_stop() |
|
3608 if count == total: |
|
3609 self.w_progress_frame.hide() |
|
3610 return False |
|
3611 if self.api_o.can_be_canceled(): |
|
3612 self.progress_cancel.show() |
|
3613 else: |
|
3614 self.progress_cancel.hide() |
|
3615 self.w_progress_frame.show() |
|
3616 result = (count + 0.0)/total |
|
3617 if result > 1.0: |
|
3618 result = 1.0 |
|
3619 elif result < 0.0: |
|
3620 result = 0.0 |
|
3621 self.w_status_progressbar.set_fraction(result) |
|
3622 |
|
3623 |
|
3624 def __progress_pulse_start(self): |
|
3625 if self.progress_stop_thread == True: |
|
3626 self.progress_stop_thread = False |
|
3627 Thread(target = self.__progress_pulse).start() |
|
3628 |
|
3629 def __progress_pulse_stop(self): |
|
3630 self.progress_stop_thread = True |
|
3631 |
|
3632 def __progress_pulse(self): |
|
3633 gobject.idle_add(self.w_progress_frame.show) |
|
3634 while not self.progress_stop_thread: |
|
3635 if self.api_o.can_be_canceled(): |
|
3636 gobject.idle_add(self.progress_cancel.show) |
|
3637 else: |
|
3638 gobject.idle_add(self.progress_cancel.hide) |
|
3639 gobject.idle_add(self.w_status_progressbar.pulse) |
3632 time.sleep(0.1) |
3640 time.sleep(0.1) |
3633 gobject.idle_add(self.w_progress_dialog.hide) |
3641 gobject.idle_add(self.w_progress_frame.hide) |
3634 self.progress_stop_timer_thread = False |
3642 self.progress_stop_thread = True |
3635 |
|
3636 # For initial setup before loading package entries allow 5% of progress bar |
|
3637 # update it on a time base as we have no other way to judge progress at this point |
|
3638 def __progressdialog_progress_time(self): |
|
3639 while not self.progress_stop_timer_thread and \ |
|
3640 self.progress_fraction_time_count <= \ |
|
3641 INITIAL_PROGRESS_TOTAL_PERCENTAGE: |
|
3642 |
|
3643 gobject.idle_add(self.w_progressbar.set_fraction, |
|
3644 self.progress_fraction_time_count) |
|
3645 self.progress_fraction_time_count += \ |
|
3646 INITIAL_PROGRESS_TIME_PERCENTAGE |
|
3647 time.sleep(INITIAL_PROGRESS_TIME_INTERVAL) |
|
3648 self.progress_stop_timer_thread = False |
|
3649 self.progress_fraction_time_count = 0 |
|
3650 |
|
3651 def __progressdialog_progress_percent(self, fraction, count, total): |
|
3652 gobject.idle_add(self.w_progressinfo_label.set_text, _( |
|
3653 "Processing package entries: %d of %d") % (count, total) ) |
|
3654 gobject.idle_add(self.w_progressbar.set_fraction, fraction) |
|
3655 |
3643 |
3656 def error_occurred(self, error_msg, msg_title=None, msg_type=gtk.MESSAGE_ERROR): |
3644 def error_occurred(self, error_msg, msg_title=None, msg_type=gtk.MESSAGE_ERROR): |
3657 if msg_title: |
3645 if msg_title: |
3658 title = msg_title |
3646 title = msg_title |
3659 else: |
3647 else: |
3752 return version |
3740 return version |
3753 |
3741 |
3754 #-----------------------------------------------------------------------------# |
3742 #-----------------------------------------------------------------------------# |
3755 # Public Methods |
3743 # Public Methods |
3756 #-----------------------------------------------------------------------------# |
3744 #-----------------------------------------------------------------------------# |
3757 def setup_progressdialog_show(self): |
|
3758 self.w_progress_dialog.set_title(_("Loading Repository Information")) |
|
3759 self.w_progressinfo_label.set_text( |
|
3760 _( "Fetching package entries ...")) |
|
3761 self.w_progress_cancel.hide() |
|
3762 self.w_progress_dialog.show() |
|
3763 Thread(target = self.__progressdialog_progress_time).start() |
|
3764 |
|
3765 def setup_progressdialog_hide(self): |
|
3766 self.progress_stop_timer_thread = True |
|
3767 self.w_progress_dialog.hide() |
|
3768 |
|
3769 def init_show_filter(self): |
3745 def init_show_filter(self): |
3770 """ Sets up the Filter Combobox and returns the maximum length of text |
3746 """ Sets up the Filter Combobox and returns the maximum length of text |
3771 labels it is displaying.""" |
3747 labels it is displaying.""" |
3772 return self.__init_show_filter() #Initiates filter |
3748 return self.__init_show_filter() #Initiates filter |
3773 |
3749 |
3780 |
3756 |
3781 def is_busy_cursor_set(self): |
3757 def is_busy_cursor_set(self): |
3782 return self.gdk_window.is_visible() |
3758 return self.gdk_window.is_visible() |
3783 |
3759 |
3784 def set_busy_cursor(self): |
3760 def set_busy_cursor(self): |
|
3761 self.__progress_pulse_start() |
3785 self.gdk_window.show() |
3762 self.gdk_window.show() |
3786 |
3763 |
3787 def unset_busy_cursor(self): |
3764 def unset_busy_cursor(self): |
|
3765 self.__progress_pulse_stop() |
3788 self.gdk_window.hide() |
3766 self.gdk_window.hide() |
3789 |
3767 |
3790 def process_package_list_start(self, image_directory): |
3768 def process_package_list_start(self, image_directory): |
3791 self.image_directory = image_directory |
3769 self.image_directory = image_directory |
3792 if not self.api_o: |
3770 if not self.api_o: |
3821 if self.update_all_proceed: |
3799 if self.update_all_proceed: |
3822 # TODO: Handle situation where only SUNWipkg/SUNWipg-gui have been updated |
3800 # TODO: Handle situation where only SUNWipkg/SUNWipg-gui have been updated |
3823 # in update all: bug 6357 |
3801 # in update all: bug 6357 |
3824 self.__on_update_all(None) |
3802 self.__on_update_all(None) |
3825 self.update_all_proceed = False |
3803 self.update_all_proceed = False |
3826 self.setup_progressdialog_hide() |
|
3827 self.__enable_disable_install_remove() |
3804 self.__enable_disable_install_remove() |
3828 self.update_statusbar() |
3805 self.update_statusbar() |
3829 self.in_setup = False |
3806 self.in_setup = False |
3830 self.cancelled = False |
3807 self.cancelled = False |
3831 if self.set_section != 0 or \ |
3808 if self.set_section != 0 or \ |
3871 listed_str = _('%d listed') % len(self.application_list) |
3848 listed_str = _('%d listed') % len(self.application_list) |
3872 sel_str = _('%d selected') % sel |
3849 sel_str = _('%d selected') % sel |
3873 inst_str = _('%d installed') % installed |
3850 inst_str = _('%d installed') % installed |
3874 status_str = _("%s: %s , %s, %s.") % (visible_publisher, |
3851 status_str = _("%s: %s , %s, %s.") % (visible_publisher, |
3875 listed_str, inst_str, sel_str) |
3852 listed_str, inst_str, sel_str) |
3876 self.w_main_statusbar.push(0, status_str) |
3853 self.__update_statusbar_message(status_str) |
3877 return |
3854 return |
3878 |
3855 |
3879 # In Search Mode |
3856 # In Search Mode |
3880 active = "" |
3857 active = "" |
3881 if self.is_all_publishers: |
3858 if self.is_all_publishers: |
3906 elif self.search_time_sec > 1: |
3883 elif self.search_time_sec > 1: |
3907 time_str = _("in %d seconds") % self.search_time_sec |
3884 time_str = _("in %d seconds") % self.search_time_sec |
3908 |
3885 |
3909 status_str = fmt_str % {"option_str" : opt_str, "number" : |
3886 status_str = fmt_str % {"option_str" : opt_str, "number" : |
3910 len(self.application_list), "time" : time_str} |
3887 len(self.application_list), "time" : time_str} |
3911 self.w_main_statusbar.push(0, status_str) |
3888 self.__update_statusbar_message(status_str) |
3912 |
3889 |
3913 def update_package_list(self, update_list): |
3890 def update_package_list(self, update_list): |
3914 if update_list == None and self.img_timestamp: |
3891 if update_list == None and self.img_timestamp: |
3915 return |
3892 return |
3916 visible_publisher = self.__get_selected_publisher() |
3893 visible_publisher = self.__get_selected_publisher() |