Print this page
*** NO COMMENTS ***


  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
  41 MAX_INFO_CACHE_LIMIT = 100                # Max number of package descriptions to cache
  42 NOTEBOOK_PACKAGE_LIST_PAGE = 0            # Main Package List page index
  43 NOTEBOOK_START_PAGE = 1                   # Main View Start page index
  44 INFO_NOTEBOOK_LICENSE_PAGE = 3            # License Tab index
  45 SHOW_INFO_DELAY = 600       # Delay before showing selected pacakge information
  46 SHOW_LICENSE_DELAY = 600    # Delay before showing license information
  47 SEARCH_STR_FORMAT = "<%s>"
  48 SEARCH_LIMIT = 100                        # Maximum number of results shown for
  49                                           # api search
  50 MIN_APP_WIDTH = 750                       # Minimum application width
  51 MIN_APP_HEIGHT = 500                     # Minimum application height
  52 INITIAL_APP_WIDTH_PREFERENCES = "/apps/packagemanager/preferences/initial_app_width"
  53 INITIAL_APP_HEIGHT_PREFERENCES = "/apps/packagemanager/preferences/initial_app_height"
  54 INITIAL_APP_HPOS_PREFERENCES = "/apps/packagemanager/preferences/initial_app_hposition"
  55 INITIAL_APP_VPOS_PREFERENCES = "/apps/packagemanager/preferences/initial_app_vposition"
  56 INITIAL_SHOW_FILTER_PREFERENCES = "/apps/packagemanager/preferences/initial_show_filter"
  57 INITIAL_SECTION_PREFERENCES = "/apps/packagemanager/preferences/initial_section"
  58 SHOW_STARTPAGE_PREFERENCES = "/apps/packagemanager/preferences/show_startpage"
  59 API_SEARCH_ERROR_PREFERENCES = "/apps/packagemanager/preferences/api_search_error"
  60 CATEGORIES_STATUS_COLUMN_INDEX = 0   # Index of Status Column in Categories TreeView
  61 
  62 STATUS_COLUMN_INDEX = 2   # Index of Status Column in Application TreeView
  63 
  64 PKG_CLIENT_NAME = "packagemanager"
  65 
  66 # Location for themable icons
  67 ICON_LOCATION = "usr/share/package-manager/icons"
  68 # Load Start Page from lang dir if available
  69 START_PAGE_CACHE_LANG_BASE = "var/pkg/gui_cache/startpagebase/%s/%s"


 253                 self.categories_status_id = 0
 254                 self.icon_theme = gtk.IconTheme()
 255                 icon_location = os.path.join(self.application_dir, ICON_LOCATION)
 256                 self.icon_theme.append_search_path(icon_location)
 257                 self.search_options = [
 258                     ('ips-search',
 259                     gui_misc.get_icon(self.icon_theme, 'search', 20),
 260                     _("_Current Repository"),
 261                     _("Search Current Repository")),
 262                     ('ips-search-all',
 263                     gui_misc.get_icon(self.icon_theme, 'search_all', 20),
 264                     _("_All Repositories"),
 265                     _("Search All Repositories"))
 266                     ]
 267                 self.__register_iconsets(self.search_options)               
 268                 self.visible_repository = None
 269                 self.visible_repository_uptodate = False
 270                 self.last_active_publisher = None
 271                 self.search_start = 0
 272                 self.search_time_sec = 0

 273                 self.section_list = None
 274                 self.filter_list = self.__get_new_filter_liststore()
 275                 self.application_list = None
 276                 self.a11y_application_treeview = None
 277                 self.a11y_categories_treeview = None
 278                 self.application_treeview_range = None
 279                 self.application_treeview_initialized = False
 280                 self.categories_treeview_range = None
 281                 self.categories_treeview_initialized = False
 282                 self.category_list = None
 283                 self.repositories_list = None
 284                 self.pr = progress.NullProgressTracker()
 285                 self.pylintstub = None
 286                 self.release_notes_url = "http://www.opensolaris.org"
 287                 self.__image_activity_lock = Lock()
 288 
 289                 # Create Widgets and show gui
 290                 self.gladefile = os.path.join(self.application_dir,
 291                     "usr/share/package-manager/packagemanager.glade")
 292                 w_tree_main = gtk.glade.XML(self.gladefile, "mainwindow")


 658                 is_search_all = (i != 0)
 659                 self.__update_repository_combobox_for_search(is_search_all)
 660                 if is_search_all:
 661                         self.__setup_before_search_all_mode()
 662                 else:
 663                         self.__restore_setup_for_browse()
 664                 self.changing_search_option = False
 665 
 666         def __update_repository_combobox_for_search(self, is_search_all):
 667                 if is_search_all:
 668                         self.saved_repository_combobox_active = \
 669                             self.w_repository_combobox.get_active()
 670                 self.__disconnect_repository_model()
 671                 if is_search_all:
 672                         self.repositories_list.prepend(
 673                             [-1, _("All Repositories Search Results"), ])
 674                 else:
 675                         self.repositories_list.remove(
 676                             self.repositories_list.get_iter_first())
 677                 self.w_repository_combobox.set_model(self.repositories_list)
 678                 self.visible_repository = None
 679 
 680 
 681         def __link_load_blank(self):
 682                 self.document.clear()
 683                 self.document.open_stream('text/html')
 684                 self.document.write_stream(_(
 685                     "<html><head></head><body></body></html>"))
 686                 self.document.close_stream()
 687 
 688         def __search_menu_item_activate(self, widget):
 689                 name = widget.get_name()
 690                 i = 0
 691                 for stock_id, pixbuf, label, description in self.search_options:
 692                         if stock_id == name:
 693                                 self.__set_search_option(i)
 694                                 self.search_image.set_from_pixbuf(pixbuf)
 695                                 self.a11y_search_button.set_description(description)
 696                                 break
 697                         i += 1
 698                         self.pylintstub = label


 745                                 start_page_lang_base % (self.lang_root, START_PAGE_HOME))
 746                         if self.__load_uri(self.document, start_page_url):
 747                                 return True
 748 
 749                 start_page_url = os.path.join(self.application_dir,
 750                         start_page_lang_base % ("C", START_PAGE_HOME))
 751                 if self.__load_uri(self.document, start_page_url):
 752                         return True
 753                 return False
 754 
 755         def __handle_startpage_load_error(self, start_page_url):
 756                 self.document.open_stream('text/html')
 757                 self.document.write_stream(_(
 758                     "<html><head></head><body><H2>Welcome to"
 759                     "PackageManager!</H2><br>"
 760                     "<font color='#0000FF'>Warning: Unable to "
 761                     "load Start Page:<br>%s</font></body></html>"
 762                     % (start_page_url)))
 763                 self.document.close_stream()
 764 
 765         def __parse_api_search_error(self, error):
 766                 self.current_repos_with_search_errors = []
 767                 if "failed_servers" in error.__dict__ and len(error.failed_servers) > 0:
 768                         #TBD we should not have to parse the error output
 769                         rem_str = " doesn't speak a known version of search operation"
 770                         timeout_str = "urlopen error timed out"
 771                         repos = []
 772                         for err in error.failed_servers:
 773                                 err_str = str(err[1])
 774                                 if rem_str in err_str:
 775                                         repo = err_str.replace(rem_str,"")
 776                                         self.current_repos_with_search_errors.append(repo)
 777                                 elif timeout_str in err_str:
 778                                         repo = err[0].repositories[0].origins[0].uri
 779                                         self.current_repos_with_search_errors.append(repo)
 780 











 781         def __on_infosearch_button_clicked(self, widget):
 782                 self.__handle_api_search_error(True)
 783 
 784         def __handle_api_search_error(self, show_all=False):
 785                 if len(self.current_repos_with_search_errors) == 0:
 786                         self.w_infosearch_frame.hide()
 787                         return
 788                 else:
 789                         self.w_infosearch_button.set_size_request(26, 22)
 790                         self.w_infosearch_frame.show()
 791 
 792                 repo_pubs = self.__get_repo_publishers()
 793                 repo_count = 0
 794                 for url in self.current_repos_with_search_errors:
 795                         if show_all or (url not in self.gconf_not_show_repos):
 796                                 repo_count += 1
 797                 if repo_count == 0:

 798                         return
 799 


 800                 infobuffer = self.api_search_error_textview.get_buffer()
 801                 infobuffer.set_text("")
 802                 textiter = infobuffer.get_end_iter()
 803                 for url in self.current_repos_with_search_errors:
 804                         if show_all or (url not in self.gconf_not_show_repos):

 805                                 infobuffer.insert_with_tags_by_name(textiter,
 806                                         "%s" % repo_pubs[url], "bold")
 807                                 infobuffer.insert(textiter, " (%s)\n" % url)


 808                 self.api_search_checkbox.set_active(False)
 809                 self.api_search_error_dialog.show()
 810                 self.api_search_button.grab_focus()
 811 
 812         def __get_repo_publishers(self):
 813                 repo_pub_dict = {}
 814                 pubs = self.api_o.get_publishers()
 815                 for pub in pubs:
 816                         repo = pub.selected_repository
 817                         origin = repo.origins[0]
 818                         repo_pub_dict[origin.uri] = pub.prefix
 819                 return repo_pub_dict
 820 
 821         def __on_url(self, view, link):
 822                 # Handle mouse over events on links and reset when not on link
 823                 if link == None or link == "":
 824                         self.update_statusbar()
 825                 else:
 826                         display_link = self.__handle_link(None, link, DISPLAY_LINK)
 827                         if display_link != None:


 998                         gobject.TYPE_STRING,      # enumerations.SECTION_NAME
 999                         gobject.TYPE_STRING,      # enumerations.SECTION_SUBCATEGORY
