src/packagemanager.py
changeset 1236 15707d6de40b
parent 1233 32a432cffc1e
child 1243 d1f303f7dd86
equal deleted inserted replaced
1235:7c34ba6e5e4f 1236:15707d6de40b
    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()