1000                         gobject.TYPE_BOOLEAN,     # enumerations.SECTION_ENABLED
1001                         )
1002 
1003         @staticmethod
1004         def __get_new_filter_liststore():
1005                 return gtk.ListStore(
1006                         gobject.TYPE_INT,         # enumerations.FILTER_ID
1007                         gobject.TYPE_STRING,      # enumerations.FILTER_NAME
1008                         )
1009 
1010         @staticmethod
1011         def __get_new_repositories_liststore():
1012                 return gtk.ListStore(
1013                         gobject.TYPE_INT,         # enumerations.REPOSITORY_ID
1014                         gobject.TYPE_STRING,      # enumerations.REPOSITORY_NAME
1015                         )
1016 
1017         def __init_application_tree_view(self, application_list,
1018             application_list_filter, application_list_sort):

1019                 ##APPLICATION MAIN TREEVIEW
1020                 if application_list_filter == None:
1021                         application_list_filter = application_list.filter_new()
1022                 if application_list_sort == None:
1023                         application_list_sort = \
1024                             gtk.TreeModelSort(application_list_filter)
1025                         application_list_sort.set_sort_column_id(
1026                             enumerations.NAME_COLUMN, gtk.SORT_ASCENDING)
1027                         application_list_sort.set_sort_func(
1028                             enumerations.STATUS_ICON_COLUMN, self.__status_sort_func)
1029                 toggle_renderer = gtk.CellRendererToggle()
1030 
1031                 column = gtk.TreeViewColumn("", toggle_renderer, \
1032                     active = enumerations.MARK_COLUMN)
1033                 column.set_sort_column_id(enumerations.MARK_COLUMN)
1034                 column.set_sort_indicator(True)
1035                 column.set_cell_data_func(toggle_renderer, self.cell_data_function, None)
1036                 column.connect_after('clicked',
1037                     self.__application_treeview_column_sorted, None)
1038                 self.w_application_treeview.append_column(column)
1039                 name_renderer = gtk.CellRendererText()
1040                 column = gtk.TreeViewColumn(_("Name"), name_renderer,
1041                     text = enumerations.NAME_COLUMN)
1042                 column.set_resizable(True)

1043                 column.set_sort_column_id(enumerations.NAME_COLUMN)
1044                 column.set_sort_indicator(True)
1045                 column.set_cell_data_func(name_renderer, self.cell_data_function, None)
1046                 column.connect_after('clicked',
1047                     self.__application_treeview_column_sorted, None)
1048                 self.w_application_treeview.append_column(column)
1049                 column = self.__create_icon_column(_("Status"), True,
1050                     enumerations.STATUS_ICON_COLUMN, True)
1051                 column.set_sort_column_id(enumerations.STATUS_ICON_COLUMN)
1052                 column.set_sort_indicator(True)
1053                 column.connect_after('clicked',
1054                     self.__application_treeview_column_sorted, None)
1055                 self.w_application_treeview.append_column(column)
1056                 if self.is_search_all:
1057                         repository_renderer = gtk.CellRendererText()
1058                         column = gtk.TreeViewColumn(_('Repository'),
1059                             repository_renderer,
1060                             text = enumerations.AUTHORITY_COLUMN)
1061                         column.set_sort_column_id(enumerations.AUTHORITY_COLUMN)
1062                         column.set_resizable(True)


1071                     description_renderer,
1072                     text = enumerations.DESCRIPTION_COLUMN)
1073                 column.set_sort_column_id(enumerations.DESCRIPTION_COLUMN)
1074                 column.set_resizable(True)
1075                 column.set_sort_indicator(True)
1076                 column.set_cell_data_func(description_renderer,
1077                     self.cell_data_function, None)
1078                 column.connect_after('clicked',
1079                     self.__application_treeview_column_sorted, None)
1080                 self.w_application_treeview.append_column(column)
1081                 #Added selection listener
1082                 self.package_selection = self.w_application_treeview.get_selection()
1083                 self.application_list = application_list
1084                 self.application_list_filter = application_list_filter
1085                 self.application_list_sort = application_list_sort
1086                 toggle_renderer.connect('toggled', self.__active_pane_toggle,
1087                     application_list_sort)
1088 
1089         def __init_tree_views(self, application_list, category_list, 
1090             section_list, application_list_filter = None, 
1091             application_list_sort = None):

1092                 '''This function connects treeviews with their models and also applies
1093                 filters'''
1094                 if category_list == None:
1095                         self.w_application_treeview.set_model(None)
1096                         self.__remove_treeview_columns(self.w_application_treeview)
1097                 elif application_list == None:
1098                         self.w_categories_treeview.set_model(None)
1099                         self.__remove_treeview_columns(self.w_categories_treeview)
1100                 else:
1101                         self.__disconnect_models()
1102                         self.__remove_treeview_columns(self.w_application_treeview)
1103                         self.__remove_treeview_columns(self.w_categories_treeview)
1104                 # The logic for set section needs to be here as some sections
1105                 # might be not enabled. In such situation we are setting the set
1106                 # section to "All Categories" one.
1107                 if section_list != None:
1108                         row = section_list[self.set_section]
1109                         if row[enumerations.SECTION_ENABLED] and \
1110                             self.set_section >= 0 and \
1111                             self.set_section < len(section_list):
1112                                 if row[enumerations.SECTION_ID] != self.set_section:
1113                                         self.set_section = 0
1114                         else:
1115                                 self.set_section = 0
1116 
1117                 if application_list != None:
1118                         self.__init_application_tree_view(application_list,
1119                             application_list_filter, application_list_sort)

1120 
1121                 if self.first_run:
1122                         # When vadj changes we need to set image descriptions
1123                         # on visible status icons. This catches moving the scroll bars
1124                         # and scrolling up and down using keyboard.
1125                         vadj = self.w_application_treeview.get_vadjustment()
1126                         vadj.connect('value-changed',
1127                             self.__application_treeview_vadjustment_changed, None)
1128                         vadj = self.w_categories_treeview.get_vadjustment()
1129                         vadj.connect('value-changed',
1130                             self.__categories_treeview_vadjustment_changed, None)
1131 
1132                         # When the size of the application_treeview changes
1133                         # we need to set image descriptions on visible status icons.
1134                         self.w_application_treeview.connect('size-allocate',
1135                             self.__application_treeview_size_allocate, None)
1136                         self.w_categories_treeview.connect('size-allocate',
1137                             self.__categories_treeview_size_allocate, None)
1138 
1139                 if category_list != None:


1299                 status = model.get_value(itr, enumerations.STATUS_COLUMN)
1300                 if status == enumerations.INSTALLED:
1301                         desc = _("Installed")
1302                 elif status == enumerations.NOT_INSTALLED:
1303                         desc = _("Not Installed")
1304                 elif status == enumerations.UPDATABLE:
1305                         desc = _("Updates Available")
1306                 else:
1307                         desc = None
1308                 if desc != None:
1309                         obj = self.a11y_application_treeview.ref_at(
1310                             int(model.get_string_from_iter(itr)),
1311                             STATUS_COLUMN_INDEX)
1312                         obj.set_image_description(desc)
1313 
1314         def __set_visible_status(self, check_range = True):
1315                 self.visible_status_id = 0
1316                 if self.w_main_view_notebook.get_current_page() != \
1317                     NOTEBOOK_PACKAGE_LIST_PAGE:
1318                         return



1319                 a11y_enabled = False
1320                 if self.a11y_application_treeview.get_n_accessible_children() != 0:
1321                         a11y_enabled = True
1322 
1323                 visible_range = self.w_application_treeview.get_visible_range()
1324                 if visible_range == None:
1325                         return
1326                 start = visible_range[0][0]
1327                 end = visible_range[1][0]
1328                 if debug_descriptions:
1329                         print "Range Start: %d End: %d" % (start, end)
1330 
1331                 # Switching Publishers need to use default range
1332                 active_pub = self.__get_active_publisher()
1333                 if self.last_active_publisher != active_pub:
1334                         check_range = False
1335                 self.last_active_publisher = active_pub
1336                 if self.in_search_mode:
1337                         check_range = False
1338                 


1355                 self.application_treeview_range = visible_range
1356 
1357                 sort_filt_model = \
1358                     self.w_application_treeview.get_model() #gtk.TreeModelSort
1359                 filt_model = sort_filt_model.get_model() #gtk.TreeModelFilter
1360                 model = filt_model.get_model() #gtk.ListStore
1361                 sf_itr = sort_filt_model.get_iter_from_string(str(start))                
1362                 pkg_stems_and_itr_to_fetch = {}
1363                 while start <= end:
1364                         filtered_itr = sort_filt_model.convert_iter_to_child_iter(None,
1365                             sf_itr)
1366                         app_itr = filt_model.convert_iter_to_child_iter(filtered_itr)
1367 
1368                         desc = sort_filt_model.get_value(sf_itr,
1369                             enumerations.DESCRIPTION_COLUMN)
1370                         # Only Fetch description for packages without a
1371                         # description
1372                         if desc == '...':
1373                                 fmri = sort_filt_model.get_value(sf_itr,
1374                                     enumerations.FMRI_COLUMN)

1375                                 pkg_stem = fmri.get_pkg_stem(
1376                                     include_scheme = True)
1377                                 pkg_stems_and_itr_to_fetch[pkg_stem] = \
1378                                     model.get_string_from_iter(app_itr)
1379                         if a11y_enabled:
1380                                 self.__set_accessible_status(sort_filt_model, sf_itr)
1381                         start += 1
1382                         sf_itr = sort_filt_model.iter_next(sf_itr)
1383 
1384                 if debug_descriptions:
1385                         print "PKGS to FETCH: \n%s" % pkg_stems_and_itr_to_fetch
1386                 if len(pkg_stems_and_itr_to_fetch) > 0:
1387                         Thread(target = self.__get_pkg_descriptions,
1388                             args = [pkg_stems_and_itr_to_fetch, model]).start() 
1389                     
1390         def __doing_search(self):
1391                 return self.search_start > 0
1392                 
1393         def __get_pkg_descriptions(self, pkg_stems_and_itr_to_fetch, orig_model):
1394                 # Note: no need to aquire lock even though this can be called from


1405                 except api_errors.TransportError:
1406                         self.update_statusbar()
1407                         return
1408                 if info and len(info.get(0)) == 0:
1409                         self.update_statusbar()
1410                         return
1411                 pkg_infos = info.get(0)
1412                 pkg_descriptions_for_update = []
1413                 for pkg_info in pkg_infos:
1414                         short_fmri = fmri.PkgFmri(pkg_info.fmri).get_pkg_stem(
1415                             include_scheme = True)
1416                         pkg_descriptions_for_update.append((short_fmri,
1417                             pkg_stems_and_itr_to_fetch[short_fmri],
1418                             pkg_info.summary))
1419                 if debug_descriptions:
1420                         print "FETCHED PKGS: \n%s" % pkg_descriptions_for_update
1421                 gobject.idle_add(self.__update_description_from_iter,
1422                     pkg_descriptions_for_update, orig_model)
1423 
1424         def __update_description_from_iter(self, pkg_descriptions_for_update, orig_model):




1425                 sort_filt_model = \
1426                     self.w_application_treeview.get_model() #gtk.TreeModelSort
1427                 filt_model = sort_filt_model.get_model() #gtk.TreeModelFilter
1428                 model = filt_model.get_model() #gtk.ListStore
1429 
1430                 #If model has changed abandon description updates
1431                 if orig_model != model:
1432                         return
1433 
1434                 if debug_descriptions:
1435                         print "UPDATE DESCRIPTIONS: \n%s" % pkg_descriptions_for_update
1436                 for pkg_stem, path, summary in pkg_descriptions_for_update:
1437                         itr = model.get_iter_from_string(path)
1438                         stored_pkg_fmri = model.get_value(itr, enumerations.FMRI_COLUMN)
1439                         stored_pkg_stem = stored_pkg_fmri.get_pkg_stem(
1440                             include_scheme = True)
1441 
1442                         if pkg_stem != stored_pkg_stem:
1443                                 if debug:
1444                                         print ("__update_description_from_iter(): "


1717                 self.search_time_sec = 0
1718                 text = self.w_searchentry.get_text()
1719                 # Here we call the search API to get the results
1720                 searches = []
1721                 servers = []
1722                 result = []
1723                 pargs = []
1724                 search_str = SEARCH_STR_FORMAT % text
1725                 pargs.append(search_str)
1726                 if search_all:
1727                         servers = None
1728                 else:
1729                         pub_prefix = self.__get_active_publisher()
1730                         if pub_prefix != None:
1731                                 pub = self.api_o.get_publisher(prefix=pub_prefix)
1732                         else:
1733                                 pub = self.api_o.get_preferred_publisher()
1734                         origin_uri = self.__get_origin_uri(pub.selected_repository)
1735                         servers.append({"origin": origin_uri})
1736                 if debug:
1737                         print "pargs:", pargs
1738                         print "servers:", servers
1739                         

1740                 case_sensitive = False

1741                 searches.append(self.api_o.remote_search(
1742                     [api.Query(" ".join(pargs), case_sensitive, True, None, None)],
1743                     servers=servers))
1744                 result_tuple = {}








1745                 try:
1746                         for query_num, publisher, (v, return_type, tmp) in \
1747                             itertools.chain(*searches):
1748                                 if v == 1 and \
1749                                     return_type == api.Query.RETURN_PACKAGES:
1750                                         repo = None
1751                                         if publisher is not None \
1752                                             and "prefix" in publisher:
1753                                                 repo = publisher["prefix"]
1754                                         name = fmri.PkgFmri(str(tmp)).get_name()
1755                                         result_tuple[(name, repo)] = -1
1756                                         if len(result_tuple) == SEARCH_LIMIT:
1757                                                 break
1758                                 else:
1759                                         # We are not interested in this error
1760                                         gobject.idle_add(self.w_progress_dialog.hide)
1761                                         self.__process_after_search_failure()
1762                                         return




















1763                                 self.pylintstub = query_num
1764                 except api_errors.ProblematicSearchServers, ex:
1765                         self.__parse_api_search_error(ex)
1766                         gobject.idle_add(self.w_progress_dialog.hide)
1767                         gobject.idle_add(self.__handle_api_search_error)
1768                         if len(result_tuple) == 0:
1769                                 self.__process_after_search_with_zero_results()
1770                                 return
1771                 except Exception, ex:
1772                         # We are not interested in this error
1773                         gobject.idle_add(self.w_progress_dialog.hide)
1774                         self.__process_after_search_failure()
1775                         return
1776                 if debug:
1777                         print "Number of search results:", len(result_tuple)
1778                 for name, repo in result_tuple:
1779                         a_res = name, repo
1780                         result.append(a_res)
1781                 if len(result) == 0:
1782                         if debug:
1783                                 print "No search results"
1784                         self.__process_after_search_with_zero_results()
1785                         return
1786                 # We cannot get status of the packages if catalogs have not
1787                 # been loaded so we pause for up to 5 seconds here to
1788                 # allow catalogs to be loaded
1789                 times = 5
1790                 while self.catalog_loaded == False:
1791                         if times == 0:
1792                                 break
1793                         time.sleep(1)
1794                         times -= 1


1795                 self.in_setup = True
1796                 application_list = self.__get_list_from_search(result)



1797                 if self.search_start > 0:
1798                         self.search_time_sec = int(time.time() - self.search_start)


1799                 self.search_start = 0
1800                 gobject.idle_add(self.__set_empty_details_panel)
1801                 gobject.idle_add(self.__set_main_view_package_list)
1802                 gobject.idle_add(self.__init_tree_views, application_list,
1803                     None, None)
1804 
1805         def __process_after_search_with_zero_results(self):
1806                 if self.search_start > 0:
1807                         self.search_time_sec = int(time.time() - self.search_start)
1808                 self.search_start = 0
1809                 self.in_setup = True
1810                 application_list = self.__get_new_application_liststore()
1811                 gobject.idle_add(self.__set_empty_details_panel)
1812                 gobject.idle_add(self.__set_main_view_package_list)
1813                 gobject.idle_add(self.__init_tree_views, application_list, None, None)
1814 
1815         def __get_list_from_search(self, search_result):
1816                 application_list = self.__get_new_application_liststore()









1817                 self.__add_pkgs_to_list_from_search(search_result,
1818                     application_list)
1819                 return application_list
1820 
1821         def __add_pkgs_to_list_from_search(self, search_result,
1822             application_list):
1823                 pargs = []
1824                 default_pub = self.api_o.get_preferred_publisher().prefix
1825                 for name, publisher in search_result:
1826                         pargs.append("pkg://" + publisher + "/" + name)
1827                 # We now need to get the status for each package
1828                 if debug_descriptions:
1829                         print "pargs:", pargs
1830                 try:
1831                         pkgs_known = self.__get_inventory_list(pargs,
1832                             True, True)
1833                 except api_errors.InventoryException:
1834                         # This can happen if load_catalogs has not been run
1835                         err = _("Unable to get status for search results.\n"
1836                             "The catalogs have not been loaded.\n"


2063                 self.w_preferencesdialog.show()
2064 
2065         def __on_preferencesclose_clicked(self, widget):
2066                 self.w_preferencesdialog.hide()
2067 
2068         def __on_preferenceshelp_clicked(self, widget):
2069                 gui_misc.display_help(self.application_dir, "pm_win")
2070 
2071         def __on_startpage_checkbutton_toggled(self, widget):
2072                 self.show_startpage = self.w_startpage_checkbutton.get_active()
2073                 try:
2074                         self.client.set_bool(SHOW_STARTPAGE_PREFERENCES,
2075                             self.show_startpage)
2076                 except GError:
2077                         pass
2078 
2079         def __on_api_search_checkbox_toggled(self, widget):
2080                 active = self.api_search_checkbox.get_active()
2081                 if len(self.current_repos_with_search_errors) > 0:
2082                         if active:
2083                                 for url in self.current_repos_with_search_errors:
2084                                         if url not in self.gconf_not_show_repos:
2085                                                 self.gconf_not_show_repos += url + ","

2086                         else:
2087                                 for url in self.current_repos_with_search_errors:

2088                                         self.gconf_not_show_repos = \
2089                                             self.gconf_not_show_repos.replace(
2090                                             url + ",", "")
2091                         try:
2092                                 self.client.set_string(API_SEARCH_ERROR_PREFERENCES,
2093                                     self.gconf_not_show_repos)
2094                         except GError:
2095                                 pass
2096 
2097         def __on_searchentry_focus_in(self, widget, event):
2098                 if self.w_main_clipboard.wait_is_text_available():
2099                         self.w_paste_menuitem.set_sensitive(True)
2100                 char_count = widget.get_text_length()
2101                 if char_count > 0:
2102                         self.w_selectall_menuitem.set_sensitive(True)
2103                 else:
2104                         self.w_selectall_menuitem.set_sensitive(False)
2105                 bounds = widget.get_selection_bounds()
2106                 if bounds:
2107                         offset1 = bounds[0]
2108                         offset2 = bounds[1] 
2109                         if abs(offset2 - offset1) == char_count:
2110                                 self.w_selectall_menuitem.set_sensitive(False)


2411                                 start, end = self.w_searchentry.get_selection_bounds()
2412                                 self.w_searchentry.select_region(end, end)
2413 
2414                 pub = [active_publisher, ]
2415                 self.set_show_filter = self.initial_show_filter
2416                 self.set_section = self.initial_section
2417                 Thread(target = self.__setup_publisher, args = [pub]).start()
2418                 self.__set_main_view_package_list()
2419 
2420         def __get_active_publisher(self):
2421                 pub_iter = self.w_repository_combobox.get_active_iter()
2422                 if pub_iter == None:
2423                         return None
2424                 return self.repositories_list.get_value(pub_iter, \
2425                             enumerations.REPOSITORY_NAME)
2426 
2427         def __setup_publisher(self, publishers=[]):
2428                 self.saved_filter_combobox_active = self.initial_show_filter
2429                 application_list, category_list , section_list = \
2430                     self.__get_application_categories_lists(publishers)

2431                 gobject.idle_add(self.__init_tree_views, application_list,
2432                     category_list, section_list)
2433 







2434         def __get_application_categories_lists(self, publishers=[]):
2435                 if not self.visible_repository:
2436                         self.visible_repository = self.__get_active_publisher()
2437                 application_list = self.__get_new_application_liststore()
2438                 category_list = self.__get_new_category_liststore()
2439                 section_list = self.__get_new_section_liststore()
2440                 first_loop = True
2441                 for publisher in publishers:
2442                         uptodate = False
2443                         try:
2444                                 uptodate = self.__check_if_cache_uptodate(publisher)
2445                                 if uptodate:
2446                                         self.__add_pkgs_to_lists_from_cache(publisher,
2447                                             application_list, category_list,
2448                                             section_list)
2449                         except (UnpicklingError, EOFError, IOError):
2450                                 #Most likely cache is corrupted, silently load list
2451                                 #from api.
2452                                 application_list = self.__get_new_application_liststore()
2453                                 category_list = self.__get_new_category_liststore()
2454                                 uptodate = False
2455                         if not uptodate:
2456                                 if first_loop == True:
2457                                         first_loop = False
2458                                         gobject.idle_add(self.setup_progressdialog_show)
2459                                 self.api_o.refresh(pubs=[publisher])
2460                                 self.__add_pkgs_to_lists_from_api(publisher,
2461                                     application_list, category_list, section_list)
2462                                 category_list.prepend([0, _('All'), None, None, False,
2463                                     True, None])
2464                         if self.application_list and self.category_list and \
2465                             not self.visible_repository_uptodate:
2466                                 if self.visible_repository:




2467                                         self.__dump_datamodels(self.visible_repository,
2468                                             self.application_list, self.category_list,
2469                                             self.section_list)
2470                         self.visible_repository = self.__get_active_publisher()
2471                         self.visible_repository_uptodate = uptodate
2472                 return application_list, category_list, section_list
2473 
2474         def __check_if_cache_uptodate(self, publisher):
2475                 if self.cache_o:
2476                         return self.cache_o.check_if_cache_uptodate(publisher)
2477                 return False
2478 
2479         def __dump_datamodels(self, publisher, application_list, category_list,
2480             section_list):












2481                 if self.cache_o:
2482                         if self.img_timestamp == \
2483                             self.cache_o.get_index_timestamp():
2484                                 Thread(target = self.cache_o.dump_datamodels,
2485                                     args = (publisher, application_list, category_list,
2486                                     section_list)).start()
2487                         else:
2488                                 self.__remove_cache()
2489 
2490         def __remove_cache(self):
2491                 model = self.w_repository_combobox.get_model()
2492                 for publisher in model:
2493                         pub_name = publisher[1]
2494                         if pub_name and pub_name != _("Add..."):
2495                                 Thread(target = self.cache_o.remove_datamodel,
2496                                     args = [publisher[1]]).start()
2497 
2498         def __on_install_update(self, widget):
2499                 self.api_o.reset()
2500                 install_update = []


2599                 #Let the progress_pulse finish. This should be done other way, but at
2600                 #The moment this works fine
2601                 time.sleep(0.2)
2602                 gobject.idle_add(self.w_progress_cancel.show)
2603                 gobject.idle_add(self.process_package_list_start,
2604                     self.image_directory)
2605 
2606         def __main_application_quit(self, be_name = None):
2607                 '''quits the main gtk loop'''
2608                 self.cancelled = True
2609                 if self.in_setup:
2610                         return
2611 
2612                 if be_name:
2613                         if self.image_dir_arg:
2614                                 gobject.spawn_async([self.application_path, "-R",
2615                                     self.image_dir_arg, "-U", be_name])
2616                         else:
2617                                 gobject.spawn_async([self.application_path,
2618                                     "-U", be_name])
2619                 elif not self.in_search_mode:




2620                         visible_repository = self.__get_visible_repository_name()
2621                         self.__dump_datamodels(visible_repository,
2622                                 self.application_list, self.category_list,
2623                                 self.section_list)
2624 
2625                 width, height = self.w_main_window.get_size()
2626                 hpos = self.w_main_hpaned.get_position()
2627                 vpos = self.w_main_vpaned.get_position()
2628                 try:
2629                         self.client.set_int(INITIAL_APP_WIDTH_PREFERENCES, width)
2630                         self.client.set_int(INITIAL_APP_HEIGHT_PREFERENCES, height)
2631                         self.client.set_int(INITIAL_APP_HPOS_PREFERENCES, hpos)
2632                         self.client.set_int(INITIAL_APP_VPOS_PREFERENCES, vpos)
2633                 except GError:
2634                         pass
2635 
2636                 self.w_main_window.hide()
2637                 while gtk.events_pending():
2638                         gtk.main_iteration(False)
2639                 gtk.main_quit()


3793                     self.set_show_filter != enumerations.FILTER_ALL:
3794                         self.__application_refilter()
3795                 else:
3796                         self.unset_busy_cursor()
3797                 
3798                 if self.first_run or self.in_reload:
3799                         Thread(target = self.__enable_disable_update_all).start()
3800                 self.first_run = False
3801                 self.in_reload = False
3802 
3803         def get_icon_pixbuf_from_glade_dir(self, icon_name):
3804                 return gui_misc.get_pixbuf_from_path(self.application_dir +
3805                     "/usr/share/package-manager/", icon_name)
3806 
3807         def update_statusbar(self):
3808                 '''Function which updates statusbar'''
3809                 if self.statusbar_message_id > 0:
3810                         self.w_main_statusbar.remove(0, self.statusbar_message_id)
3811                         self.statusbar_message_id = 0
3812                 search_text = self.w_searchentry.get_text()
3813                 if self.in_search_mode:
3814                         if self.is_search_all:
3815                                 opt_str = _('Searched All for "%s"') % (search_text)
3816                         else:
3817                                 opt_str = \
3818                                         _('Searched %(last_active)s '
3819                                             'for "%(search_text)s"') \
3820                                         % {"last_active" : self.last_active_publisher,
3821                                             "search_text" : search_text}
3822                         if len(self.application_list) == SEARCH_LIMIT:
3823                                 fmt_str = _("%(option_str)s:  first %(number)d "
3824                                     "found %(time)s")
3825                         else:
3826                                 fmt_str = _("%(option_str)s:  %(number)d found %(time)s")
3827                         time_str = ""
3828                         if self.search_time_sec > 0:
3829                                 time_str = _("in %d seconds") % self.search_time_sec
3830                         status_str = fmt_str % {"option_str" : opt_str,
3831                             "number" : len(self.application_list), "time" : time_str}
3832                         self.w_main_statusbar.push(0, status_str)
3833                         return
3834                 installed = 0
3835                 self.selected = 0
3836                 sel = 0
3837                 if self.application_list == None:
3838                         return
3839                 visible_repository = self.__get_visible_repository_name()
3840                 pkgs = self.selected_pkgs.get(visible_repository)
3841                 if pkgs:
3842                         self.selected = len(pkgs)
3843                 for pkg_row in self.application_list:
3844                         if pkg_row[enumerations.STATUS_COLUMN] == enumerations.INSTALLED \

3845                             or pkg_row[enumerations.STATUS_COLUMN] == \
3846                             enumerations.UPDATABLE:
3847                                 installed = installed + 1
3848                         if pkg_row[enumerations.MARK_COLUMN]:
3849                                 sel = sel + 1
3850                 listed_str = _('%d listed') % len(self.application_list)
3851                 sel_str = _('%d selected') % sel
3852                 inst_str = _('%d installed') % installed
3853                 status_str = _("%s: %s , %s, %s.") % (visible_repository, listed_str,
3854                         inst_str, sel_str)
3855                 self.w_main_statusbar.push(0, status_str)

3856 






























3857         def update_package_list(self, update_list):
3858                 if update_list == None and self.img_timestamp:
3859                         return
3860                 visible_repository = self.__get_visible_repository_name()
3861                 default_publisher = self.default_publisher
3862                 self.api_o.refresh()
3863                 if not self.img_timestamp:
3864                         self.img_timestamp = self.cache_o.get_index_timestamp()
3865                         self.__on_reload(None)
3866                         return
3867                 self.img_timestamp = self.cache_o.get_index_timestamp()
3868                 installed_icon = gui_misc.get_icon(self.icon_theme,
3869                     "status_installed")
3870                 visible_list = update_list.get(visible_repository)
3871                 if visible_list:
3872                         i = 0
3873                         while i < len(visible_list):
3874                                 visible_list[i] = gui_misc.get_pkg_name(
3875                                     visible_list[i])
3876                                 i +=  1




  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
  41 MAX_INFO_CACHE_LIMIT = 100                # Max number of package descriptions to cache
  42 NOTEBOOK_PACKAGE_LIST_PAGE = 0            # Main Package List page index
  43 NOTEBOOK_START_PAGE = 1                   # Main View Start page index
  44 INFO_NOTEBOOK_LICENSE_PAGE = 3            # License Tab index
  45 SHOW_INFO_DELAY = 600       # Delay before showing selected pacakge information
  46 SHOW_LICENSE_DELAY = 600    # Delay before showing license information
  47 SEARCH_STR_FORMAT = "<%s>"


  48 MIN_APP_WIDTH = 750                       # Minimum application width
  49 MIN_APP_HEIGHT = 500                     # Minimum application height
  50 INITIAL_APP_WIDTH_PREFERENCES = "/apps/packagemanager/preferences/initial_app_width"
  51 INITIAL_APP_HEIGHT_PREFERENCES = "/apps/packagemanager/preferences/initial_app_height"
  52 INITIAL_APP_HPOS_PREFERENCES = "/apps/packagemanager/preferences/initial_app_hposition"
  53 INITIAL_APP_VPOS_PREFERENCES = "/apps/packagemanager/preferences/initial_app_vposition"
  54 INITIAL_SHOW_FILTER_PREFERENCES = "/apps/packagemanager/preferences/initial_show_filter"
  55 INITIAL_SECTION_PREFERENCES = "/apps/packagemanager/preferences/initial_section"
  56 SHOW_STARTPAGE_PREFERENCES = "/apps/packagemanager/preferences/show_startpage"
  57 API_SEARCH_ERROR_PREFERENCES = "/apps/packagemanager/preferences/api_search_error"
  58 CATEGORIES_STATUS_COLUMN_INDEX = 0   # Index of Status Column in Categories TreeView
  59 
  60 STATUS_COLUMN_INDEX = 2   # Index of Status Column in Application TreeView
  61 
  62 PKG_CLIENT_NAME = "packagemanager"
  63 
  64 # Location for themable icons
  65 ICON_LOCATION = "usr/share/package-manager/icons"
  66 # Load Start Page from lang dir if available
  67 START_PAGE_CACHE_LANG_BASE = "var/pkg/gui_cache/startpagebase/%s/%s"


 251                 self.categories_status_id = 0
 252                 self.icon_theme = gtk.IconTheme()
 253                 icon_location = os.path.join(self.application_dir, ICON_LOCATION)
 254                 self.icon_theme.append_search_path(icon_location)
 255                 self.search_options = [
 256                     ('ips-search',
 257                     gui_misc.get_icon(self.icon_theme, 'search', 20),
 258                     _("_Current Repository"),
 259                     _("Search Current Repository")),
 260                     ('ips-search-all',
 261                     gui_misc.get_icon(self.icon_theme, 'search_all', 20),
 262                     _("_All Repositories"),
 263                     _("Search All Repositories"))
 264                     ]
 265                 self.__register_iconsets(self.search_options)               
 266                 self.visible_repository = None
 267                 self.visible_repository_uptodate = False
 268                 self.last_active_publisher = None
 269                 self.search_start = 0
 270                 self.search_time_sec = 0
 271                 self.current_search_publisher = None
 272                 self.section_list = None
 273                 self.filter_list = self.__get_new_filter_liststore()
 274                 self.application_list = None
 275                 self.a11y_application_treeview = None
 276                 self.a11y_categories_treeview = None
 277                 self.application_treeview_range = None
 278                 self.application_treeview_initialized = False
 279                 self.categories_treeview_range = None
 280                 self.categories_treeview_initialized = False
 281                 self.category_list = None
 282                 self.repositories_list = None
 283                 self.pr = progress.NullProgressTracker()
 284                 self.pylintstub = None
 285                 self.release_notes_url = "http://www.opensolaris.org"
 286                 self.__image_activity_lock = Lock()
 287 
 288                 # Create Widgets and show gui
 289                 self.gladefile = os.path.join(self.application_dir,
 290                     "usr/share/package-manager/packagemanager.glade")
 291                 w_tree_main = gtk.glade.XML(self.gladefile, "mainwindow")


 657                 is_search_all = (i != 0)
 658                 self.__update_repository_combobox_for_search(is_search_all)
 659                 if is_search_all:
 660                         self.__setup_before_search_all_mode()
 661                 else:
 662                         self.__restore_setup_for_browse()
 663                 self.changing_search_option = False
 664 
 665         def __update_repository_combobox_for_search(self, is_search_all):
 666                 if is_search_all:
 667                         self.saved_repository_combobox_active = \
 668                             self.w_repository_combobox.get_active()
 669                 self.__disconnect_repository_model()
 670                 if is_search_all:
 671                         self.repositories_list.prepend(
 672                             [-1, _("All Repositories Search Results"), ])
 673                 else:
 674                         self.repositories_list.remove(
 675                             self.repositories_list.get_iter_first())
 676                 self.w_repository_combobox.set_model(self.repositories_list)
 677                 #self.visible_repository = None
 678 
 679 
 680         def __link_load_blank(self):
 681                 self.document.clear()
 682                 self.document.open_stream('text/html')
 683                 self.document.write_stream(_(
 684                     "<html><head></head><body></body></html>"))
 685                 self.document.close_stream()
 686 
 687         def __search_menu_item_activate(self, widget):
 688                 name = widget.get_name()
 689                 i = 0
 690                 for stock_id, pixbuf, label, description in self.search_options:
 691                         if stock_id == name:
 692                                 self.__set_search_option(i)
 693                                 self.search_image.set_from_pixbuf(pixbuf)
 694                                 self.a11y_search_button.set_description(description)
 695                                 break
 696                         i += 1
 697                         self.pylintstub = label


 744                                 start_page_lang_base % (self.lang_root, START_PAGE_HOME))
 745                         if self.__load_uri(self.document, start_page_url):
 746                                 return True
 747 
 748                 start_page_url = os.path.join(self.application_dir,
 749                         start_page_lang_base % ("C", START_PAGE_HOME))
 750                 if self.__load_uri(self.document, start_page_url):
 751                         return True
 752                 return False
 753 
 754         def __handle_startpage_load_error(self, start_page_url):
 755                 self.document.open_stream('text/html')
 756                 self.document.write_stream(_(
 757                     "<html><head></head><body><H2>Welcome to"
 758                     "PackageManager!</H2><br>"
 759                     "<font color='#0000FF'>Warning: Unable to "
 760                     "load Start Page:<br>%s</font></body></html>"
 761                     % (start_page_url)))
 762                 self.document.close_stream()
 763 
 764         def __process_api_search_error(self, error):
 765                 self.current_repos_with_search_errors = []













 766 
 767                 for pub, err in error.failed_servers:
 768                         self.current_repos_with_search_errors.append(
 769                             (pub, _("failed to respond"), err))
 770                 for pub in error.invalid_servers:
 771                         self.current_repos_with_search_errors.append(
 772                             (pub, _("invalid response"),
 773                                 _("A valid response was not returned.")))
 774                 for pub, err in error.unsupported_servers:
 775                         self.current_repos_with_search_errors.append(
 776                             (pub, _("unsupported search"), err))
 777 
 778         def __on_infosearch_button_clicked(self, widget):
 779                 self.__handle_api_search_error(True)
 780 
 781         def __handle_api_search_error(self, show_all=False):
 782                 if len(self.current_repos_with_search_errors) == 0:
 783                         self.w_infosearch_frame.hide()
 784                         return



 785 

 786                 repo_count = 0
 787                 for pub, err_type, err_str in self.current_repos_with_search_errors:
 788                         if show_all or (pub not in self.gconf_not_show_repos):
 789                                 repo_count += 1
 790                 if repo_count == 0:
 791                         self.w_infosearch_frame.hide()
 792                         return
 793 
 794                 self.w_infosearch_button.set_size_request(26, 22)
 795                 self.w_infosearch_frame.show()
 796                 infobuffer = self.api_search_error_textview.get_buffer()
 797                 infobuffer.set_text("")
 798                 textiter = infobuffer.get_end_iter()
 799                 for pub, err_type, err_str in self.current_repos_with_search_errors:
 800 
 801                         if show_all or (pub not in self.gconf_not_show_repos):
 802                                 infobuffer.insert_with_tags_by_name(textiter,
 803                                     "%(pub)s (%(err_type)s)\n" % {"pub": pub,
 804                                     "err_type": err_type}, "bold")
 805                                 infobuffer.insert(textiter, "%s\n" % (err_str))
 806 
 807                 self.api_search_checkbox.set_active(False)
 808                 self.api_search_error_dialog.show()
 809                 self.api_search_button.grab_focus()
 810 
 811         def __get_repo_publishers(self):
 812                 repo_pub_dict = {}
 813                 pubs = self.api_o.get_publishers()
 814                 for pub in pubs:
 815                         repo = pub.selected_repository
 816                         origin = repo.origins[0]
 817                         repo_pub_dict[origin.uri] = pub.prefix
 818                 return repo_pub_dict
 819 
 820         def __on_url(self, view, link):
 821                 # Handle mouse over events on links and reset when not on link
 822                 if link == None or link == "":
 823                         self.update_statusbar()
 824                 else:
 825                         display_link = self.__handle_link(None, link, DISPLAY_LINK)
 826                         if display_link != None:


 997                         gobject.TYPE_STRING,      # enumerations.SECTION_NAME
 998                         gobject.TYPE_STRING,      # enumerations.SECTION_SUBCATEGORY
 999                         gobject.TYPE_BOOLEAN,     # enumerations.SECTION_ENABLED
1000                         )
1001 
1002         @staticmethod
1003         def __get_new_filter_liststore():
1004                 return gtk.ListStore(
1005                         gobject.TYPE_INT,         # enumerations.FILTER_ID
1006                         gobject.TYPE_STRING,      # enumerations.FILTER_NAME
1007                         )
1008 
1009         @staticmethod
1010         def __get_new_repositories_liststore():
1011                 return gtk.ListStore(
1012                         gobject.TYPE_INT,         # enumerations.REPOSITORY_ID
1013                         gobject.TYPE_STRING,      # enumerations.REPOSITORY_NAME
1014                         )
1015 
1016         def __init_application_tree_view(self, application_list,
1017             application_list_filter, application_list_sort,
1018             application_sort_column):
1019                 ##APPLICATION MAIN TREEVIEW
1020                 if application_list_filter == None:
1021                         application_list_filter = application_list.filter_new()
1022                 if application_list_sort == None:
1023                         application_list_sort = \
1024                             gtk.TreeModelSort(application_list_filter)
1025                         application_list_sort.set_sort_column_id(
1026                             application_sort_column, gtk.SORT_ASCENDING)
1027                         application_list_sort.set_sort_func(
1028                             enumerations.STATUS_ICON_COLUMN, self.__status_sort_func)
1029                 toggle_renderer = gtk.CellRendererToggle()
1030 
1031                 column = gtk.TreeViewColumn("", toggle_renderer, \
1032                     active = enumerations.MARK_COLUMN)
1033                 column.set_sort_column_id(enumerations.MARK_COLUMN)
1034                 column.set_sort_indicator(True)
1035                 column.set_cell_data_func(toggle_renderer, self.cell_data_function, None)
1036                 column.connect_after('clicked',
1037                     self.__application_treeview_column_sorted, None)
1038                 self.w_application_treeview.append_column(column)
1039                 name_renderer = gtk.CellRendererText()
1040                 column = gtk.TreeViewColumn(_("Name"), name_renderer,
1041                     text = enumerations.NAME_COLUMN)
1042                 column.set_resizable(True)
1043                 column.set_min_width(150)
1044                 column.set_sort_column_id(enumerations.NAME_COLUMN)
1045                 column.set_sort_indicator(True)
1046                 column.set_cell_data_func(name_renderer, self.cell_data_function, None)
1047                 column.connect_after('clicked',
1048                     self.__application_treeview_column_sorted, None)
1049                 self.w_application_treeview.append_column(column)
1050                 column = self.__create_icon_column(_("Status"), True,
1051                     enumerations.STATUS_ICON_COLUMN, True)
1052                 column.set_sort_column_id(enumerations.STATUS_ICON_COLUMN)
1053                 column.set_sort_indicator(True)
1054                 column.connect_after('clicked',
1055                     self.__application_treeview_column_sorted, None)
1056                 self.w_application_treeview.append_column(column)
1057                 if self.is_search_all:
1058                         repository_renderer = gtk.CellRendererText()
1059                         column = gtk.TreeViewColumn(_('Repository'),
1060                             repository_renderer,
1061                             text = enumerations.AUTHORITY_COLUMN)
1062                         column.set_sort_column_id(enumerations.AUTHORITY_COLUMN)
1063                         column.set_resizable(True)


1072                     description_renderer,
1073                     text = enumerations.DESCRIPTION_COLUMN)
1074                 column.set_sort_column_id(enumerations.DESCRIPTION_COLUMN)
1075                 column.set_resizable(True)
1076                 column.set_sort_indicator(True)
1077                 column.set_cell_data_func(description_renderer,
1078                     self.cell_data_function, None)
1079                 column.connect_after('clicked',
1080                     self.__application_treeview_column_sorted, None)
1081                 self.w_application_treeview.append_column(column)
1082                 #Added selection listener
1083                 self.package_selection = self.w_application_treeview.get_selection()
1084                 self.application_list = application_list
1085                 self.application_list_filter = application_list_filter
1086                 self.application_list_sort = application_list_sort
1087                 toggle_renderer.connect('toggled', self.__active_pane_toggle,
1088                     application_list_sort)
1089 
1090         def __init_tree_views(self, application_list, category_list, 
1091             section_list, application_list_filter = None, 
1092             application_list_sort = None, 
1093             application_sort_column = enumerations.NAME_COLUMN):
1094                 '''This function connects treeviews with their models and also applies
1095                 filters'''
1096                 if category_list == None:
1097                         self.w_application_treeview.set_model(None)
1098                         self.__remove_treeview_columns(self.w_application_treeview)
1099                 elif application_list == None:
1100                         self.w_categories_treeview.set_model(None)
1101                         self.__remove_treeview_columns(self.w_categories_treeview)
1102                 else:
1103                         self.__disconnect_models()
1104                         self.__remove_treeview_columns(self.w_application_treeview)
1105                         self.__remove_treeview_columns(self.w_categories_treeview)
1106                 # The logic for set section needs to be here as some sections
1107                 # might be not enabled. In such situation we are setting the set
1108                 # section to "All Categories" one.
1109                 if section_list != None:
1110                         row = section_list[self.set_section]
1111                         if row[enumerations.SECTION_ENABLED] and \
1112                             self.set_section >= 0 and \
1113                             self.set_section < len(section_list):
1114                                 if row[enumerations.SECTION_ID] != self.set_section:
1115                                         self.set_section = 0
1116                         else:
1117                                 self.set_section = 0
1118 
1119                 if application_list != None:
1120                         self.__init_application_tree_view(application_list,
1121                             application_list_filter, application_list_sort, 
1122                             application_sort_column)
1123 
1124                 if self.first_run:
1125                         # When vadj changes we need to set image descriptions
1126                         # on visible status icons. This catches moving the scroll bars
1127                         # and scrolling up and down using keyboard.
1128                         vadj = self.w_application_treeview.get_vadjustment()
1129                         vadj.connect('value-changed',
1130                             self.__application_treeview_vadjustment_changed, None)
1131                         vadj = self.w_categories_treeview.get_vadjustment()
1132                         vadj.connect('value-changed',
1133                             self.__categories_treeview_vadjustment_changed, None)
1134 
1135                         # When the size of the application_treeview changes
1136                         # we need to set image descriptions on visible status icons.
1137                         self.w_application_treeview.connect('size-allocate',
1138                             self.__application_treeview_size_allocate, None)
1139                         self.w_categories_treeview.connect('size-allocate',
1140                             self.__categories_treeview_size_allocate, None)
1141 
1142                 if category_list != None:


1302                 status = model.get_value(itr, enumerations.STATUS_COLUMN)
1303                 if status == enumerations.INSTALLED:
1304                         desc = _("Installed")
1305                 elif status == enumerations.NOT_INSTALLED:
1306                         desc = _("Not Installed")
1307                 elif status == enumerations.UPDATABLE:
1308                         desc = _("Updates Available")
1309                 else:
1310                         desc = None
1311                 if desc != None:
1312                         obj = self.a11y_application_treeview.ref_at(
1313                             int(model.get_string_from_iter(itr)),
1314                             STATUS_COLUMN_INDEX)
1315                         obj.set_image_description(desc)
1316 
1317         def __set_visible_status(self, check_range = True):
1318                 self.visible_status_id = 0
1319                 if self.w_main_view_notebook.get_current_page() != \
1320                     NOTEBOOK_PACKAGE_LIST_PAGE:
1321                         return
1322                 if self.__doing_search():
1323                         return
1324 
1325                 a11y_enabled = False
1326                 if self.a11y_application_treeview.get_n_accessible_children() != 0:
1327                         a11y_enabled = True
1328 
1329                 visible_range = self.w_application_treeview.get_visible_range()
1330                 if visible_range == None:
1331                         return
1332                 start = visible_range[0][0]
1333                 end = visible_range[1][0]
1334                 if debug_descriptions:
1335                         print "Range Start: %d End: %d" % (start, end)
1336 
1337                 # Switching Publishers need to use default range
1338                 active_pub = self.__get_active_publisher()
1339                 if self.last_active_publisher != active_pub:
1340                         check_range = False
1341                 self.last_active_publisher = active_pub
1342                 if self.in_search_mode:
1343                         check_range = False
1344                 


1361                 self.application_treeview_range = visible_range
1362 
1363                 sort_filt_model = \
1364                     self.w_application_treeview.get_model() #gtk.TreeModelSort
1365                 filt_model = sort_filt_model.get_model() #gtk.TreeModelFilter
1366                 model = filt_model.get_model() #gtk.ListStore
1367                 sf_itr = sort_filt_model.get_iter_from_string(str(start))                
1368                 pkg_stems_and_itr_to_fetch = {}
1369                 while start <= end:
1370                         filtered_itr = sort_filt_model.convert_iter_to_child_iter(None,
1371                             sf_itr)
1372                         app_itr = filt_model.convert_iter_to_child_iter(filtered_itr)
1373 
1374                         desc = sort_filt_model.get_value(sf_itr,
1375                             enumerations.DESCRIPTION_COLUMN)
1376                         # Only Fetch description for packages without a
1377                         # description
1378                         if desc == '...':
1379                                 fmri = sort_filt_model.get_value(sf_itr,
1380                                     enumerations.FMRI_COLUMN)
1381                                 if fmri != None:
1382                                         pkg_stem = fmri.get_pkg_stem(
1383                                             include_scheme = True)
1384                                         pkg_stems_and_itr_to_fetch[pkg_stem] = \
1385                                             model.get_string_from_iter(app_itr)
1386                         if a11y_enabled:
1387                                 self.__set_accessible_status(sort_filt_model, sf_itr)
1388                         start += 1
1389                         sf_itr = sort_filt_model.iter_next(sf_itr)
1390 
1391                 if debug_descriptions:
1392                         print "PKGS to FETCH: \n%s" % pkg_stems_and_itr_to_fetch
1393                 if len(pkg_stems_and_itr_to_fetch) > 0:
1394                         Thread(target = self.__get_pkg_descriptions,
1395                             args = [pkg_stems_and_itr_to_fetch, model]).start() 
1396                     
1397         def __doing_search(self):
1398                 return self.search_start > 0
1399                 
1400         def __get_pkg_descriptions(self, pkg_stems_and_itr_to_fetch, orig_model):
1401                 # Note: no need to aquire lock even though this can be called from


1412                 except api_errors.TransportError:
1413                         self.update_statusbar()
1414                         return
1415                 if info and len(info.get(0)) == 0:
1416                         self.update_statusbar()
1417                         return
1418                 pkg_infos = info.get(0)
1419                 pkg_descriptions_for_update = []
1420                 for pkg_info in pkg_infos:
1421                         short_fmri = fmri.PkgFmri(pkg_info.fmri).get_pkg_stem(
1422                             include_scheme = True)
1423                         pkg_descriptions_for_update.append((short_fmri,
1424                             pkg_stems_and_itr_to_fetch[short_fmri],
1425                             pkg_info.summary))
1426                 if debug_descriptions:
1427                         print "FETCHED PKGS: \n%s" % pkg_descriptions_for_update
1428                 gobject.idle_add(self.__update_description_from_iter,
1429                     pkg_descriptions_for_update, orig_model)
1430 
1431         def __update_description_from_iter(self, pkg_descriptions_for_update, orig_model):
1432                 #If doing a search abandon description updates
1433                 if self.__doing_search():
1434                         return
1435 
1436                 sort_filt_model = \
1437                     self.w_application_treeview.get_model() #gtk.TreeModelSort
1438                 filt_model = sort_filt_model.get_model() #gtk.TreeModelFilter
1439                 model = filt_model.get_model() #gtk.ListStore
1440 
1441                 #If model has changed abandon description updates
1442                 if orig_model != model:
1443                         return
1444 
1445                 if debug_descriptions:
1446                         print "UPDATE DESCRIPTIONS: \n%s" % pkg_descriptions_for_update
1447                 for pkg_stem, path, summary in pkg_descriptions_for_update:
1448                         itr = model.get_iter_from_string(path)
1449                         stored_pkg_fmri = model.get_value(itr, enumerations.FMRI_COLUMN)
1450                         stored_pkg_stem = stored_pkg_fmri.get_pkg_stem(
1451                             include_scheme = True)
1452 
1453                         if pkg_stem != stored_pkg_stem:
1454                                 if debug:
1455                                         print ("__update_description_from_iter(): "


1728                 self.search_time_sec = 0
1729                 text = self.w_searchentry.get_text()
1730                 # Here we call the search API to get the results
1731                 searches = []
1732                 servers = []
1733                 result = []
1734                 pargs = []
1735                 search_str = SEARCH_STR_FORMAT % text
1736                 pargs.append(search_str)
1737                 if search_all:
1738                         servers = None
1739                 else:
1740                         pub_prefix = self.__get_active_publisher()
1741                         if pub_prefix != None:
1742                                 pub = self.api_o.get_publisher(prefix=pub_prefix)
1743                         else:
1744                                 pub = self.api_o.get_preferred_publisher()
1745                         origin_uri = self.__get_origin_uri(pub.selected_repository)
1746                         servers.append({"origin": origin_uri})
1747                 if debug:
1748                         print "Search: pargs %s servers: %s" % (pargs, servers)

1749 
1750                 #TBD If we ever search just Installed pkgs should allow for a local search
1751                 case_sensitive = False
1752                 return_actions = True
1753                 searches.append(self.api_o.remote_search(
1754                     [api.Query(" ".join(pargs), case_sensitive, return_actions)],
1755                     servers=servers))
1756                 if debug:
1757                         print "Search Args: %s : cs: %s : retact: %s" % \
1758                                 ("".join(pargs), case_sensitive, return_actions)
1759 
1760                 last_name = ""
1761                 self.current_search_publisher = None
1762 
1763                 # Sorting results by Name gives best overall appearance and flow
1764                 sort_col = enumerations.NAME_COLUMN
1765                 try:
1766                         for query_num, publisher, (v, return_type, tmp) in \
1767                             itertools.chain(*searches):
1768                                 if v < 1 or return_type != api.Query.RETURN_PACKAGES:











1769                                         gobject.idle_add(self.w_progress_dialog.hide)
1770                                         self.__process_after_search_failure()
1771                                         return
1772 
1773                                 pub = None
1774                                 if publisher is not None \
1775                                     and "prefix" in publisher:
1776                                         pub = publisher["prefix"]
1777                                 name = fmri.PkgFmri(str(tmp)).get_name()
1778                                 if last_name != name:
1779                                         if debug:
1780                                                 print "Result Name: %s (%s)" % (name, pub)
1781                                         a_res = name, pub
1782                                         result.append(a_res)
1783                                         #Ignore Status when fetching
1784                                         application_list = \
1785                                                 self.__get_min_list_from_search(result)
1786                                         self.current_search_publisher = pub
1787                                         self.in_setup = True
1788                                         gobject.idle_add(self.__init_tree_views, 
1789                                             application_list, None, None, None, None,
1790                                             sort_col)
1791                                 last_name = name
1792                                 self.pylintstub = query_num
1793                 except api_errors.ProblematicSearchServers, ex:
1794                         self.__process_api_search_error(ex)
1795                         gobject.idle_add(self.w_progress_dialog.hide)
1796                         gobject.idle_add(self.__handle_api_search_error)
1797                         if len(result) == 0:
1798                                 self.__process_after_search_with_zero_results()
1799                                 return
1800                 except Exception, ex:
1801                         # We are not interested in this error
1802                         gobject.idle_add(self.w_progress_dialog.hide)
1803                         self.__process_after_search_failure()
1804                         return
1805                 if debug:
1806                         print "Number of search results:", len(result)



1807                 if len(result) == 0:
1808                         if debug:
1809                                 print "No search results"
1810                         self.__process_after_search_with_zero_results()
1811                         return
1812                 # We cannot get status of the packages if catalogs have not
1813                 # been loaded so we pause for up to 5 seconds here to
1814                 # allow catalogs to be loaded
1815                 times = 5
1816                 while self.catalog_loaded == False:
1817                         if times == 0:
1818                                 break
1819                         time.sleep(1)
1820                         times -= 1
1821 
1822                 #Now fetch full result set with Status
1823                 self.in_setup = True
1824                 application_list = self.__get_full_list_from_search(result)
1825                 gobject.idle_add(self.__init_tree_views, application_list, None, None, \
1826                     None, None, sort_col)
1827 
1828                 if self.search_start > 0:
1829                         self.search_time_sec = int(time.time() - self.search_start)
1830                         if debug:
1831                                 print "Search time: %d (sec)" % self.search_time_sec
1832                 self.search_start = 0




1833 
1834         def __process_after_search_with_zero_results(self):
1835                 if self.search_start > 0:
1836                         self.search_time_sec = int(time.time() - self.search_start)
1837                 self.search_start = 0
1838                 self.in_setup = True
1839                 application_list = self.__get_new_application_liststore()
1840                 gobject.idle_add(self.__set_empty_details_panel)
1841                 gobject.idle_add(self.__set_main_view_package_list)
1842                 gobject.idle_add(self.__init_tree_views, application_list, None, None)
1843 
1844         def __get_min_list_from_search(self, search_result):
1845                 application_list = self.__get_new_application_liststore()
1846                 for name, publisher in search_result:
1847                         application_list.append(
1848                             [False, None, name, '...', enumerations.NOT_INSTALLED, None, 
1849                             "pkg://" + publisher + "/" + name, None, True, None, 
1850                             publisher])
1851                 return application_list
1852 
1853         def __get_full_list_from_search(self, search_result):
1854                 application_list = self.__get_new_application_liststore()
1855                 self.__add_pkgs_to_list_from_search(search_result,
1856                     application_list)
1857                 return application_list
1858 
1859         def __add_pkgs_to_list_from_search(self, search_result,
1860             application_list):
1861                 pargs = []
1862                 default_pub = self.api_o.get_preferred_publisher().prefix
1863                 for name, publisher in search_result:
1864                         pargs.append("pkg://" + publisher + "/" + name)
1865                 # We now need to get the status for each package
1866                 if debug_descriptions:
1867                         print "pargs:", pargs
1868                 try:
1869                         pkgs_known = self.__get_inventory_list(pargs,
1870                             True, True)
1871                 except api_errors.InventoryException:
1872                         # This can happen if load_catalogs has not been run
1873                         err = _("Unable to get status for search results.\n"
1874                             "The catalogs have not been loaded.\n"


2101                 self.w_preferencesdialog.show()
2102 
2103         def __on_preferencesclose_clicked(self, widget):
2104                 self.w_preferencesdialog.hide()
2105 
2106         def __on_preferenceshelp_clicked(self, widget):
2107                 gui_misc.display_help(self.application_dir, "pm_win")
2108 
2109         def __on_startpage_checkbutton_toggled(self, widget):
2110                 self.show_startpage = self.w_startpage_checkbutton.get_active()
2111                 try:
2112                         self.client.set_bool(SHOW_STARTPAGE_PREFERENCES,
2113                             self.show_startpage)
2114                 except GError:
2115                         pass
2116 
2117         def __on_api_search_checkbox_toggled(self, widget):
2118                 active = self.api_search_checkbox.get_active()
2119                 if len(self.current_repos_with_search_errors) > 0:
2120                         if active:
2121                                 for pub, err_type, err_str in \
2122                                         self.current_repos_with_search_errors:
2123                                         if pub not in self.gconf_not_show_repos:
2124                                                 self.gconf_not_show_repos += pub + ","
2125                         else:
2126                                 for pub, err_type, err_str in \
2127                                         self.current_repos_with_search_errors:
2128                                         self.gconf_not_show_repos = \
2129                                             self.gconf_not_show_repos.replace(
2130                                             pub + ",", "")
2131                         try:
2132                                 self.client.set_string(API_SEARCH_ERROR_PREFERENCES,
2133                                     self.gconf_not_show_repos)
2134                         except GError:
2135                                 pass
2136 
2137         def __on_searchentry_focus_in(self, widget, event):
2138                 if self.w_main_clipboard.wait_is_text_available():
2139                         self.w_paste_menuitem.set_sensitive(True)
2140                 char_count = widget.get_text_length()
2141                 if char_count > 0:
2142                         self.w_selectall_menuitem.set_sensitive(True)
2143                 else:
2144                         self.w_selectall_menuitem.set_sensitive(False)
2145                 bounds = widget.get_selection_bounds()
2146                 if bounds:
2147                         offset1 = bounds[0]
2148                         offset2 = bounds[1] 
2149                         if abs(offset2 - offset1) == char_count:
2150                                 self.w_selectall_menuitem.set_sensitive(False)


2451                                 start, end = self.w_searchentry.get_selection_bounds()
2452                                 self.w_searchentry.select_region(end, end)
2453 
2454                 pub = [active_publisher, ]
2455                 self.set_show_filter = self.initial_show_filter
2456                 self.set_section = self.initial_section
2457                 Thread(target = self.__setup_publisher, args = [pub]).start()
2458                 self.__set_main_view_package_list()
2459 
2460         def __get_active_publisher(self):
2461                 pub_iter = self.w_repository_combobox.get_active_iter()
2462                 if pub_iter == None:
2463                         return None
2464                 return self.repositories_list.get_value(pub_iter, \
2465                             enumerations.REPOSITORY_NAME)
2466 
2467         def __setup_publisher(self, publishers=[]):
2468                 self.saved_filter_combobox_active = self.initial_show_filter
2469                 application_list, category_list , section_list = \
2470                     self.__get_application_categories_lists(publishers)
2471                 self.__unset_saved()
2472                 gobject.idle_add(self.__init_tree_views, application_list,
2473                     category_list, section_list)
2474 
2475         def __unset_saved(self):
2476                 self.saved_application_list = None
2477                 self.saved_application_list_filter = None
2478                 self.saved_application_list_sort = None
2479                 self.saved_category_list = None
2480                 self.saved_section_list = None
2481 
2482         def __get_application_categories_lists(self, publishers=[]):
2483                 if not self.visible_repository:
2484                         self.visible_repository = self.__get_active_publisher()
2485                 application_list = self.__get_new_application_liststore()
2486                 category_list = self.__get_new_category_liststore()
2487                 section_list = self.__get_new_section_liststore()
2488                 first_loop = True
2489                 for publisher in publishers:
2490                         uptodate = False
2491                         try:
2492                                 uptodate = self.__check_if_cache_uptodate(publisher)
2493                                 if uptodate:
2494                                         self.__add_pkgs_to_lists_from_cache(publisher,
2495                                             application_list, category_list,
2496                                             section_list)
2497                         except (UnpicklingError, EOFError, IOError):
2498                                 #Most likely cache is corrupted, silently load list
2499                                 #from api.
2500                                 application_list = self.__get_new_application_liststore()
2501                                 category_list = self.__get_new_category_liststore()
2502                                 uptodate = False
2503                         if not uptodate:
2504                                 if first_loop == True:
2505                                         first_loop = False
2506                                         gobject.idle_add(self.setup_progressdialog_show)
2507                                 self.api_o.refresh(pubs=[publisher])
2508                                 self.__add_pkgs_to_lists_from_api(publisher,
2509                                     application_list, category_list, section_list)
2510                                 category_list.prepend([0, _('All'), None, None, False,
2511                                     True, None])
2512                         if self.application_list and self.category_list and \
2513                             not self.visible_repository_uptodate:
2514                                 if self.visible_repository:
2515                                         dump_list = self.application_list
2516                                         if self.saved_application_list != None:
2517                                                 dump_list = \
2518                                                     self.saved_application_list
2519                                         self.__dump_datamodels(self.visible_repository,
2520                                             dump_list, self.category_list,
2521                                             self.section_list)
2522                         self.visible_repository = self.__get_active_publisher()
2523                         self.visible_repository_uptodate = uptodate
2524                 return application_list, category_list, section_list
2525 
2526         def __check_if_cache_uptodate(self, publisher):
2527                 if self.cache_o:
2528                         return self.cache_o.check_if_cache_uptodate(publisher)
2529                 return False
2530 
2531         def __dump_datamodels(self, publisher, application_list, category_list,
2532             section_list):
2533                 #Consistency check - only dump models if publisher passed in matches 
2534                 #publisher in application list
2535                 if application_list == None:
2536                         return
2537                 app_pub = application_list[0][enumerations.AUTHORITY_COLUMN]
2538                 if publisher != app_pub:
2539                         if debug:
2540                                 print "ERROR: __dump_data_models(): INCONSISTENT " \
2541                                         "pub %s != app_list_pub %s" % \
2542                                         (publisher,  app_pub)
2543                         return
2544 
2545                 if self.cache_o:
2546                         if self.img_timestamp == \
2547                             self.cache_o.get_index_timestamp():
2548                                 Thread(target = self.cache_o.dump_datamodels,
2549                                     args = (publisher, application_list, category_list,
2550                                     section_list)).start()
2551                         else:
2552                                 self.__remove_cache()
2553 
2554         def __remove_cache(self):
2555                 model = self.w_repository_combobox.get_model()
2556                 for publisher in model:
2557                         pub_name = publisher[1]
2558                         if pub_name and pub_name != _("Add..."):
2559                                 Thread(target = self.cache_o.remove_datamodel,
2560                                     args = [publisher[1]]).start()
2561 
2562         def __on_install_update(self, widget):
2563                 self.api_o.reset()
2564                 install_update = []


2663                 #Let the progress_pulse finish. This should be done other way, but at
2664                 #The moment this works fine
2665                 time.sleep(0.2)
2666                 gobject.idle_add(self.w_progress_cancel.show)
2667                 gobject.idle_add(self.process_package_list_start,
2668                     self.image_directory)
2669 
2670         def __main_application_quit(self, be_name = None):
2671                 '''quits the main gtk loop'''
2672                 self.cancelled = True
2673                 if self.in_setup:
2674                         return
2675 
2676                 if be_name:
2677                         if self.image_dir_arg:
2678                                 gobject.spawn_async([self.application_path, "-R",
2679                                     self.image_dir_arg, "-U", be_name])
2680                         else:
2681                                 gobject.spawn_async([self.application_path,
2682                                     "-U", be_name])
2683                 elif self.in_search_mode:
2684                         self.__dump_datamodels(self.visible_repository,
2685                             self.saved_application_list, self.category_list,
2686                             self.section_list)
2687                 else:
2688                         visible_repository = self.__get_visible_repository_name()
2689                         self.__dump_datamodels(visible_repository,
2690                                 self.application_list, self.category_list,
2691                                 self.section_list)
2692 
2693                 width, height = self.w_main_window.get_size()
2694                 hpos = self.w_main_hpaned.get_position()
2695                 vpos = self.w_main_vpaned.get_position()
2696                 try:
2697                         self.client.set_int(INITIAL_APP_WIDTH_PREFERENCES, width)
2698                         self.client.set_int(INITIAL_APP_HEIGHT_PREFERENCES, height)
2699                         self.client.set_int(INITIAL_APP_HPOS_PREFERENCES, hpos)
2700                         self.client.set_int(INITIAL_APP_VPOS_PREFERENCES, vpos)
2701                 except GError:
2702                         pass
2703 
2704                 self.w_main_window.hide()
2705                 while gtk.events_pending():
2706                         gtk.main_iteration(False)
2707                 gtk.main_quit()


3861                     self.set_show_filter != enumerations.FILTER_ALL:
3862                         self.__application_refilter()
3863                 else:
3864                         self.unset_busy_cursor()
3865                 
3866                 if self.first_run or self.in_reload:
3867                         Thread(target = self.__enable_disable_update_all).start()
3868                 self.first_run = False
3869                 self.in_reload = False
3870 
3871         def get_icon_pixbuf_from_glade_dir(self, icon_name):
3872                 return gui_misc.get_pixbuf_from_path(self.application_dir +
3873                     "/usr/share/package-manager/", icon_name)
3874 
3875         def update_statusbar(self):
3876                 '''Function which updates statusbar'''
3877                 if self.statusbar_message_id > 0:
3878                         self.w_main_statusbar.remove(0, self.statusbar_message_id)
3879                         self.statusbar_message_id = 0
3880                 search_text = self.w_searchentry.get_text()
3881 
3882                 if not self.in_search_mode:



















3883                         installed = 0
3884                         self.selected = 0
3885                         sel = 0
3886                         if self.application_list == None:
3887                                 return
3888                         visible_repository = self.__get_visible_repository_name()
3889                         pkgs = self.selected_pkgs.get(visible_repository)
3890                         if pkgs:
3891                                 self.selected = len(pkgs)
3892                         for pkg_row in self.application_list:
3893                                 if pkg_row[enumerations.STATUS_COLUMN] == \
3894                                         enumerations.INSTALLED \
3895                                         or pkg_row[enumerations.STATUS_COLUMN] == \
3896                                     enumerations.UPDATABLE:
3897                                         installed = installed + 1
3898                                 if pkg_row[enumerations.MARK_COLUMN]:
3899                                         sel = sel + 1
3900                         listed_str = _('%d listed') % len(self.application_list)
3901                         sel_str = _('%d selected') % sel
3902                         inst_str = _('%d installed') % installed
3903                         status_str = _("%s: %s , %s, %s.") % (visible_repository,
3904                             listed_str, inst_str, sel_str)
3905                         self.w_main_statusbar.push(0, status_str)
3906                         return
3907 
3908                 # In Search Mode
3909                 active = ""
3910                 if self.is_search_all:
3911                         if self.__doing_search():
3912                                 if self.current_search_publisher != None:
3913                                         active = "(" + self.current_search_publisher + \
3914                                                 ") "
3915                                 opt_str = _('Searching... '
3916                                     '%(active)sfor "%(search_text)s"') % \
3917                                         {"active": active, "search_text": search_text}
3918                         else:
3919                                 opt_str = _('Searched All for "%s"') % (search_text)
3920                 else:
3921                         search_str = _("Searched")
3922                         if self.__doing_search():
3923                                 search_str = _("Searching...")
3924                         if self.last_active_publisher != None:
3925                                 active = "(" + self.last_active_publisher + ") "
3926                         opt_str = \
3927                                 _('%(search)s %(last_active)sfor "%(search_text)s"') \
3928                                 % {"search": search_str, "last_active" : active,
3929                                     "search_text" : search_text}
3930                 fmt_str = _("%(option_str)s:  %(number)d found %(time)s")
3931                 time_str = ""
3932                 if self.search_time_sec > 0:
3933                         time_str = _("in %d seconds") % self.search_time_sec
3934                 status_str = fmt_str % {"option_str" : opt_str, "number" :
3935                     len(self.application_list), "time" : time_str}
3936                 self.w_main_statusbar.push(0, status_str)
3937 
3938         def update_package_list(self, update_list):
3939                 if update_list == None and self.img_timestamp:
3940                         return
3941                 visible_repository = self.__get_visible_repository_name()
3942                 default_publisher = self.default_publisher
3943                 self.api_o.refresh()
3944                 if not self.img_timestamp:
3945                         self.img_timestamp = self.cache_o.get_index_timestamp()
3946                         self.__on_reload(None)
3947                         return
3948                 self.img_timestamp = self.cache_o.get_index_timestamp()
3949                 installed_icon = gui_misc.get_icon(self.icon_theme,
3950                     "status_installed")
3951                 visible_list = update_list.get(visible_repository)
3952                 if visible_list:
3953                         i = 0
3954                         while i < len(visible_list):
3955                                 visible_list[i] = gui_misc.get_pkg_name(
3956                                     visible_list[i])
3957                                 i +=  1