Print this page
*** NO COMMENTS ***


  22 # Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
  23 # Use is subject to license terms.
  24 #
  25 
  26 # Progress:
  27 # Startup Progress has two phases:
  28 # - Start phase:
  29 #   The start phase should be fairly constant at around a few seconds and so is given 5%
  30 #   of the total progress bar.
  31 # - Package entry loading phase:
  32 #   The package entry loading phase is given the remaining 95% of the bar for progress.
  33 
  34 INITIAL_PROGRESS_TIME_INTERVAL = 0.5      # Time to update progress during start phase
  35 INITIAL_PROGRESS_TIME_PERCENTAGE = 0.005  # Amount to update progress during start phase
  36 INITIAL_PROGRESS_TOTAL_PERCENTAGE = 0.05  # Total progress for start phase
  37 PACKAGE_PROGRESS_TOTAL_INCREMENTS = 95    # 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 TYPE_AHEAD_DELAY = 600    # Time of the last type in search box after which search is performed
  43 
  44 CLIENT_API_VERSION = 4
  45 PKG_CLIENT_NAME = "packagemanager"
  46 
  47 import getopt
  48 import os
  49 import sys
  50 import time
  51 import locale
  52 import urlparse
  53 import socket
  54 import gettext
  55 from threading import Thread
  56 from urllib2 import HTTPError, URLError
  57 
  58 try:
  59         import gobject
  60         import gnome
  61         gobject.threads_init()
  62         import gtk
  63         import gtk.glade
  64         import pygtk
  65         pygtk.require("2.0")
  66 except ImportError:
  67         sys.exit(1)
  68 import pkg.client.history as history
  69 import pkg.client.image as image
  70 import pkg.client.progress as progress
  71 import pkg.client.api_errors as api_errors
  72 import pkg.client.api as api
  73 import pkg.client.retrieve as retrieve
  74 import pkg.portable as portable
  75 import pkg.gui.repository as repository
  76 import pkg.gui.beadmin as beadm
  77 import pkg.gui.imageinfo as imageinfo
  78 import pkg.gui.installupdate as installupdate
  79 import pkg.gui.enumerations as enumerations
  80 from pkg.client import global_settings
  81 
  82 # Put _() in the global namespace
  83 import __builtin__
  84 __builtin__._ = gettext.gettext
  85 
  86 class PackageManager:
  87         def __init__(self):
  88                 self.api_o = None
  89                 socket.setdefaulttimeout(


 256                             }
 257                         dic_progress = \
 258                             {
 259                                 "on_cancel_progressdialog_clicked": \
 260                                     self.__on_cancel_progressdialog_clicked,
 261                             }
 262                         w_tree_main.signal_autoconnect(dic_mainwindow)
 263                         w_tree_progress.signal_autoconnect(dic_progress)
 264                 except AttributeError, error:
 265                         print self._( \
 266                             'GUI will not respond to any event! %s.' + \
 267                             'Check declare_signals()') \
 268                             % error
 269                             
 270                 self.package_selection = None
 271                 self.category_list_filter = None
 272                 self.application_list_filter = None
 273                 self.application_refilter_id = 0 
 274                 self.in_setup = True
 275                 self.w_main_window.show_all()





 276 
 277         @staticmethod
 278         def __get_new_application_liststore():
 279                 return gtk.ListStore(
 280                         gobject.TYPE_BOOLEAN,     # enumerations.MARK_COLUMN
 281                         gtk.gdk.Pixbuf,           # enumerations.STATUS_ICON_COLUMN
 282                         gtk.gdk.Pixbuf,           # enumerations.ICON_COLUMN
 283                         gobject.TYPE_STRING,      # enumerations.NAME_COLUMN
 284                         gobject.TYPE_STRING,      # enumerations.INSTALLED_VERSION_COLUMN
 285                         gobject.TYPE_PYOBJECT,    # enumerations.INSTALLED_OBJECT_COLUMN
 286                         gobject.TYPE_STRING,      # enumerations.LATEST_AVAILABLE_COLUMN
 287                         gobject.TYPE_INT,         # enumerations.RATING_COLUMN
 288                         gobject.TYPE_STRING,      # enumerations.DESCRIPTION_COLUMN
 289                         gobject.TYPE_PYOBJECT,    # enumerations.PACKAGE_OBJECT_COLUMN



 290                         gobject.TYPE_BOOLEAN,     # enumerations.IS_VISIBLE_COLUMN
 291                         gobject.TYPE_PYOBJECT     # enumerations.CATEGORY_LIST_OBJECT
 292                         )
 293 
 294         @staticmethod
 295         def __get_new_category_liststore():
 296                 return gtk.ListStore(
 297                         gobject.TYPE_INT,         # enumerations.CATEGORY_ID
 298                         gobject.TYPE_STRING,      # enumerations.CATEGORY_NAME
 299                         gobject.TYPE_STRING,      # enumerations.CATEGORY_DESCRIPTION
 300                         gtk.gdk.Pixbuf,           # enumerations.CATEGORY_ICON
 301                         gobject.TYPE_BOOLEAN,     # enumerations.CATEGORY_VISIBLE
 302                         gobject.TYPE_PYOBJECT,    # enumerations.SECTION_LIST_OBJECT
 303                         )
 304 
 305         @staticmethod
 306         def __get_new_section_liststore():
 307                 return gtk.ListStore(
 308                         gobject.TYPE_INT,         # enumerations.SECTION_ID
 309                         gobject.TYPE_STRING,      # enumerations.SECTION_NAME
 310                         )
 311 


 359                 column = gtk.TreeViewColumn(self._("Name"), name_renderer, \
 360                     text = enumerations.NAME_COLUMN)
 361                 column.set_resizable(True)
 362                 column.set_sort_column_id(enumerations.NAME_COLUMN)
 363                 column.set_sort_indicator(True)
 364                 column.set_cell_data_func(name_renderer, self.cell_data_function, None)
 365                 self.w_application_treeview.append_column(column)
 366                 column = gtk.TreeViewColumn()
 367                 column.set_title(self._("Status"))
 368                 #Commented, since there was funny jumping of the icons
 369                 #column.set_sizing(gtk.TREE_VIEW_COLUMN_AUTOSIZE)
 370                 render_pixbuf = gtk.CellRendererPixbuf()
 371                 column.pack_start(render_pixbuf, expand = True)
 372                 column.add_attribute(render_pixbuf, "pixbuf", \
 373                     enumerations.STATUS_ICON_COLUMN)
 374                 column.set_fixed_width(32)
 375                 column.set_sort_column_id(enumerations.STATUS_ICON_COLUMN)
 376                 column.set_sort_indicator(True)
 377                 column.set_cell_data_func(render_pixbuf, self.cell_data_function, None)
 378                 self.w_application_treeview.append_column(column)
 379                 installed_version_renderer = gtk.CellRendererText()
 380                 column = gtk.TreeViewColumn(self._('Installed Version'), \
 381                     installed_version_renderer, \
 382                     text = enumerations.INSTALLED_VERSION_COLUMN)
 383                 column.set_sort_column_id(enumerations.INSTALLED_VERSION_COLUMN)
 384                 column.set_sort_indicator(True)
 385                 column.set_cell_data_func(installed_version_renderer, \
 386                     self.cell_data_function, None)
 387                 latest_available_renderer = gtk.CellRendererText()
 388                 column = gtk.TreeViewColumn(self._('Latest Version'), \
 389                     latest_available_renderer, \
 390                     text = enumerations.LATEST_AVAILABLE_COLUMN)
 391                 column.set_sort_column_id(enumerations.LATEST_AVAILABLE_COLUMN)
 392                 column.set_sort_indicator(True)
 393                 column.set_cell_data_func(latest_available_renderer, \
 394                     self.cell_data_function, None)
 395                 rating_renderer = gtk.CellRendererText()
 396                 column = gtk.TreeViewColumn(self._('Rating'), rating_renderer, \
 397                     text = enumerations.RATING_COLUMN)
 398                 column.set_cell_data_func(rating_renderer, self.cell_data_function, None)
 399                 description_renderer = gtk.CellRendererText()
 400                 column = gtk.TreeViewColumn(self._('Description'), \
 401                     description_renderer, text = enumerations.DESCRIPTION_COLUMN)
 402                 column.set_resizable(True)
 403                 column.set_sort_column_id(enumerations.DESCRIPTION_COLUMN)
 404                 column.set_sort_indicator(True)
 405                 column.set_cell_data_func(description_renderer, \
 406                     self.cell_data_function, None)
 407                 self.w_application_treeview.append_column(column)
 408                 #Added selection listener
 409                 self.package_selection = self.w_application_treeview.get_selection()
 410 
 411                 ##CATEGORIES TREEVIEW
 412                 #enumerations.CATEGORY_NAME
 413                 category_list_filter = category_list.filter_new()
 414                 enumerations.CATEGORY_NAME_renderer = gtk.CellRendererText()
 415                 column = gtk.TreeViewColumn(self._('Name'), \
 416                     enumerations.CATEGORY_NAME_renderer, \
 417                     text = enumerations.CATEGORY_NAME)
 418                 self.w_categories_treeview.append_column(column)


 463                 category_list_filter.set_visible_func(self.category_filter)
 464                 toggle_renderer.connect('toggled', self.__active_pane_toggle, \
 465                     application_list_sort)
 466                 category_selection.connect("changed", \
 467                     self.__on_category_selection_changed, None)
 468                 self.package_selection.set_mode(gtk.SELECTION_SINGLE)
 469                 self.package_selection.connect("changed", \
 470                     self.__on_package_selection_changed, None)
 471                 self.first_run = False
 472                 
 473         def __disconnect_models(self):
 474                 self.w_application_treeview.set_model(None)
 475                 self.w_categories_treeview.set_model(None)
 476                 self.w_repository_combobox.set_model(None)
 477                 self.w_sections_combobox.set_model(None)
 478                 self.w_filter_combobox.set_model(None)
 479 
 480         @staticmethod
 481         def __status_sort_func(treemodel, iter1, iter2, user_data=None):
 482                 get_val = treemodel.get_value
 483                 lat1 = get_val(iter1, enumerations.LATEST_AVAILABLE_COLUMN)
 484                 ins1 = get_val(iter1, enumerations.INSTALLED_VERSION_COLUMN)
 485                 lat2 = get_val(iter2, enumerations.LATEST_AVAILABLE_COLUMN)
 486                 ins2 = get_val(iter2, enumerations.INSTALLED_VERSION_COLUMN)
 487                 if ins1 and not ins2:
 488                         return -1
 489                 if ins2 and not ins1:
 490                         return 1
 491                 if lat1 and not lat2:
 492                         return -1
 493                 if lat2 and not lat1:
 494                         return 1
 495                 return 0
 496 
 497         @staticmethod
 498         def __remove_treeview_columns(treeview):
 499                 columns = treeview.get_columns()
 500                 if columns:
 501                         for column in columns:
 502                                 treeview.remove_column(column)
 503 
 504         def __init_sections(self):
 505                 '''This function is for initializing sections combo box, also adds "All"
 506                 Category. It sets active section combobox entry "All"'''
 507                 self.section_list.append([0, self._('All'), ])
 508                 self.section_list.append([-1, "", ])
 509                 self.section_list.append([2, self._('Meta Packages'), ])
 510                 self.section_list.append([3, self._('Applications'), ])
 511                 self.section_list.append([4, self._('Desktop (GNOME)'), ])
 512                 self.section_list.append([5, self._('Development'), ])
 513                 self.section_list.append([6, self._('Distributions'), ])
 514                 self.section_list.append([7, self._('Drivers'), ])
 515                 self.section_list.append([8, self._('System'), ])


 537                         # XXX if some changes were applied:
 538                         self.__main_application_quit()
 539                         return True
 540                 else:
 541                         self.__main_application_quit()
 542 
 543         def __on_file_quit_activate(self, widget):
 544                 ''' handler for quit menu event '''
 545                 self.__on_mainwindow_delete_event(None, None)
 546 
 547         def __on_edit_repositories_activate(self, widget):
 548                 ''' handler for repository menu event '''
 549                 repository.Repository(self)
 550 
 551         def __on_file_be_activate(self, widget):
 552                 ''' handler for be menu event '''
 553                 beadm.Beadmin(self)
 554 
 555         def __on_searchentry_changed(self, widget):
 556                 '''On text search field changed we should refilter the main view'''

 557                 if self.application_refilter_id != 0:
 558                         gobject.source_remove(self.application_refilter_id)
 559                         self.application_refilter_id = 0
 560                 if self.w_searchentry_dialog.get_text() == "":
 561                         self.application_refilter_id = \
 562                             gobject.idle_add(self.__application_refilter)
 563                 else:
 564                         self.application_refilter_id = \
 565                             gobject.timeout_add(TYPE_AHEAD_DELAY, self.__application_refilter)

 566 
 567         def __application_refilter(self):
 568                 self.application_list_filter.refilter()
 569                 gobject.idle_add(self.__enable_disable_selection_menus)
 570                 self.application_refilter_id = 0
 571                 return False
 572 
 573         def __on_edit_paste(self, widget):
 574                 self.w_searchentry_dialog.insert_text(self.main_clipboard_text, \
 575                     self.w_searchentry_dialog.get_position())
 576 
 577         def __on_clear_paste(self, widget):
 578                 bounds = self.w_searchentry_dialog.get_selection_bounds()
 579                 self.w_searchentry_dialog.delete_text(bounds[0], bounds[1])
 580                 return
 581 
 582         def __on_copy(self, widget):
 583                 bounds = self.w_searchentry_dialog.get_selection_bounds()
 584                 text = self.w_searchentry_dialog.get_chars(bounds[0], bounds[1])
 585                 self.w_main_clipboard.set_text(text)


 626                 self.__enable_disable_install_update()
 627                 self.__enable_disable_remove()
 628 
 629         def __on_select_updates(self, widget):
 630                 sort_filt_model = \
 631                     self.w_application_treeview.get_model() #gtk.TreeModelSort
 632                 filt_model = sort_filt_model.get_model() #gtk.TreeModelFilter
 633                 model = filt_model.get_model() #gtk.ListStore
 634                 iter_next = sort_filt_model.get_iter_first()
 635                 list_of_paths = []
 636                 while iter_next != None:
 637                         sorted_path = sort_filt_model.get_path(iter_next)
 638                         filtered_iter = sort_filt_model.convert_iter_to_child_iter(None, \
 639                             iter_next)
 640                         app_iter = filt_model.convert_iter_to_child_iter(filtered_iter)
 641 
 642                         filtered_path = \
 643                             sort_filt_model.convert_path_to_child_path(sorted_path)
 644                         path = filt_model.convert_path_to_child_path(filtered_path)
 645                         if model.get_value(app_iter, \
 646                             enumerations.INSTALLED_VERSION_COLUMN):
 647                                 if  model.get_value(app_iter, \
 648                                     enumerations.LATEST_AVAILABLE_COLUMN):
 649                                         list_of_paths.append(path)
 650                         iter_next = sort_filt_model.iter_next(iter_next)
 651                 for path in list_of_paths:
 652                         itr = model.get_iter(path)
 653                         model.set_value(itr, enumerations.MARK_COLUMN, True)
 654                 self.__enable_disable_selection_menus()
 655                 self.update_statusbar()
 656                 self.__enable_disable_install_update()
 657                 self.__enable_disable_remove()
 658 
 659         def __on_deselect(self, widget):
 660                 sort_filt_model = \
 661                     self.w_application_treeview.get_model() #gtk.TreeModelSort
 662                 filt_model = sort_filt_model.get_model() #gtk.TreeModelFilter
 663                 model = filt_model.get_model() #gtk.ListStore
 664                 iter_next = sort_filt_model.get_iter_first()
 665                 list_of_paths = []
 666                 while iter_next != None:
 667                         sorted_path = sort_filt_model.get_path(iter_next)
 668                         filtered_iter = sort_filt_model.convert_iter_to_child_iter(None, \


 685         def __on_searchentry_focus_in(self, widget, event):
 686                 self.w_paste_menuitem.set_sensitive(True)
 687 
 688         def __on_searchentry_focus_out(self, widget, event):
 689                 self.w_paste_menuitem.set_sensitive(False)
 690 
 691         def __on_searchentry_event(self, widget, event):
 692                 self.w_main_clipboard.request_text(self.__clipboard_text_received)
 693                 if widget.get_selection_bounds():
 694                         #enable selection functions
 695                         self.w_cut_menuitem.set_sensitive(True)
 696                         self.w_copy_menuitem.set_sensitive(True)
 697                         self.w_clear_menuitem.set_sensitive(True)
 698                 else:
 699                         self.w_cut_menuitem.set_sensitive(False)
 700                         self.w_copy_menuitem.set_sensitive(False)
 701                         self.w_clear_menuitem.set_sensitive(False)
 702 
 703         def __on_category_selection_changed(self, selection, widget):
 704                 '''This function is for handling category selection changes'''
 705                 self.application_list_filter.refilter()
 706                 self.__enable_disable_selection_menus()
 707 
 708         def __on_package_selection_changed(self, selection, widget):
 709                 '''This function is for handling package selection changes'''
 710                 model, itr = selection.get_selected()
 711                 if itr:
 712                         self.pkginfo_thread += 1
 713                         self.selected_pkgname = \
 714                                model.get_value(itr, enumerations.NAME_COLUMN)
 715                         Thread(target = self.__show_package_info, \
 716                             args = (model, itr, self.pkginfo_thread)).start()
 717                         if self.w_info_notebook.get_current_page() == 3:
 718                                 self.__on_notebook_change(None, None, 3)
 719 
 720 
 721         def __on_filtercombobox_changed(self, widget):
 722                 '''On filter combobox changed'''
 723                 if self.in_setup:
 724                         return
 725                 self.application_list_filter.refilter()
 726                 self.__enable_disable_selection_menus()
 727 
 728         def __on_sectionscombobox_changed(self, widget):
 729                 '''On section combobox changed'''
 730                 if self.in_setup:
 731                         return
 732                 selected_section = widget.get_active()
 733                 if selected_section == 0:
 734                         for category in self.category_list:
 735                                 category[enumerations.CATEGORY_VISIBLE] = True
 736                 else:
 737                         for category in self.category_list:
 738                                 if category[enumerations.CATEGORY_ID] == 0:
 739                                         category[enumerations.CATEGORY_VISIBLE] = True
 740                                 else:
 741                                         category_list = \
 742                                             category[enumerations.SECTION_LIST_OBJECT]
 743                                         if not category_list:
 744                                                 category[enumerations.CATEGORY_VISIBLE] \
 745                                                     = False
 746                                         else:
 747                                                 for section in category_list:
 748                                                         if section == selected_section:
 749                                                                 category[enumerations. \
 750                                                                     CATEGORY_VISIBLE] = \
 751                                                                     True
 752                                                         else:
 753                                                                 category[enumerations. \
 754                                                                     CATEGORY_VISIBLE] = \
 755                                                                     False

 756                 self.category_list_filter.refilter()
 757                 self.application_list_filter.refilter()
 758                 self.__enable_disable_selection_menus()
 759 
 760         def __on_repositorycombobox_changed(self, widget):
 761                 '''On repository combobox changed'''
 762                 if self.in_setup:
 763                         return  
 764                 self.application_list_filter.refilter()
 765                 self.__enable_disable_selection_menus()
 766 
 767         def __on_install_update(self, widget):
 768                 self.api_o.reset()
 769                 install_update = []
 770                 for row in self.application_list:
 771                         if row[enumerations.MARK_COLUMN]:



 772                                 install_update.append(row[\
 773                                     enumerations.NAME_COLUMN])
 774                 installupdate.InstallUpdate(install_update, self, \
 775                     self.api_o, ips_update = False, \
 776                     action = enumerations.INSTALL_UPDATE)
 777 
 778         def __on_update_all(self, widget):
 779                 opensolaris_image = True
 780                 self.progress_stop_timer_thread = False
 781                 notfound = self.__installed_fmris_from_args(self.api_o, \
 782                     ["SUNWipkg", "SUNWcs"])
 783 
 784                 if notfound:
 785                         opensolaris_image = False
 786 
 787                 if opensolaris_image:
 788                         # Load the catalogs from the repository, its a long 
 789                         # running tasks so need a progress dialog
 790                         self.w_progress_dialog.set_title(self._("Update All"))
 791                         self.w_progressinfo_label.set_text(self._( \
 792                             "Checking SUNWipkg and SUNWipkg-gui versions\n" \
 793                             "\nPlease wait ..."))


 837                             action = enumerations.IMAGE_UPDATE)
 838 
 839         def __on_help_about(self, widget):
 840                 wTreePlan = gtk.glade.XML(self.gladefile, "aboutdialog") 
 841                 aboutdialog = wTreePlan.get_widget("aboutdialog")
 842                 aboutdialog.connect("response", lambda x = None, \
 843                     y = None: aboutdialog.destroy())
 844                 aboutdialog.run()
 845 
 846         def __on_help_help(self, widget):
 847                 props = { gnome.PARAM_APP_DATADIR : self.application_dir + \
 848                             '/usr/share/package-manager/help' }
 849                 gnome.program_init('package-manager', '0.1', properties=props)
 850                 gnome.help_display('package-manager') 
 851 
 852         def __on_remove(self, widget):
 853                 self.api_o.reset()
 854                 remove_list = []
 855                 for pkg in self.application_list:
 856                         if pkg[enumerations.MARK_COLUMN] and \
 857                             pkg[enumerations.INSTALLED_VERSION_COLUMN]:

 858                                 remove_list.append(\
 859                                     pkg[enumerations.NAME_COLUMN])
 860                 installupdate.InstallUpdate(remove_list, self, \
 861                     self.api_o, ips_update = False, \
 862                     action = enumerations.REMOVE)
 863 
 864         def __on_reload(self, widget):
 865                 if self.description_thread_running:
 866                         self.cancelled = True
 867                 self.in_setup = True
 868                 self.w_progress_dialog.set_title(self._("Refreshing catalogs"))
 869                 self.w_progressinfo_label.set_text(self._("Refreshing catalogs..."))
 870                 self.progress_stop_timer_thread = False
 871                 Thread(target = self.__progressdialog_progress_pulse).start()
 872                 self.w_progress_dialog.show()
 873                 self.__disconnect_models()
 874                 Thread(target = self.__catalog_refresh).start()
 875 
 876         def __catalog_refresh_done(self):
 877                 self.progress_stop_timer_thread = True
 878                 #Let the progress_pulse finish. This should be done other way, but at
 879                 #The moment this works fine


 926 
 927                         repositories_list.append([i, repo, ])
 928                         i = i + 1
 929                 self.w_repository_combobox.set_model(repositories_list)
 930                 if default_authority:
 931                         self.w_repository_combobox.set_active(active)
 932                 else:
 933                         self.w_repository_combobox.set_active(0)
 934 
 935         def __active_pane_toggle(self, cell, path, model_sort):
 936                 '''Toggle function for column enumerations.MARK_COLUMN'''
 937                 applicationModel = model_sort.get_model()
 938                 applicationPath = model_sort.convert_path_to_child_path(path)
 939                 filterModel = applicationModel.get_model()
 940                 child_path = applicationModel.convert_path_to_child_path(applicationPath)
 941                 itr = filterModel.get_iter(child_path)
 942                 if itr:
 943                         modified = filterModel.get_value(itr, enumerations.MARK_COLUMN)
 944                         filterModel.set_value(itr, enumerations.MARK_COLUMN, \
 945                             not modified)
 946                         latest_available = filterModel.get_value(itr, \
 947                             enumerations.LATEST_AVAILABLE_COLUMN)
 948                         installed_available = filterModel.get_value(itr, \
 949                             enumerations.INSTALLED_VERSION_COLUMN)
 950                         self.update_statusbar()
 951                         self.__update_install_update_button(latest_available, modified)
 952                         self.__update_remove_button(installed_available, modified)
 953                         self.__enable_disable_selection_menus()
 954 
 955 
 956         def __update_install_update_button(self, latest_available, toggle_true):
 957                 if not toggle_true and self.user_rights:
 958                         if latest_available:

 959                                 self.w_installupdate_button.set_sensitive(True)
 960                                 self.w_installupdate_menuitem.set_sensitive(True)
 961                 else:
 962                         available = None


 963                         for row in self.application_list:
 964                                 if row[enumerations.MARK_COLUMN]:
 965                                         available = \
 966                                             row[enumerations.LATEST_AVAILABLE_COLUMN]
 967                                         if available:


 968                                                 return
 969                         if not available:
 970                                 self.w_installupdate_button.set_sensitive(False)
 971                                 self.w_installupdate_menuitem.set_sensitive(False)
 972 
 973         def __update_reload_button(self):
 974                 if self.user_rights:
 975                         self.w_reload_button.set_sensitive(True)
 976                 else:
 977                         self.w_reload_button.set_sensitive(False)
 978 
 979         def __update_remove_button(self, installed_available, toggle_true):
 980                 if not toggle_true and self.user_rights:
 981                         if installed_available:

 982                                 self.w_remove_button.set_sensitive(True)
 983                                 self.w_remove_menuitem.set_sensitive(True)
 984                 else:
 985                         available = None
 986                         for row in self.application_list:
 987                                 if row[enumerations.MARK_COLUMN]:
 988                                         installed = \
 989                                             row[enumerations.INSTALLED_VERSION_COLUMN]
 990                                         if installed:


 991                                                 return
 992                         if not available:
 993                                 self.w_remove_button.set_sensitive(False)
 994                                 self.w_remove_menuitem.set_sensitive(False)
 995 
 996         def __show_fetching_package_info(self, pkg, icon):
 997                 pkg_name = pkg.get_name()
 998                 if icon and icon != pkg:
 999                         self.w_packageicon_image.set_from_pixbuf(icon)
1000                 else:
1001                         self.w_packageicon_image.set_from_pixbuf( \
1002                             self.__get_pixbuf_from_path("/usr/share/package-manager/", \
1003                             "PM_package_36x"))
1004                 self.w_packagename_label.set_markup("<b>" + pkg_name + "</b>")
1005                 
1006                 if self.__setting_from_cache(pkg_name):

1007                         return
1008                         
1009                 self.w_shortdescription_label.set_text( \
1010                     self._("Fetching description..."))
1011                 instbuffer = self.w_installedfiles_textview.get_buffer()
1012                 depbuffer = self.w_dependencies_textview.get_buffer()
1013                 infobuffer = self.w_generalinfo_textview.get_buffer()
1014                 instbuffer.set_text(self._("Fetching information..."))
1015                 depbuffer.set_text(self._("Fetching information..."))
1016                 infobuffer.set_text(self._("Fetching information..."))
1017                 return
1018                 
1019         def __setting_from_cache(self, pkg_name):
1020                 if len(self.info_cache) > MAX_INFO_CACHE_LIMIT:
1021                         self.info_cache = {}
1022 
1023                 if self.info_cache.has_key(pkg_name):
1024                         self.w_shortdescription_label.set_text(\
1025                                 self.info_cache[pkg_name][0])
1026                         instbuffer = self.w_installedfiles_textview.get_buffer()
1027                         depbuffer = self.w_dependencies_textview.get_buffer()
1028                         infobuffer = self.w_generalinfo_textview.get_buffer()
1029                         infobuffer.set_text(self.info_cache[pkg_name][1])
1030                         instbuffer.set_text(self.info_cache[pkg_name][2])
1031                         depbuffer.set_text(self.info_cache[pkg_name][3])
1032                         return True
1033                 else:
1034                         return False
1035                 
1036         def __update_package_info(self, pkg, icon, installed, pkg_info):
1037                 pkg_name = pkg.get_name()

1038                 if icon and icon != pkg:
1039                         self.w_packageicon_image.set_from_pixbuf(icon)
1040                 else:
1041                         self.w_packageicon_image.set_from_pixbuf( \
1042                             self.__get_pixbuf_from_path("/usr/share/package-manager/", \
1043                             "PM_package_36x"))
1044                 self.w_packagename_label.set_markup("<b>" + pkg_name + "</b>")
1045                 
1046                 if self.__setting_from_cache(pkg_name):
1047                         return
1048                         
1049                 instbuffer = self.w_installedfiles_textview.get_buffer()
1050                 depbuffer = self.w_dependencies_textview.get_buffer()
1051                 infobuffer = self.w_generalinfo_textview.get_buffer()
1052 
1053                 if not pkg_info:
1054                         self.w_shortdescription_label.set_text( \
1055                             self._("Description not available for this package..."))
1056                         instbuffer.set_text( \
1057                             self._("Files Details not available for this package..."))
1058                         depbuffer.set_text(self._( \
1059                             "Dependencies info not available for this package..."))
1060                         infobuffer.set_text( \
1061                             self._("Information not available for this package..."))
1062                         return
1063                 description = pkg_info.summary
1064                 #XXX long term need to have something more robust here for multi byte
1065                 if len(description) > MAX_DESC_LEN:
1066                         description = description[:MAX_DESC_LEN] + " ..."


1087                 if pkg_info.files:
1088                         inst_str += ''.join(["\t%s\n" % x for x in pkg_info.files])
1089                 if pkg_info.hardlinks:
1090                         inst_str += ''.join(["\t%s\n" % x for x in pkg_info.hardlinks])
1091                 if pkg_info.links:
1092                         inst_str += ''.join(["\t%s\n" % x for x in pkg_info.links])
1093                         
1094                 if description:
1095                         info_str += self._("  Description:\t%s\n") % description
1096                 info_str += self._("  Name:\t\t%s\n") % pkg_name
1097                 info_str += self._("  FMRI:\t\t%s\n") % pkg.get_fmri()
1098                 info_str +=  self._("  Version:\t\t%s\n") % \
1099                     pkg.version.get_short_version()
1100                 info_str +=  self._("  Packaged:\t%s\n") % \
1101                     self.get_datetime(pkg.version)
1102                 
1103                 infobuffer.set_text(info_str)
1104                 instbuffer.set_text(inst_str)
1105                 depbuffer.set_text(dep_str)
1106 
1107                 self.info_cache[pkg_name] = \
1108                         (description, info_str, inst_str, dep_str)
1109                 
1110         def __update_package_license(self, licenses):
1111                 lic = ""
1112                 lic_u = ""
1113                 if licenses == None:
1114                         lic_u = self._("Not available")
1115                 else:
1116                         for licens in licenses:
1117                                 lic += licens.get_text()
1118                                 lic += "\n"
1119                         try:
1120                                 lic_u = unicode(lic, "utf-8")
1121                         except UnicodeDecodeError:
1122                                 lic_u += ""
1123                 licbuffer = self.w_license_textview.get_buffer()
1124                 licbuffer.set_text(lic_u)
1125 
1126         def __update_description(self, description, package):
1127                 '''workaround function'''
1128                 for pkg in self.application_list:
1129                         p = pkg[enumerations.PACKAGE_OBJECT_COLUMN][0]
1130                         if p == package:
1131                                 pkg[enumerations.DESCRIPTION_COLUMN] = description
1132                                 return
1133 
1134         def __show_package_licenses(self, th_no):
1135                 #XXX revisit this and replace with gobject.timer_add() instead of sleep
1136                 # sleep for a little time, this is done for the users who are
1137                 # fast browsing the list of the packages.
1138                 time.sleep(1)
1139                 if th_no != self.pkginfo_thread:
1140                         return
1141                 if self.selected_pkgname == None:
1142                         gobject.idle_add(self.__update_package_license, \
1143                             None)
1144                         return
1145                 info = self.api_o.info([self.selected_pkgname], True, True)
1146                 pkgs_info = None
1147                 package_info = None
1148                 no_licenses = 0
1149                 if info:
1150                         pkgs_info = info[0]
1151                 if pkgs_info:
1152                         package_info = pkgs_info[0]
1153                 if package_info:


1160                         gobject.idle_add(self.__update_package_license, \
1161                             package_info.licenses)
1162                 else:
1163                         return
1164 
1165         def __get_pkg_info(self, pkg_name, installed):
1166                 info = self.api_o.info([pkg_name], installed, get_licenses=False, \
1167                                 get_action_info=True)
1168                 pkgs_info = None
1169                 package_info = None
1170                 if info:
1171                         pkgs_info = info[0]
1172                 if pkgs_info:
1173                         package_info = pkgs_info[0]
1174                 if package_info:
1175                         return package_info
1176                 else:
1177                         return
1178 
1179         def __show_package_info(self, model, itr, th_no):
1180                 pkg = model.get_value(itr, enumerations.INSTALLED_OBJECT_COLUMN)
1181                 icon = model.get_value(itr, enumerations.INSTALLED_OBJECT_COLUMN)
1182                 installed = False
1183                 if not pkg:
1184                         packages = model.get_value(itr, \
1185                             enumerations.PACKAGE_OBJECT_COLUMN)
1186                         pkg = max(packages)
1187                         gobject.idle_add( \
1188                                 self.__show_fetching_package_info, pkg, icon)
1189                 else:
1190                         gobject.idle_add( \
1191                                 self.__show_fetching_package_info, pkg, icon)
1192                         installed = True


1193                         
1194                 if self.info_cache.has_key(pkg.get_name()):
1195                         return
1196 
1197                 # sleep for a little time, this is done for the users which are
1198                 # fast browsing the list of the packages.
1199                 time.sleep(1)
1200                 if th_no != self.pkginfo_thread:
1201                         return
1202                 man = None
1203                 img = self.api_o.img
1204                 img.history.operation_name = "info"
1205 
1206                 pkg_info = self.__get_pkg_info(pkg.get_name(), installed)
1207                 if th_no == self.pkginfo_thread:
1208                         if not pkg:
1209                                 gobject.idle_add(self.__update_package_info, pkg, icon, \
1210                                     installed, pkg_info)
1211                         else:
1212                                 gobject.idle_add(self.__update_package_info, pkg, icon, \
1213                                     installed, pkg_info)
1214                         img.history.operation_result = \
1215                             history.RESULT_SUCCEEDED
1216                 else:
1217                         img.history.operation_result = \
1218                             history.RESULT_SUCCEEDED
1219                         return
1220 
1221         # This function is ported from pkg.actions.generic.distinguished_name()
1222         def __locale_distinguished_name(self, action):
1223                 if action.key_attr == None:
1224                         return str(action)
1225                 return "%s: %s" % \
1226                     (self._(action.name), action.attrs.get(action.key_attr, "???"))
1227 
1228         def __application_filter(self, model, itr):
1229                 '''This function is used to filter content in the main 
1230                 application view'''
1231                 if self.in_setup or self.cancelled:
1232                         return False
1233                 # XXX Show filter, chenge text to integers 
1234                 selected_category = 0
1235                 selection = self.w_categories_treeview.get_selection()
1236                 category_model, category_iter = selection.get_selected()
1237                 if not category_iter:         #no category was selected, so select "All"
1238                         selection.select_path(0)
1239                         category_model, category_iter = selection.get_selected()
1240                 if category_iter:
1241                         selected_category = category_model.get_value(category_iter, \
1242                             enumerations.CATEGORY_ID)
1243                 category_list_iter = model.get_value(itr, \
1244                     enumerations.CATEGORY_LIST_OBJECT)
1245                 category = False
1246                 repo = self.__is_pkg_repository_visible(model, itr)
1247                 if category_list_iter:
1248                         sel = False
1249                         for category_iter in category_list_iter:
1250                                 if category != True:
1251                                         category = \
1252                                             self.category_filter(self.category_list, \
1253                                             category_iter)
1254                                 if selected_category != 0:
1255                                         if selected_category == \
1256                                             self.category_list.get_value(category_iter, \
1257                                             enumerations.CATEGORY_ID):
1258                                                 sel = True
1259                                         category = sel
1260                 else:
1261                         if selected_category == 0:
1262                                 selected_section = self.w_sections_combobox.get_active()
1263                                 if selected_section == 0:
1264                                         category = True


1272                             model.get_value \
1273                             (itr, enumerations.NAME_COLUMN).lower():
1274                                 return (repo & category & \
1275                                     self.__is_package_filtered(model, itr))
1276                 if not model.get_value(itr, enumerations.DESCRIPTION_COLUMN) == None:
1277                         if self.w_searchentry_dialog.get_text().lower() in \
1278                             model.get_value \
1279                             (itr, enumerations.DESCRIPTION_COLUMN).lower():
1280                                 return (repo & category & \
1281                                     self.__is_package_filtered(model, itr))
1282                 else:
1283                         return False
1284 
1285         def __is_package_filtered(self, model, itr):
1286                 '''Function for filtercombobox'''
1287                 # XXX Instead of string comparison, we should do it through integers.
1288                 # XXX It should be faster and better for localisations.
1289                 filter_text = self.w_filter_combobox.get_active()
1290                 if filter_text == 0:
1291                         return True
1292                 elif filter_text == 2:
1293                         return model.get_value(itr, \
1294                             enumerations.INSTALLED_VERSION_COLUMN) != None

1295                 elif filter_text == 3:
1296                         return (model.get_value(itr, \
1297                             enumerations.INSTALLED_VERSION_COLUMN) != None) & \
1298                             (model.get_value(itr, \
1299                             enumerations.LATEST_AVAILABLE_COLUMN) != None)
1300                 elif filter_text == 4:
1301                         return not model.get_value(itr, \
1302                             enumerations.INSTALLED_VERSION_COLUMN) != None
1303                 elif filter_text == 6:
1304                         return model.get_value(itr, enumerations.MARK_COLUMN)
1305                 elif filter_text == 8:
1306                         # XXX Locked support
1307                         return False
1308 
1309 
1310         def __is_pkg_repository_visible(self, model, itr):
1311                 if len(self.repositories_list) <= 1:
1312                         return True
1313                 else:
1314                         auth_iter = self.w_repository_combobox.get_active_iter()
1315                         authority = self.repositories_list.get_value(auth_iter, \
1316                             enumerations.REPOSITORY_NAME)
1317                         packages = model.get_value(itr, \
1318                             enumerations.PACKAGE_OBJECT_COLUMN)
1319                         if not packages:
1320                                 return False
1321                         pkg = max(packages)
1322                         if cmp(pkg.get_authority(), authority) == 0:
1323                                 return True
1324                         else:
1325                                 return False
1326 
1327         def __do_ips_uptodate_check(self):
1328                 ret = self.__catalog_refresh(False)
1329                 if ret != -1:
1330                         self.ips_uptodate = self.__ipkg_ipkgui_uptodate()
1331                 else:
1332                         self.progress_canceled = True
1333                 self.progress_stop_timer_thread = True
1334 
1335         def __ipkg_ipkgui_uptodate(self):
1336                 self.api_o.reset()
1337                 list_of_packages = [self.ipkg_fmri, self.ipkggui_fmri]
1338                 ret = True
1339                 try:
1340                         upgrade_needed, cre = self.api_o.plan_install(
1341                             list_of_packages, filters = [])


1358                 self.__enable_disable_deselect()
1359                 # XXX disabled until new API
1360                 self.__enable_disable_update_all()
1361 
1362         def __enable_disable_select_all(self):
1363                 
1364                 if self.in_setup:
1365                         return
1366                 if len(self.w_application_treeview.get_model()) > 0:
1367                         for row in self.w_application_treeview.get_model():
1368                                 if not row[enumerations.MARK_COLUMN]:
1369                                         self.w_selectall_menuitem.set_sensitive(True)
1370                                         return
1371                         self.w_selectall_menuitem.set_sensitive(False)
1372                 else:
1373                         self.w_selectall_menuitem.set_sensitive(False)
1374 
1375         def __enable_disable_install_update(self):
1376                 for row in self.application_list:
1377                         if row[enumerations.MARK_COLUMN]:
1378                                 if row[enumerations.LATEST_AVAILABLE_COLUMN] and \
1379                                     self.user_rights:


1380                                         self.w_installupdate_button.set_sensitive(True)
1381                                         self.w_installupdate_menuitem.set_sensitive(True)
1382                                         return
1383                 self.w_installupdate_button.set_sensitive(False)
1384                 self.w_installupdate_menuitem.set_sensitive(False)
1385 
1386         def __enable_disable_remove(self):
1387                 for row in self.application_list:
1388                         if row[enumerations.MARK_COLUMN]:
1389                                 if row[enumerations.INSTALLED_VERSION_COLUMN] and \
1390                                     self.user_rights:


1391                                         self.w_remove_button.set_sensitive(True)
1392                                         self.w_remove_menuitem.set_sensitive(True)
1393                                         return
1394                 self.w_remove_button.set_sensitive(False)
1395                 self.w_remove_menuitem.set_sensitive(False)
1396 
1397         def __enable_disable_select_updates(self):
1398                 for row in self.w_application_treeview.get_model():
1399                         if row[enumerations.INSTALLED_VERSION_COLUMN]:
1400                                 if row[enumerations.LATEST_AVAILABLE_COLUMN]:
1401                                         if not row[enumerations.MARK_COLUMN]:
1402                                                 self.w_selectupdates_menuitem. \
1403                                                     set_sensitive(True)
1404                                                 return
1405                 self.w_selectupdates_menuitem.set_sensitive(False)
1406                 return
1407 
1408         def __enable_disable_update_all(self):
1409                 for row in self.application_list:
1410                         if self.__is_pkg_repository_visible(self.application_list, \
1411                             row.iter):
1412                                 if self.application_list.get_value(row.iter, \
1413                                     enumerations.INSTALLED_VERSION_COLUMN):
1414                                         if self.application_list.get_value(row.iter, \
1415                                             enumerations.LATEST_AVAILABLE_COLUMN) and \
1416                                             self.user_rights:
1417                                                 self.w_updateall_menuitem. \
1418                                                     set_sensitive(True)
1419                                                 self.w_updateall_button. \
1420                                                     set_sensitive(True)
1421                                                 return
1422                 self.w_updateall_button.set_sensitive(False)
1423                 self.w_updateall_menuitem.set_sensitive(False)

1424 
1425         def __enable_disable_deselect(self):
1426                 for row in self.w_application_treeview.get_model():
1427                         if row[enumerations.MARK_COLUMN]:
1428                                 self.w_deselect_menuitem.set_sensitive(True)
1429                                 return
1430                 self.w_deselect_menuitem.set_sensitive(False)
1431                 return
1432 
1433 
1434         def __catalog_refresh(self, reload_gui=True):
1435                 """Update image's catalogs."""
1436                 full_refresh = True
1437                 try:
1438                         self.api_o.refresh(full_refresh)
1439                         self.api_o.img.load_catalogs(self.pr)
1440                 except api_errors.UnrecognizedAuthorityException:
1441                         # In current implementation, this will never happen
1442                         # We are not refrehsing specific authority
1443                         self.__catalog_refresh_done()
1444                         raise
1445                 except api_errors.PermissionsException, pe:
1446                         #Error will already have been reported in 
1447                         #Manage Repository dialog
1448                         self.__catalog_refresh_done()
1449                         return -1
1450                 except api_errors.CatalogRefreshException, cre:
1451                         total = cre.total
1452                         succeeded = cre.succeeded
1453                         ermsg = self._("Network problem.\n\n")
1454                         ermsg += self._("Details:\n")
1455                         ermsg += "%s/%s" % (succeeded, total) 
1456                         ermsg += self._(" catalogs successfully updated:\n") 
1457                         for auth, err in cre.failed:
1458                                 if isinstance(err, HTTPError):
1459                                         ermsg += "   %s: %s - %s\n" % \
1460                                             (err.filename, err.code, err.msg)
1461                                 elif isinstance(err, URLError):
1462                                         if err.args[0][0] == 8:
1463                                                 ermsg += "    %s: %s\n" % \
1464                                                     (urlparse.urlsplit(
1465                                                         auth["origin"])[1].split(":")[0],


1483                             None, gtk.MESSAGE_INFO)
1484                         self.__catalog_refresh_done()
1485                         return -1
1486 
1487                 except api_errors.UnrecognizedAuthorityException:
1488                         self.__catalog_refresh_done()
1489                         raise
1490                 except Exception:
1491                         self.__catalog_refresh_done()
1492                         raise
1493                 if reload_gui:
1494                         self.__catalog_refresh_done()
1495                 return 0
1496 
1497         def __get_image_from_directory(self, api_o, progressdialog_progress):
1498                 """ This method set up image from the given directory and
1499                 returns the image object or None"""
1500                 application_list = self.__get_new_application_liststore()
1501                 category_list = self.__get_new_category_liststore()
1502                 repositories_list = self.__get_new_repositories_liststore()
1503 


1504                 try:
1505                         pkgs_known = [ pf[0] for pf in
1506                             sorted(api_o.img.inventory(all_known = True)) ]


































1507                 except api_errors.InventoryException:
1508                         # Can't happen when all_known is true and no args,
1509                         # but here for completeness.
1510                         err = self._("Error occured while getting list of packages")
1511                         gobject.idle_add(self.w_progress_dialog.hide)
1512                         gobject.idle_add(self.error_occured, err)
1513                         return
1514 
1515                 #Only one instance of those icons should be in memory
1516                 update_available_icon = self.get_icon_pixbuf("status_newupdate")
1517                 installed_icon = self.get_icon_pixbuf("status_installed")
1518                 #Imageinfo for categories
1519                 imginfo = imageinfo.ImageInfo()
1520                 sectioninfo = imageinfo.ImageInfo()
1521                 catalogs = api_o.img.catalogs
1522                 categories = {}
1523                 sections = {}
1524                 share_path = "/usr/share/package-manager/data/"
1525                 for cat in catalogs:
1526                         category = imginfo.read(self.application_dir + \
1527                             share_path + cat)
1528                         if len(category) == 0:
1529                                 category = imginfo.read(self.application_dir + \
1530                                     share_path + "opensolaris.org")                                
1531                         categories[cat] = category
1532                         section = sectioninfo.read(self.application_dir + \
1533                             share_path + cat + ".sections")
1534                         if len(section) == 0:
1535                                 section = sectioninfo.read(self.application_dir + \
1536                                     share_path + "opensolaris.org.sections")
1537                         sections[cat] = section
1538                 # Speedup, instead of checking if the pkg is already in the list, 
1539                 # iterating through all elements, we will only compare to the previous
1540                 # package and if the package is the same (version difference) then we
1541                 # are adding to the first iterator for the set of those packages. 
1542                 # We can do that, since the list pkgs_known is sorted
1543                 # This will give a sppedup from 18sec to ~3!!!
1544                 p_pkg_iter = None
1545                 p_pkg = None
1546                 insert_count = 0
1547                 icon_path = self.application_dir + \
1548                     "/usr/share/package-manager/data/pixmaps/"
1549 
1550                 pkg_count = 0
1551                 progress_percent = INITIAL_PROGRESS_TOTAL_PERCENTAGE
1552                 total_pkg_count = len(pkgs_known)
1553                 progress_increment = \
1554                         total_pkg_count / PACKAGE_PROGRESS_TOTAL_INCREMENTS
1555 
1556                 self.progress_stop_timer_thread = True
1557                 while gtk.events_pending():
1558                         gtk.main_iteration(False)
1559                 for pkg in pkgs_known:









1560                         if progress_increment > 0 and pkg_count % progress_increment == 0:
1561                                 progress_percent += PACKAGE_PROGRESS_PERCENT_INCREMENT
1562                                 if progress_percent <= PACKAGE_PROGRESS_PERCENT_TOTAL:
1563                                         progressdialog_progress(progress_percent, \
1564                                             pkg_count, total_pkg_count)
1565                                 while gtk.events_pending():
1566                                         gtk.main_iteration(False)
1567                         pkg_count += 1
1568                         
1569                         #speedup hack, check only last package
1570                         already_in_model = \
1571                             self.check_if_pkg_have_row_in_model(pkg, p_pkg)
1572                         if not already_in_model:         #Create new row
1573                                 available_version = None
1574                                 version_installed = None
1575                                 status_icon = None
1576                                 fmris = [pkg, ]
1577                                 package_installed = \
1578                                     self.get_installed_version(api_o, pkg)
1579                                 if package_installed:
1580                                         version_installed = \
1581                                             package_installed.version.get_short_version()
1582                                         #HACK, sometimes the package is installed but 
1583                                         #it's not in the pkgs_known
1584                                         status_icon = installed_icon
1585                                         if package_installed != pkg:
1586                                                 fmris.append(package_installed)
1587                                 else:
1588                                         dt = self.get_datetime(pkg.version)
1589                                         dt_str = (":%02d%02d") % (dt.month, dt.day)
1590                                         available_version = \
1591                                             pkg.version.get_short_version() + dt_str
1592                                 package_icon = self.__get_pixbuf_from_path(icon_path, \
1593                                     pkg.get_name())
1594                                 app = \
1595                                     [
1596                                         False, status_icon, package_icon, pkg.get_name(),
1597                                         version_installed, package_installed,
1598                                         available_version, -1, '...', fmris,
1599                                         True, None
1600                                     ]
1601                                 # XXX Small hack, if this is not applied, first package 
1602                                 # is listed twice. Insert is ~0.5 sec faster than append
1603                                 if insert_count == 0:
1604                                         row_iter = application_list.append(app)
1605                                 else:
1606                                         row_iter = \
1607                                             application_list.insert(insert_count, \
1608                                             app)
1609                                 # XXX Do not iterate through all the catalogs. Package 
1610                                 # should know what is package fmri prefix?
1611                                 apc = self.__add_package_to_category
1612                                 app_ls = application_list
1613                                 for cat in categories:
1614                                         if cat in categories:
1615                                                 name = pkg.get_name()
1616                                                 if name in categories[cat]:
1617                                                         pkg_categories = \
1618                                                             categories[cat][ \
1619                                                             name]
1620                                                         for pcat in \
1621                                                             pkg_categories.split(","):
1622                                                                 if pcat:
1623                                                                         apc(self._( \
1624                                                                             pcat), None \
1625                                                                             , None, \
1626                                                                             row_iter, \
1627                                                                             app_ls, \
1628                                                                             category_list)
1629                                 insert_count = insert_count + 1
1630                                 p_pkg_iter = row_iter
1631                                 p_pkg = pkg                  #The current become previous
1632                         else:
1633                                 # XXX check versions in here. For all installed/not 
1634                                 # installed:
1635                                 # if there is newer version, put it in the available 
1636                                 # field.
1637                                 #
1638                                 # XXXhack, since image_get_version_installed(pkg) is not 
1639                                 # working,as it should. For example package:
1640                                 # SUNWarc@0.5.11,5.11-0.79:20080205T152309Z
1641                                 # is not installed and it's newer version of installed
1642                                 # package:
1643                                 # SUNWarc@0.5.11,5.11-0.75:20071114T201151Z
1644                                 # the function returns only proper installed version for 
1645                                 # the older package and None for the newer.
1646                                 # The hack is a little bit slow since we are iterating 
1647                                 # for all known packages
1648                                 list_of_pkgs = \
1649                                     application_list.get_value(p_pkg_iter, \
1650                                     enumerations.PACKAGE_OBJECT_COLUMN)
1651                                 if pkg not in list_of_pkgs:
1652                                         list_of_pkgs.append(pkg)
1653                                 installed = application_list.get_value(p_pkg_iter, \
1654                                     enumerations.INSTALLED_OBJECT_COLUMN)
1655                                 latest = max(list_of_pkgs)
1656                                 dt = self.get_datetime(latest.version)
1657                                 dt_str = (":%02d%02d") % (dt.month, dt.day)
1658                                 if not installed:
1659                                         application_list.set_value(p_pkg_iter, \
1660                                             enumerations.LATEST_AVAILABLE_COLUMN, \
1661                                             latest.version.get_short_version() + \
1662                                             dt_str)
1663                                 else:
1664                                         if installed < latest:
1665                                                 application_list.set_value( \
1666                                                     p_pkg_iter, \
1667                                                     enumerations. \
1668                                                     LATEST_AVAILABLE_COLUMN, \
1669                                                     latest.version.get_short_version() + \
1670                                                     dt_str)
1671                                                 application_list.set_value(\
1672                                                     p_pkg_iter, \
1673                                                     enumerations.STATUS_ICON_COLUMN, \
1674                                                     update_available_icon)
1675                         # XXX How to get descriptions without manifest?
1676                         # XXX Downloading manifest is slow and can not work without 
1677                         # XXX Network connection
1678                         #if not image_obj.has_manifest(pkg):
1679                         #        image_obj.get_manifest(pkg)#verify(pkg, pr)
1680                         #installed_version = None
1681                         #package_iter = None #the iterator which points for other package
1682                 for authority in sections:
1683                         for section in sections[authority]:
1684                                 for category in sections[authority][section].split(","):
1685                                         self.__add_category_to_section(self._(category), \
1686                                             self._(section), category_list)
1687 
1688                 #1915 Sort the Categories into alphabetical order and prepend All Category
1689                 if len(category_list) > 0:
1690                         rows = [tuple(r) + (i,) for i, r in enumerate(category_list)]
1691                         rows.sort(self.__sort)
1692                         r = []
1693                         category_list.reorder([r[-1] for r in rows])
1694                 category_list.prepend([0, self._('All'), None, None, True, None])
1695 
1696                 progressdialog_progress(PACKAGE_PROGRESS_PERCENT_TOTAL, pkg_count, \
1697                     total_pkg_count)
1698                 gobject.idle_add(self.process_package_list_end, api_o, \
1699                     application_list, category_list, repositories_list)

1700 
1701         def __add_package_to_category(self, category_name, category_description, \
1702             category_icon, package, application_list, category_list):
1703                 if not package or category_name == self._('All'):
1704                         return
1705                 if not category_name:
1706                         return
1707                         # XXX check if needed
1708                         # category_name = self._('All')
1709                         # category_description = self._('All packages')
1710                         # category_icon = None
1711                 category_ref = None
1712                 for category in category_list:
1713                         if category[enumerations.CATEGORY_NAME] == category_name:
1714                                 category_ref = category.iter
1715                 if not category_ref:                       # Category not exists
1716                         category_ref = category_list.append([len( \
1717                             category_list)+1, category_name, category_description, \
1718                             category_icon, True, None])
1719                 if category_ref:
1720                         if application_list.get_value(package, \
1721                             enumerations.CATEGORY_LIST_OBJECT):
1722                                 a = application_list.get_value(package, \
1723                                     enumerations.CATEGORY_LIST_OBJECT)
1724                                 a.append(category_ref)
1725                         else:
1726                                 category_list = []
1727                                 category_list.append(category_ref)
1728                                 application_list.set(package, \
1729                                     enumerations.CATEGORY_LIST_OBJECT, category_list)
1730 
1731         def __add_category_to_section(self, category_name, section_name, category_list):
1732                 '''Adds the section to section list in category. If there is no such 
1733                 section, than it is not added. If there was already section than it
1734                 is skipped. Sections must be case sensitive'''
1735                 if not category_name:
1736                         return
1737                 for section in self.section_list:
1738                         if section[enumerations.SECTION_NAME] == section_name:
1739                                 for category in category_list:
1740                                         if category[enumerations.CATEGORY_NAME] == \
1741                                             category_name:
1742                                                 if not category[ \
1743                                                     enumerations.SECTION_LIST_OBJECT]:
1744                                                         category[ \
1745                                                             enumerations. \
1746                                                             SECTION_LIST_OBJECT] = \
1747                                                             [section[ \
1748                                                             enumerations.SECTION_ID], ]
1749                                                 else:


1854         @staticmethod
1855         def cell_data_function(column, renderer, model, itr, data):
1856                 '''Function which sets the background colour to black if package is 
1857                 selected'''
1858                 if itr:
1859                         if model.get_value(itr, enumerations.MARK_COLUMN):
1860                                 renderer.set_property("cell-background", "#ffe5cc")
1861                                 renderer.set_property("cell-background-set", True)
1862                         else:
1863                                 renderer.set_property("cell-background-set", False)
1864 
1865         @staticmethod
1866         def combobox_separator(model, itr):
1867                 return model.get_value(itr, enumerations.FILTER_NAME) == ""
1868 
1869         @staticmethod
1870         def combobox_id_separator(model, itr):
1871                 return model.get_value(itr, 0) == -1
1872 
1873         @staticmethod
1874         def check_if_pkg_have_row_in_model(pkg, p_pkg):
1875                 """Returns True if package is already in model or False if not"""
1876                 if p_pkg:
1877                         if pkg.is_same_pkg(p_pkg):
1878                                 return True
1879                         else:
1880                                 return False
1881                 return False
1882 
1883         @staticmethod
1884         def category_filter(model, itr):
1885                 '''This function filters category in the main application view'''
1886                 return model.get_value(itr, enumerations.CATEGORY_VISIBLE)
1887 
1888         @staticmethod
1889         def get_datetime(version):
1890                 dt = None
1891                 try:
1892                         dt = version.get_datetime()
1893                 except AttributeError:
1894                         dt = version.get_timestamp()
1895                 return dt
1896 
1897         @staticmethod
1898         def get_installed_version(api_o, pkg):
1899                 return api_o.img.get_version_installed(pkg)
1900 
1901         @staticmethod
1902         def get_manifest(img, package, filtered = True):
1903                 '''helper function'''


1928 # Public Methods
1929 #-----------------------------------------------------------------------------#
1930         def setup_progressdialog_show(self):
1931                 self.w_progress_dialog.set_title(self._("Loading Repository Information"))
1932                 self.w_progressinfo_label.set_text(
1933                     self._( "Fetching package entries ..."))
1934                 self.w_progress_cancel.hide()
1935                 self.w_progress_dialog.show()
1936                 Thread(target = self.__progressdialog_progress_time).start()
1937         
1938         def init_sections(self):
1939                 self.__init_sections()                   #Initiates sections
1940 
1941         def init_show_filter(self):
1942                 self.__init_show_filter()                #Initiates filter
1943 
1944         def reload_packages(self):
1945                 self.api_o = self.__get_api_object(self.image_directory, self.pr)
1946                 self.__on_reload(None)
1947 






1948         def process_package_list_start(self, image_directory):
1949                 self.cancelled = True
1950                 self.setup_progressdialog_show()
1951                 while gtk.events_pending():
1952                         gtk.main_iteration(False)
1953                 self.image_directory = image_directory
1954                 # Create our image object based on image directory.
1955                 api_o = self.__get_api_object(image_directory, self.pr)
1956                 api_o.img.load_catalogs(self.pr)
1957                 self.api_o = api_o
1958                 # Acquire image contents and update progress bar as you do so.
1959                 Thread(target = self.__get_image_from_directory, args = (api_o,
1960                         self.__progressdialog_progress_percent)).start()
1961 
1962         @staticmethod
1963         def __get_api_object(img_dir, progtrack):
1964                 api_o = None
1965                 try:
1966                         api_o = api.ImageInterface(img_dir, \
1967                             CLIENT_API_VERSION, \


1991                 self.w_progress_dialog.hide()
1992 
1993         def __get_manifests_thread(self):
1994                 Thread(target = self.get_manifests_for_packages,
1995                     args = ()).start()
1996 
1997         def get_icon_pixbuf(self, icon_name):
1998                 #2821: The get_icon_pixbuf should use PACKAGE_MANAGER_ROOT
1999                 return self.__get_pixbuf_from_path(self.application_dir + \
2000                     "/usr/share/icons/package-manager/", icon_name)
2001                 
2002         def get_manifests_for_packages(self):
2003                 ''' Function, which get's manifest for packages. If the manifest is not
2004                 locally tries to retrieve it. For installed packages gets manifest
2005                 for the particular version (local operation only), if the package is 
2006                 not installed than the newest one'''
2007                 time.sleep(3)
2008                 count = 0
2009                 self.description_thread_running = True
2010                 img = self.api_o.img
2011                 img.history.operation_name = "info"
2012                 for pkg in self.application_list:
2013                         if self.cancelled:
2014                                 self.description_thread_running = False
2015                                 return
2016                         info = None
2017                         img = self.api_o.img
2018                         package = pkg[enumerations.INSTALLED_OBJECT_COLUMN]
2019                         if (img and package):
2020                                 man = self.get_manifest(img, package, filtered = True)
2021                                 if man:
2022                                         info = man.get("description", "")
2023                         elif img:
2024                                 newest = max( \
2025                                     pkg[enumerations.PACKAGE_OBJECT_COLUMN])
2026                                 man = self.get_manifest(img, newest, \
2027                                     filtered = True)
2028                                 if man:
2029                                         info = man.get("description", "")
2030                         gobject.idle_add(self.update_desc, info, pkg)
2031                         count += 1
2032                         if count % 2 ==  0:
2033                                 time.sleep(0.001)
2034                 img.history.operation_name = "info"
2035                 img = self.api_o.img
2036                 img.history.operation_result = history.RESULT_SUCCEEDED
2037                 self.description_thread_running = False
2038                 
2039         def update_statusbar(self):
2040                 '''Function which updates statusbar'''
2041                 installed = 0
2042                 selected = 0
2043                 broken = 0
2044                 for pkg in self.application_list:
2045                         if pkg[enumerations.INSTALLED_VERSION_COLUMN]:


2046                                 installed = installed + 1
2047                         if pkg[enumerations.MARK_COLUMN]:
2048                                 selected = selected + 1
2049                 listed_str = self._('%d packages listed') % len(self.application_list)
2050                 inst_str = self._('%d installed') % installed
2051                 sel_str = self._('%d selected') % selected
2052                 broken_str = self._('%d broken') % broken
2053                 self.w_main_statusbar.push(0, listed_str + ', ' + inst_str + ', ' + \
2054                     sel_str + ', ' + broken_str + '.')
2055 
2056 
2057         def update_package_list(self, update_list):
2058                 img = self.api_o.img
2059                 img.clear_pkg_state()
2060                 img.load_catalogs(self.pr)
2061                 installed_icon = self.get_icon_pixbuf("status_installed")
2062                 for row in self.application_list:
2063                         status_icon = None
2064                         if row[enumerations.MARK_COLUMN] or \
2065                             row[enumerations.NAME_COLUMN] in update_list:
2066                                 pkg = row[enumerations.PACKAGE_OBJECT_COLUMN][0]
2067                                 package_installed = \
2068                                     self.get_installed_version(self.api_o, pkg)
2069                                 version_installed = None
2070                                 if package_installed:
2071                                         status_icon = installed_icon
2072                                         version_installed = \
2073                                             package_installed.version.get_short_version()
2074                                 row[enumerations.MARK_COLUMN] = False
2075                                 row[enumerations.INSTALLED_VERSION_COLUMN] = \
2076                                     version_installed
2077                                 row[enumerations.INSTALLED_OBJECT_COLUMN] = \
2078                                     package_installed
2079                                 row[enumerations.STATUS_ICON_COLUMN] = \
2080                                     status_icon
2081                                 if not package_installed:
2082                                         pkg = max(row[enumerations.PACKAGE_OBJECT_COLUMN])
2083                                         dt = self.get_datetime(pkg.version)
2084                                         dt_str = (":%02d%02d") % (dt.month, dt.day)
2085                                         available_version = \
2086                                             pkg.version.get_short_version() + dt_str
2087                                         row[enumerations.LATEST_AVAILABLE_COLUMN] = \
2088                                             available_version
2089                                 else:
2090                                         row[enumerations.LATEST_AVAILABLE_COLUMN] = None




2091                 self.w_installupdate_button.set_sensitive(False)
2092                 self.w_installupdate_menuitem.set_sensitive(False)
2093                 self.w_remove_button.set_sensitive(False)
2094                 self.w_remove_menuitem.set_sensitive(False)
2095                 self.__enable_disable_selection_menus()
2096                 self.update_statusbar()
2097 
2098         def shutdown_after_ips_update(self):    
2099 
2100                 # 2790: As IPS and IPS-GUI have been updated the IPS GUI must be shutdown 
2101                 # and restarted
2102                 msgbox = gtk.MessageDialog(parent = self.w_main_window, \
2103                     buttons = gtk.BUTTONS_OK, \
2104                     flags = gtk.DIALOG_MODAL, type = gtk.MESSAGE_INFO, \
2105                     message_format = self._("SUNWipkg and SUNWipkg-gui have been " \
2106                     "updated and Package Manager will now be restarted.\n\nAfter " \
2107                     "restart select Update All to continue."))
2108                 msgbox.set_title(self._("Update All"))
2109                 msgbox.run()
2110                 msgbox.destroy()




  22 # Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
  23 # Use is subject to license terms.
  24 #
  25 
  26 # Progress:
  27 # Startup Progress has two phases:
  28 # - Start phase:
  29 #   The start phase should be fairly constant at around a few seconds and so is given 5%
  30 #   of the total progress bar.
  31 # - Package entry loading phase:
  32 #   The package entry loading phase is given the remaining 95% of the bar for progress.
  33 
  34 INITIAL_PROGRESS_TIME_INTERVAL = 0.5      # Time to update progress during start phase
  35 INITIAL_PROGRESS_TIME_PERCENTAGE = 0.005  # Amount to update progress during start phase
  36 INITIAL_PROGRESS_TOTAL_PERCENTAGE = 0.05  # Total progress for start phase
  37 PACKAGE_PROGRESS_TOTAL_INCREMENTS = 95    # 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 TYPE_AHEAD_DELAY = 600    # The last type in search box after which search is performed
  43 
  44 CLIENT_API_VERSION = 4
  45 PKG_CLIENT_NAME = "packagemanager"
  46 
  47 import getopt
  48 import os
  49 import sys
  50 import time
  51 import locale
  52 import urlparse
  53 import socket
  54 import gettext
  55 from threading import Thread
  56 from urllib2 import HTTPError, URLError
  57 
  58 try:
  59         import gobject
  60         import gnome
  61         gobject.threads_init()
  62         import gtk
  63         import gtk.glade
  64         import pygtk
  65         pygtk.require("2.0")
  66 except ImportError:
  67         sys.exit(1)
  68 import pkg.client.history as history

  69 import pkg.client.progress as progress
  70 import pkg.client.api_errors as api_errors
  71 import pkg.client.api as api
  72 import pkg.client.retrieve as retrieve
  73 import pkg.portable as portable
  74 import pkg.gui.repository as repository
  75 import pkg.gui.beadmin as beadm
  76 import pkg.gui.imageinfo as imageinfo
  77 import pkg.gui.installupdate as installupdate
  78 import pkg.gui.enumerations as enumerations
  79 from pkg.client import global_settings
  80 
  81 # Put _() in the global namespace
  82 import __builtin__
  83 __builtin__._ = gettext.gettext
  84 
  85 class PackageManager:
  86         def __init__(self):
  87                 self.api_o = None
  88                 socket.setdefaulttimeout(


 255                             }
 256                         dic_progress = \
 257                             {
 258                                 "on_cancel_progressdialog_clicked": \
 259                                     self.__on_cancel_progressdialog_clicked,
 260                             }
 261                         w_tree_main.signal_autoconnect(dic_mainwindow)
 262                         w_tree_progress.signal_autoconnect(dic_progress)
 263                 except AttributeError, error:
 264                         print self._( \
 265                             'GUI will not respond to any event! %s.' + \
 266                             'Check declare_signals()') \
 267                             % error
 268                             
 269                 self.package_selection = None
 270                 self.category_list_filter = None
 271                 self.application_list_filter = None
 272                 self.application_refilter_id = 0 
 273                 self.in_setup = True
 274                 self.w_main_window.show_all()
 275                 gdk_win = self.w_main_window.get_window()
 276                 self.gdk_window = gtk.gdk.Window(gdk_win, gtk.gdk.screen_width(), 
 277                     gtk.gdk.screen_height(), gtk.gdk.WINDOW_CHILD, 0, gtk.gdk.INPUT_ONLY)
 278                 gdk_cursor = gtk.gdk.Cursor(gtk.gdk.WATCH)
 279                 self.gdk_window.set_cursor(gdk_cursor)
 280 
 281         @staticmethod
 282         def __get_new_application_liststore():
 283                 return gtk.ListStore(
 284                         gobject.TYPE_BOOLEAN,     # enumerations.MARK_COLUMN
 285                         gtk.gdk.Pixbuf,           # enumerations.STATUS_ICON_COLUMN
 286                         gtk.gdk.Pixbuf,           # enumerations.ICON_COLUMN
 287                         gobject.TYPE_STRING,      # enumerations.NAME_COLUMN




 288                         gobject.TYPE_STRING,      # enumerations.DESCRIPTION_COLUMN
 289                         gobject.TYPE_INT,         # enumerations.STATUS_COLUMN
 290                         gobject.TYPE_PYOBJECT,    # enumerations.FMRI_COLUMN
 291                         gobject.TYPE_STRING,      # enumerations.STEM_COLUMN
 292                         gobject.TYPE_STRING,      # enumerations.DISPLAY_NAME_COLUMN
 293                         gobject.TYPE_BOOLEAN,     # enumerations.IS_VISIBLE_COLUMN
 294                         gobject.TYPE_PYOBJECT     # enumerations.CATEGORY_LIST_COLUMN
 295                         )
 296 
 297         @staticmethod
 298         def __get_new_category_liststore():
 299                 return gtk.ListStore(
 300                         gobject.TYPE_INT,         # enumerations.CATEGORY_ID
 301                         gobject.TYPE_STRING,      # enumerations.CATEGORY_NAME
 302                         gobject.TYPE_STRING,      # enumerations.CATEGORY_DESCRIPTION
 303                         gtk.gdk.Pixbuf,           # enumerations.CATEGORY_ICON
 304                         gobject.TYPE_BOOLEAN,     # enumerations.CATEGORY_VISIBLE
 305                         gobject.TYPE_PYOBJECT,    # enumerations.SECTION_LIST_OBJECT
 306                         )
 307 
 308         @staticmethod
 309         def __get_new_section_liststore():
 310                 return gtk.ListStore(
 311                         gobject.TYPE_INT,         # enumerations.SECTION_ID
 312                         gobject.TYPE_STRING,      # enumerations.SECTION_NAME
 313                         )
 314 


 362                 column = gtk.TreeViewColumn(self._("Name"), name_renderer, \
 363                     text = enumerations.NAME_COLUMN)
 364                 column.set_resizable(True)
 365                 column.set_sort_column_id(enumerations.NAME_COLUMN)
 366                 column.set_sort_indicator(True)
 367                 column.set_cell_data_func(name_renderer, self.cell_data_function, None)
 368                 self.w_application_treeview.append_column(column)
 369                 column = gtk.TreeViewColumn()
 370                 column.set_title(self._("Status"))
 371                 #Commented, since there was funny jumping of the icons
 372                 #column.set_sizing(gtk.TREE_VIEW_COLUMN_AUTOSIZE)
 373                 render_pixbuf = gtk.CellRendererPixbuf()
 374                 column.pack_start(render_pixbuf, expand = True)
 375                 column.add_attribute(render_pixbuf, "pixbuf", \
 376                     enumerations.STATUS_ICON_COLUMN)
 377                 column.set_fixed_width(32)
 378                 column.set_sort_column_id(enumerations.STATUS_ICON_COLUMN)
 379                 column.set_sort_indicator(True)
 380                 column.set_cell_data_func(render_pixbuf, self.cell_data_function, None)
 381                 self.w_application_treeview.append_column(column)




















 382                 description_renderer = gtk.CellRendererText()
 383                 column = gtk.TreeViewColumn(self._('Description'), \
 384                     description_renderer, text = enumerations.DESCRIPTION_COLUMN)
 385                 column.set_resizable(True)
 386                 column.set_sort_column_id(enumerations.DESCRIPTION_COLUMN)
 387                 column.set_sort_indicator(True)
 388                 column.set_cell_data_func(description_renderer, \
 389                     self.cell_data_function, None)
 390                 self.w_application_treeview.append_column(column)
 391                 #Added selection listener
 392                 self.package_selection = self.w_application_treeview.get_selection()
 393 
 394                 ##CATEGORIES TREEVIEW
 395                 #enumerations.CATEGORY_NAME
 396                 category_list_filter = category_list.filter_new()
 397                 enumerations.CATEGORY_NAME_renderer = gtk.CellRendererText()
 398                 column = gtk.TreeViewColumn(self._('Name'), \
 399                     enumerations.CATEGORY_NAME_renderer, \
 400                     text = enumerations.CATEGORY_NAME)
 401                 self.w_categories_treeview.append_column(column)


 446                 category_list_filter.set_visible_func(self.category_filter)
 447                 toggle_renderer.connect('toggled', self.__active_pane_toggle, \
 448                     application_list_sort)
 449                 category_selection.connect("changed", \
 450                     self.__on_category_selection_changed, None)
 451                 self.package_selection.set_mode(gtk.SELECTION_SINGLE)
 452                 self.package_selection.connect("changed", \
 453                     self.__on_package_selection_changed, None)
 454                 self.first_run = False
 455                 
 456         def __disconnect_models(self):
 457                 self.w_application_treeview.set_model(None)
 458                 self.w_categories_treeview.set_model(None)
 459                 self.w_repository_combobox.set_model(None)
 460                 self.w_sections_combobox.set_model(None)
 461                 self.w_filter_combobox.set_model(None)
 462 
 463         @staticmethod
 464         def __status_sort_func(treemodel, iter1, iter2, user_data=None):
 465                 get_val = treemodel.get_value
 466                 status1 = get_val(iter1, enumerations.STATUS_COLUMN)
 467                 status2 = get_val(iter2, enumerations.STATUS_COLUMN)
 468                 return cmp(status1, status2)










 469 
 470         @staticmethod
 471         def __remove_treeview_columns(treeview):
 472                 columns = treeview.get_columns()
 473                 if columns:
 474                         for column in columns:
 475                                 treeview.remove_column(column)
 476 
 477         def __init_sections(self):
 478                 '''This function is for initializing sections combo box, also adds "All"
 479                 Category. It sets active section combobox entry "All"'''
 480                 self.section_list.append([0, self._('All'), ])
 481                 self.section_list.append([-1, "", ])
 482                 self.section_list.append([2, self._('Meta Packages'), ])
 483                 self.section_list.append([3, self._('Applications'), ])
 484                 self.section_list.append([4, self._('Desktop (GNOME)'), ])
 485                 self.section_list.append([5, self._('Development'), ])
 486                 self.section_list.append([6, self._('Distributions'), ])
 487                 self.section_list.append([7, self._('Drivers'), ])
 488                 self.section_list.append([8, self._('System'), ])


 510                         # XXX if some changes were applied:
 511                         self.__main_application_quit()
 512                         return True
 513                 else:
 514                         self.__main_application_quit()
 515 
 516         def __on_file_quit_activate(self, widget):
 517                 ''' handler for quit menu event '''
 518                 self.__on_mainwindow_delete_event(None, None)
 519 
 520         def __on_edit_repositories_activate(self, widget):
 521                 ''' handler for repository menu event '''
 522                 repository.Repository(self)
 523 
 524         def __on_file_be_activate(self, widget):
 525                 ''' handler for be menu event '''
 526                 beadm.Beadmin(self)
 527 
 528         def __on_searchentry_changed(self, widget):
 529                 '''On text search field changed we should refilter the main view'''
 530                 self.set_busy_cursor()
 531                 if self.application_refilter_id != 0:
 532                         gobject.source_remove(self.application_refilter_id)
 533                         self.application_refilter_id = 0
 534                 if self.w_searchentry_dialog.get_text() == "":
 535                         self.application_refilter_id = \
 536                             gobject.idle_add(self.__application_refilter)
 537                 else:
 538                         self.application_refilter_id = \
 539                             gobject.timeout_add(TYPE_AHEAD_DELAY, 
 540                             self.__application_refilter)
 541 
 542         def __application_refilter(self):
 543                 self.application_list_filter.refilter()
 544                 gobject.idle_add(self.__enable_disable_selection_menus)
 545                 self.application_refilter_id = 0
 546                 return False
 547 
 548         def __on_edit_paste(self, widget):
 549                 self.w_searchentry_dialog.insert_text(self.main_clipboard_text, \
 550                     self.w_searchentry_dialog.get_position())
 551 
 552         def __on_clear_paste(self, widget):
 553                 bounds = self.w_searchentry_dialog.get_selection_bounds()
 554                 self.w_searchentry_dialog.delete_text(bounds[0], bounds[1])
 555                 return
 556 
 557         def __on_copy(self, widget):
 558                 bounds = self.w_searchentry_dialog.get_selection_bounds()
 559                 text = self.w_searchentry_dialog.get_chars(bounds[0], bounds[1])
 560                 self.w_main_clipboard.set_text(text)


 601                 self.__enable_disable_install_update()
 602                 self.__enable_disable_remove()
 603 
 604         def __on_select_updates(self, widget):
 605                 sort_filt_model = \
 606                     self.w_application_treeview.get_model() #gtk.TreeModelSort
 607                 filt_model = sort_filt_model.get_model() #gtk.TreeModelFilter
 608                 model = filt_model.get_model() #gtk.ListStore
 609                 iter_next = sort_filt_model.get_iter_first()
 610                 list_of_paths = []
 611                 while iter_next != None:
 612                         sorted_path = sort_filt_model.get_path(iter_next)
 613                         filtered_iter = sort_filt_model.convert_iter_to_child_iter(None, \
 614                             iter_next)
 615                         app_iter = filt_model.convert_iter_to_child_iter(filtered_iter)
 616 
 617                         filtered_path = \
 618                             sort_filt_model.convert_path_to_child_path(sorted_path)
 619                         path = filt_model.convert_path_to_child_path(filtered_path)
 620                         if model.get_value(app_iter, \
 621                             enumerations.STATUS_COLUMN) == enumerations.UPDATABLE:


 622                                 list_of_paths.append(path)
 623                         iter_next = sort_filt_model.iter_next(iter_next)
 624                 for path in list_of_paths:
 625                         itr = model.get_iter(path)
 626                         model.set_value(itr, enumerations.MARK_COLUMN, True)
 627                 self.__enable_disable_selection_menus()
 628                 self.update_statusbar()
 629                 self.__enable_disable_install_update()
 630                 self.__enable_disable_remove()
 631 
 632         def __on_deselect(self, widget):
 633                 sort_filt_model = \
 634                     self.w_application_treeview.get_model() #gtk.TreeModelSort
 635                 filt_model = sort_filt_model.get_model() #gtk.TreeModelFilter
 636                 model = filt_model.get_model() #gtk.ListStore
 637                 iter_next = sort_filt_model.get_iter_first()
 638                 list_of_paths = []
 639                 while iter_next != None:
 640                         sorted_path = sort_filt_model.get_path(iter_next)
 641                         filtered_iter = sort_filt_model.convert_iter_to_child_iter(None, \


 658         def __on_searchentry_focus_in(self, widget, event):
 659                 self.w_paste_menuitem.set_sensitive(True)
 660 
 661         def __on_searchentry_focus_out(self, widget, event):
 662                 self.w_paste_menuitem.set_sensitive(False)
 663 
 664         def __on_searchentry_event(self, widget, event):
 665                 self.w_main_clipboard.request_text(self.__clipboard_text_received)
 666                 if widget.get_selection_bounds():
 667                         #enable selection functions
 668                         self.w_cut_menuitem.set_sensitive(True)
 669                         self.w_copy_menuitem.set_sensitive(True)
 670                         self.w_clear_menuitem.set_sensitive(True)
 671                 else:
 672                         self.w_cut_menuitem.set_sensitive(False)
 673                         self.w_copy_menuitem.set_sensitive(False)
 674                         self.w_clear_menuitem.set_sensitive(False)
 675 
 676         def __on_category_selection_changed(self, selection, widget):
 677                 '''This function is for handling category selection changes'''
 678                 self.set_busy_cursor()
 679                 gobject.idle_add(self.__application_refilter)
 680 
 681         def __on_package_selection_changed(self, selection, widget):
 682                 '''This function is for handling package selection changes'''
 683                 model, itr = selection.get_selected()
 684                 if itr:
 685                         self.pkginfo_thread += 1
 686                         self.selected_pkgname = \
 687                                model.get_value(itr, enumerations.NAME_COLUMN)
 688                         Thread(target = self.__show_package_info, \
 689                             args = (model, itr, self.pkginfo_thread)).start()
 690                         if self.w_info_notebook.get_current_page() == 3:
 691                                 self.__on_notebook_change(None, None, 3)
 692 
 693 
 694         def __on_filtercombobox_changed(self, widget):
 695                 '''On filter combobox changed'''
 696                 if self.in_setup:
 697                         return
 698                 self.set_busy_cursor()
 699                 gobject.idle_add(self.__application_refilter)
 700 
 701         def __on_sectionscombobox_changed(self, widget):
 702                 '''On section combobox changed'''
 703                 if self.in_setup:
 704                         return
 705                 selected_section = widget.get_active()
 706                 if selected_section == 0:
 707                         for category in self.category_list:
 708                                 category[enumerations.CATEGORY_VISIBLE] = True
 709                 else:
 710                         for category in self.category_list:
 711                                 if category[enumerations.CATEGORY_ID] == 0:
 712                                         category[enumerations.CATEGORY_VISIBLE] = True
 713                                 else:
 714                                         category_list = \
 715                                             category[enumerations.SECTION_LIST_OBJECT]
 716                                         if not category_list:
 717                                                 category[enumerations.CATEGORY_VISIBLE] \
 718                                                     = False
 719                                         else:
 720                                                 for section in category_list:
 721                                                         if section == selected_section:
 722                                                                 category[enumerations. \
 723                                                                     CATEGORY_VISIBLE] = \
 724                                                                     True
 725                                                         else:
 726                                                                 category[enumerations. \
 727                                                                     CATEGORY_VISIBLE] = \
 728                                                                     False
 729                 self.set_busy_cursor()
 730                 self.category_list_filter.refilter()
 731                 gobject.idle_add(self.__application_refilter)

 732 
 733         def __on_repositorycombobox_changed(self, widget):
 734                 '''On repository combobox changed'''
 735                 if self.in_setup:
 736                         return  
 737                 self.set_busy_cursor()
 738                 gobject.idle_add(self.__application_refilter)
 739 
 740         def __on_install_update(self, widget):
 741                 self.api_o.reset()
 742                 install_update = []
 743                 for row in self.application_list:
 744                         if row[enumerations.MARK_COLUMN] and \
 745                             row[enumerations.STATUS_COLUMN] == \
 746                             enumerations.NOT_INSTALLED or \
 747                             row[enumerations.STATUS_COLUMN] == enumerations.UPDATABLE:
 748                                 install_update.append(row[\
 749                                     enumerations.STEM_COLUMN])
 750                 installupdate.InstallUpdate(install_update, self, \
 751                     self.api_o, ips_update = False, \
 752                     action = enumerations.INSTALL_UPDATE)
 753 
 754         def __on_update_all(self, widget):
 755                 opensolaris_image = True
 756                 self.progress_stop_timer_thread = False
 757                 notfound = self.__installed_fmris_from_args(self.api_o, \
 758                     ["SUNWipkg", "SUNWcs"])
 759 
 760                 if notfound:
 761                         opensolaris_image = False
 762 
 763                 if opensolaris_image:
 764                         # Load the catalogs from the repository, its a long 
 765                         # running tasks so need a progress dialog
 766                         self.w_progress_dialog.set_title(self._("Update All"))
 767                         self.w_progressinfo_label.set_text(self._( \
 768                             "Checking SUNWipkg and SUNWipkg-gui versions\n" \
 769                             "\nPlease wait ..."))


 813                             action = enumerations.IMAGE_UPDATE)
 814 
 815         def __on_help_about(self, widget):
 816                 wTreePlan = gtk.glade.XML(self.gladefile, "aboutdialog") 
 817                 aboutdialog = wTreePlan.get_widget("aboutdialog")
 818                 aboutdialog.connect("response", lambda x = None, \
 819                     y = None: aboutdialog.destroy())
 820                 aboutdialog.run()
 821 
 822         def __on_help_help(self, widget):
 823                 props = { gnome.PARAM_APP_DATADIR : self.application_dir + \
 824                             '/usr/share/package-manager/help' }
 825                 gnome.program_init('package-manager', '0.1', properties=props)
 826                 gnome.help_display('package-manager') 
 827 
 828         def __on_remove(self, widget):
 829                 self.api_o.reset()
 830                 remove_list = []
 831                 for pkg in self.application_list:
 832                         if pkg[enumerations.MARK_COLUMN] and \
 833                             pkg[enumerations.STATUS_COLUMN] == enumerations.INSTALLED or \
 834                             pkg[enumerations.STATUS_COLUMN] == enumerations.UPDATABLE:
 835                                 remove_list.append(\
 836                                     pkg[enumerations.STEM_COLUMN])
 837                 installupdate.InstallUpdate(remove_list, self, \
 838                     self.api_o, ips_update = False, \
 839                     action = enumerations.REMOVE)
 840 
 841         def __on_reload(self, widget):
 842                 if self.description_thread_running:
 843                         self.cancelled = True
 844                 self.in_setup = True
 845                 self.w_progress_dialog.set_title(self._("Refreshing catalogs"))
 846                 self.w_progressinfo_label.set_text(self._("Refreshing catalogs..."))
 847                 self.progress_stop_timer_thread = False
 848                 Thread(target = self.__progressdialog_progress_pulse).start()
 849                 self.w_progress_dialog.show()
 850                 self.__disconnect_models()
 851                 Thread(target = self.__catalog_refresh).start()
 852 
 853         def __catalog_refresh_done(self):
 854                 self.progress_stop_timer_thread = True
 855                 #Let the progress_pulse finish. This should be done other way, but at
 856                 #The moment this works fine


 903 
 904                         repositories_list.append([i, repo, ])
 905                         i = i + 1
 906                 self.w_repository_combobox.set_model(repositories_list)
 907                 if default_authority:
 908                         self.w_repository_combobox.set_active(active)
 909                 else:
 910                         self.w_repository_combobox.set_active(0)
 911 
 912         def __active_pane_toggle(self, cell, path, model_sort):
 913                 '''Toggle function for column enumerations.MARK_COLUMN'''
 914                 applicationModel = model_sort.get_model()
 915                 applicationPath = model_sort.convert_path_to_child_path(path)
 916                 filterModel = applicationModel.get_model()
 917                 child_path = applicationModel.convert_path_to_child_path(applicationPath)
 918                 itr = filterModel.get_iter(child_path)
 919                 if itr:
 920                         modified = filterModel.get_value(itr, enumerations.MARK_COLUMN)
 921                         filterModel.set_value(itr, enumerations.MARK_COLUMN, \
 922                             not modified)
 923                         pkg_status = filterModel.get_value(itr, \
 924                             enumerations.STATUS_COLUMN)


 925                         self.update_statusbar()
 926                         self.__update_install_update_button(pkg_status, modified)
 927                         self.__update_remove_button(pkg_status, modified)
 928                         self.__enable_disable_selection_menus()
 929 
 930 
 931         def __update_install_update_button(self, pkg_status, toggle_true):
 932                 if not toggle_true and self.user_rights:
 933                         if pkg_status == enumerations.NOT_INSTALLED or \
 934                                             pkg_status == enumerations.UPDATABLE:
 935                                 self.w_installupdate_button.set_sensitive(True)
 936                                 self.w_installupdate_menuitem.set_sensitive(True)
 937                                 return
 938                 elif self.user_rights:
 939                         instup_button = self.w_installupdate_button
 940                         instup_menu = self.w_installupdate_menuitem
 941                         for row in self.application_list:
 942                                 if row[enumerations.MARK_COLUMN]:
 943                                         status = row[enumerations.STATUS_COLUMN]
 944                                         if status == enumerations.NOT_INSTALLED or \
 945                                             status == enumerations.UPDATABLE:
 946                                                 instup_button.set_sensitive(True)
 947                                                 instup_menu.set_sensitive(True)
 948                                                 return
 949                 else:
 950                         self.w_installupdate_button.set_sensitive(False)
 951                         self.w_installupdate_menuitem.set_sensitive(False)
 952 
 953         def __update_reload_button(self):
 954                 if self.user_rights:
 955                         self.w_reload_button.set_sensitive(True)
 956                 else:
 957                         self.w_reload_button.set_sensitive(False)
 958 
 959         def __update_remove_button(self, pkg_status, toggle_true):
 960                 if not toggle_true and self.user_rights:
 961                         if pkg_status == enumerations.INSTALLED or \
 962                             pkg_status == enumerations.UPDATABLE:
 963                                 self.w_remove_button.set_sensitive(True)
 964                                 self.w_remove_menuitem.set_sensitive(True)
 965                                 return
 966                 elif self.user_rights:
 967                         for row in self.application_list:
 968                                 if row[enumerations.MARK_COLUMN]:
 969                                         status = row[enumerations.STATUS_COLUMN]
 970                                         if status == enumerations.INSTALLED or \
 971                                             status == enumerations.UPDATABLE:
 972                                                 self.w_remove_button.set_sensitive(True)
 973                                                 self.w_remove_menuitem.set_sensitive(True)
 974                                                 return
 975                 else:
 976                         self.w_remove_button.set_sensitive(False)
 977                         self.w_remove_menuitem.set_sensitive(False)
 978 
 979         def __show_fetching_package_info(self, pkg, icon):
 980                 pkg_name = pkg.get_name()
 981                 if icon and icon != pkg:
 982                         self.w_packageicon_image.set_from_pixbuf(icon)
 983                 else:
 984                         self.w_packageicon_image.set_from_pixbuf( \
 985                             self.__get_pixbuf_from_path("/usr/share/package-manager/", \
 986                             "PM_package_36x"))
 987                 self.w_packagename_label.set_markup("<b>" + pkg_name + "</b>")
 988 
 989                 pkg_stem = pkg.get_pkg_stem()                
 990                 if self.__setting_from_cache(pkg_stem):
 991                         return
 992                         
 993                 self.w_shortdescription_label.set_text( \
 994                     self._("Fetching description..."))
 995                 instbuffer = self.w_installedfiles_textview.get_buffer()
 996                 depbuffer = self.w_dependencies_textview.get_buffer()
 997                 infobuffer = self.w_generalinfo_textview.get_buffer()
 998                 instbuffer.set_text(self._("Fetching information..."))
 999                 depbuffer.set_text(self._("Fetching information..."))
1000                 infobuffer.set_text(self._("Fetching information..."))
1001                 return
1002                 
1003         def __setting_from_cache(self, pkg_stem):
1004                 if len(self.info_cache) > MAX_INFO_CACHE_LIMIT:
1005                         self.info_cache = {}
1006 
1007                 if self.info_cache.has_key(pkg_stem):
1008                         self.w_shortdescription_label.set_text(\
1009                                 self.info_cache[pkg_stem][0])
1010                         instbuffer = self.w_installedfiles_textview.get_buffer()
1011                         depbuffer = self.w_dependencies_textview.get_buffer()
1012                         infobuffer = self.w_generalinfo_textview.get_buffer()
1013                         infobuffer.set_text(self.info_cache[pkg_stem][1])
1014                         instbuffer.set_text(self.info_cache[pkg_stem][2])
1015                         depbuffer.set_text(self.info_cache[pkg_stem][3])
1016                         return True
1017                 else:
1018                         return False
1019                 
1020         def __update_package_info(self, pkg, icon, installed, pkg_info):
1021                 pkg_name = pkg.get_name()
1022                 pkg_stem = pkg.get_pkg_stem()
1023                 if icon and icon != pkg:
1024                         self.w_packageicon_image.set_from_pixbuf(icon)
1025                 else:
1026                         self.w_packageicon_image.set_from_pixbuf( \
1027                             self.__get_pixbuf_from_path("/usr/share/package-manager/", \
1028                             "PM_package_36x"))
1029                 self.w_packagename_label.set_markup("<b>" + pkg_name + "</b>")
1030                 
1031                 if self.__setting_from_cache(pkg_stem):
1032                         return
1033                         
1034                 instbuffer = self.w_installedfiles_textview.get_buffer()
1035                 depbuffer = self.w_dependencies_textview.get_buffer()
1036                 infobuffer = self.w_generalinfo_textview.get_buffer()
1037 
1038                 if not pkg_info:
1039                         self.w_shortdescription_label.set_text( \
1040                             self._("Description not available for this package..."))
1041                         instbuffer.set_text( \
1042                             self._("Files Details not available for this package..."))
1043                         depbuffer.set_text(self._( \
1044                             "Dependencies info not available for this package..."))
1045                         infobuffer.set_text( \
1046                             self._("Information not available for this package..."))
1047                         return
1048                 description = pkg_info.summary
1049                 #XXX long term need to have something more robust here for multi byte
1050                 if len(description) > MAX_DESC_LEN:
1051                         description = description[:MAX_DESC_LEN] + " ..."


1072                 if pkg_info.files:
1073                         inst_str += ''.join(["\t%s\n" % x for x in pkg_info.files])
1074                 if pkg_info.hardlinks:
1075                         inst_str += ''.join(["\t%s\n" % x for x in pkg_info.hardlinks])
1076                 if pkg_info.links:
1077                         inst_str += ''.join(["\t%s\n" % x for x in pkg_info.links])
1078                         
1079                 if description:
1080                         info_str += self._("  Description:\t%s\n") % description
1081                 info_str += self._("  Name:\t\t%s\n") % pkg_name
1082                 info_str += self._("  FMRI:\t\t%s\n") % pkg.get_fmri()
1083                 info_str +=  self._("  Version:\t\t%s\n") % \
1084                     pkg.version.get_short_version()
1085                 info_str +=  self._("  Packaged:\t%s\n") % \
1086                     self.get_datetime(pkg.version)
1087                 
1088                 infobuffer.set_text(info_str)
1089                 instbuffer.set_text(inst_str)
1090                 depbuffer.set_text(dep_str)
1091 
1092                 self.info_cache[pkg_stem] = \
1093                         (description, info_str, inst_str, dep_str)
1094                 
1095         def __update_package_license(self, licenses):
1096                 lic = ""
1097                 lic_u = ""
1098                 if licenses == None:
1099                         lic_u = self._("Not available")
1100                 else:
1101                         for licens in licenses:
1102                                 lic += licens.get_text()
1103                                 lic += "\n"
1104                         try:
1105                                 lic_u = unicode(lic, "utf-8")
1106                         except UnicodeDecodeError:
1107                                 lic_u += ""
1108                 licbuffer = self.w_license_textview.get_buffer()
1109                 licbuffer.set_text(lic_u)
1110 








1111         def __show_package_licenses(self, th_no):
1112                 #XXX revisit this and replace with gobject.timer_add() instead of sleep
1113                 # sleep for a little time, this is done for the users who are
1114                 # fast browsing the list of the packages.
1115                 time.sleep(1)
1116                 if th_no != self.pkginfo_thread:
1117                         return
1118                 if self.selected_pkgname == None:
1119                         gobject.idle_add(self.__update_package_license, \
1120                             None)
1121                         return
1122                 info = self.api_o.info([self.selected_pkgname], True, True)
1123                 pkgs_info = None
1124                 package_info = None
1125                 no_licenses = 0
1126                 if info:
1127                         pkgs_info = info[0]
1128                 if pkgs_info:
1129                         package_info = pkgs_info[0]
1130                 if package_info:


1137                         gobject.idle_add(self.__update_package_license, \
1138                             package_info.licenses)
1139                 else:
1140                         return
1141 
1142         def __get_pkg_info(self, pkg_name, installed):
1143                 info = self.api_o.info([pkg_name], installed, get_licenses=False, \
1144                                 get_action_info=True)
1145                 pkgs_info = None
1146                 package_info = None
1147                 if info:
1148                         pkgs_info = info[0]
1149                 if pkgs_info:
1150                         package_info = pkgs_info[0]
1151                 if package_info:
1152                         return package_info
1153                 else:
1154                         return
1155 
1156         def __show_package_info(self, model, itr, th_no):


1157                 installed = False
1158                 pkg = model.get_value(itr, enumerations.FMRI_COLUMN)
1159                 status = model.get_value(itr, enumerations.STATUS_COLUMN)
1160                 if status == enumerations.UPDATABLE or status == enumerations.INSTALLED:






1161                         installed = True
1162                 gobject.idle_add( \
1163                         self.__show_fetching_package_info, pkg, pkg)
1164                         
1165                 if self.info_cache.has_key(pkg.get_pkg_stem()):
1166                         return
1167 
1168                 # sleep for a little time, this is done for the users which are
1169                 # fast browsing the list of the packages.
1170                 time.sleep(1)
1171                 if th_no != self.pkginfo_thread:
1172                         return

1173                 img = self.api_o.img
1174                 img.history.operation_name = "info"
1175 
1176                 pkg_info = self.__get_pkg_info(pkg.get_name(), installed)
1177                 if th_no == self.pkginfo_thread:
1178                         if not pkg:
1179                                 gobject.idle_add(self.__update_package_info, pkg, pkg, \
1180                                     installed, pkg_info)
1181                         else:
1182                                 gobject.idle_add(self.__update_package_info, pkg, pkg, \
1183                                     installed, pkg_info)
1184                         img.history.operation_result = \
1185                             history.RESULT_SUCCEEDED
1186                 else:
1187                         img.history.operation_result = \
1188                             history.RESULT_SUCCEEDED
1189                         return
1190 
1191         # This function is ported from pkg.actions.generic.distinguished_name()
1192         def __locale_distinguished_name(self, action):
1193                 if action.key_attr == None:
1194                         return str(action)
1195                 return "%s: %s" % \
1196                     (self._(action.name), action.attrs.get(action.key_attr, "???"))
1197 
1198         def __application_filter(self, model, itr):
1199                 '''This function is used to filter content in the main 
1200                 application view'''
1201                 if self.in_setup or self.cancelled:
1202                         return False
1203                 # XXX Show filter, chenge text to integers 
1204                 selected_category = 0
1205                 selection = self.w_categories_treeview.get_selection()
1206                 category_model, category_iter = selection.get_selected()
1207                 if not category_iter:         #no category was selected, so select "All"
1208                         selection.select_path(0)
1209                         category_model, category_iter = selection.get_selected()
1210                 if category_iter:
1211                         selected_category = category_model.get_value(category_iter, \
1212                             enumerations.CATEGORY_ID)
1213                 category_list_iter = model.get_value(itr, \
1214                     enumerations.CATEGORY_LIST_COLUMN)
1215                 category = False
1216                 repo = self.__is_pkg_repository_visible(model, itr)
1217                 if category_list_iter:
1218                         sel = False
1219                         for category_iter in category_list_iter:
1220                                 if category != True:
1221                                         category = \
1222                                             self.category_filter(self.category_list, \
1223                                             category_iter)
1224                                 if selected_category != 0:
1225                                         if selected_category == \
1226                                             self.category_list.get_value(category_iter, \
1227                                             enumerations.CATEGORY_ID):
1228                                                 sel = True
1229                                         category = sel
1230                 else:
1231                         if selected_category == 0:
1232                                 selected_section = self.w_sections_combobox.get_active()
1233                                 if selected_section == 0:
1234                                         category = True


1242                             model.get_value \
1243                             (itr, enumerations.NAME_COLUMN).lower():
1244                                 return (repo & category & \
1245                                     self.__is_package_filtered(model, itr))
1246                 if not model.get_value(itr, enumerations.DESCRIPTION_COLUMN) == None:
1247                         if self.w_searchentry_dialog.get_text().lower() in \
1248                             model.get_value \
1249                             (itr, enumerations.DESCRIPTION_COLUMN).lower():
1250                                 return (repo & category & \
1251                                     self.__is_package_filtered(model, itr))
1252                 else:
1253                         return False
1254 
1255         def __is_package_filtered(self, model, itr):
1256                 '''Function for filtercombobox'''
1257                 # XXX Instead of string comparison, we should do it through integers.
1258                 # XXX It should be faster and better for localisations.
1259                 filter_text = self.w_filter_combobox.get_active()
1260                 if filter_text == 0:
1261                         return True
1262                 status = model.get_value(itr, enumerations.STATUS_COLUMN)
1263                 if filter_text == 2:
1264                         return (status == enumerations.INSTALLED or status == \
1265                             enumerations.UPDATABLE)
1266                 elif filter_text == 3:
1267                         return status == enumerations.UPDATABLE



1268                 elif filter_text == 4:
1269                         return status == enumerations.NOT_INSTALLED

1270                 elif filter_text == 6:
1271                         return model.get_value(itr, enumerations.MARK_COLUMN)
1272                 elif filter_text == 8:
1273                         # XXX Locked support
1274                         return False
1275 
1276 
1277         def __is_pkg_repository_visible(self, model, itr):
1278                 if len(self.repositories_list) <= 1:
1279                         return True
1280                 else:
1281                         auth_iter = self.w_repository_combobox.get_active_iter()
1282                         authority = self.repositories_list.get_value(auth_iter, \
1283                             enumerations.REPOSITORY_NAME)
1284                         pkg = model.get_value(itr, \
1285                             enumerations.FMRI_COLUMN)
1286                         if not pkg:
1287                                 return False

1288                         if cmp(pkg.get_authority(), authority) == 0:
1289                                 return True
1290                         else:
1291                                 return False
1292 
1293         def __do_ips_uptodate_check(self):
1294                 ret = self.__catalog_refresh(False)
1295                 if ret != -1:
1296                         self.ips_uptodate = self.__ipkg_ipkgui_uptodate()
1297                 else:
1298                         self.progress_canceled = True
1299                 self.progress_stop_timer_thread = True
1300 
1301         def __ipkg_ipkgui_uptodate(self):
1302                 self.api_o.reset()
1303                 list_of_packages = [self.ipkg_fmri, self.ipkggui_fmri]
1304                 ret = True
1305                 try:
1306                         upgrade_needed, cre = self.api_o.plan_install(
1307                             list_of_packages, filters = [])


1324                 self.__enable_disable_deselect()
1325                 # XXX disabled until new API
1326                 self.__enable_disable_update_all()
1327 
1328         def __enable_disable_select_all(self):
1329                 
1330                 if self.in_setup:
1331                         return
1332                 if len(self.w_application_treeview.get_model()) > 0:
1333                         for row in self.w_application_treeview.get_model():
1334                                 if not row[enumerations.MARK_COLUMN]:
1335                                         self.w_selectall_menuitem.set_sensitive(True)
1336                                         return
1337                         self.w_selectall_menuitem.set_sensitive(False)
1338                 else:
1339                         self.w_selectall_menuitem.set_sensitive(False)
1340 
1341         def __enable_disable_install_update(self):
1342                 for row in self.application_list:
1343                         if row[enumerations.MARK_COLUMN]:
1344                                 status = row[enumerations.STATUS_COLUMN]
1345                                 if self.user_rights and \
1346                                     (status == enumerations.UPDATABLE or 
1347                                     status == enumerations.NOT_INSTALLED):
1348                                         self.w_installupdate_button.set_sensitive(True)
1349                                         self.w_installupdate_menuitem.set_sensitive(True)
1350                                         return
1351                 self.w_installupdate_button.set_sensitive(False)
1352                 self.w_installupdate_menuitem.set_sensitive(False)
1353 
1354         def __enable_disable_remove(self):
1355                 for row in self.application_list:
1356                         if row[enumerations.MARK_COLUMN]:
1357                                 status = row[enumerations.STATUS_COLUMN]
1358                                 if self.user_rights and \
1359                                     (status == enumerations.UPDATABLE or 
1360                                     status == enumerations.INSTALLED):
1361                                         self.w_remove_button.set_sensitive(True)
1362                                         self.w_remove_menuitem.set_sensitive(True)
1363                                         return
1364                 self.w_remove_button.set_sensitive(False)
1365                 self.w_remove_menuitem.set_sensitive(False)
1366 
1367         def __enable_disable_select_updates(self):
1368                 for row in self.w_application_treeview.get_model():
1369                         if row[enumerations.STATUS_COLUMN] == enumerations.UPDATABLE:

1370                                 if not row[enumerations.MARK_COLUMN]:
1371                                         self.w_selectupdates_menuitem. \
1372                                             set_sensitive(True)
1373                                         return
1374                 self.w_selectupdates_menuitem.set_sensitive(False)
1375                 return
1376 
1377         def __enable_disable_update_all(self):
1378                 for row in self.application_list:
1379                         if self.__is_pkg_repository_visible(self.application_list, \
1380                             row.iter):
1381                                 if self.application_list.get_value(row.iter, \
1382                                     enumerations.STATUS_COLUMN) == \
1383                                     enumerations.UPDATABLE and self.user_rights:


1384                                         self.w_updateall_menuitem. \
1385                                             set_sensitive(True)
1386                                         self.w_updateall_button. \
1387                                             set_sensitive(True)
1388                                         return
1389                 self.w_updateall_button.set_sensitive(False)
1390                 self.w_updateall_menuitem.set_sensitive(False)
1391                 self.unset_busy_cursor()
1392 
1393         def __enable_disable_deselect(self):
1394                 for row in self.w_application_treeview.get_model():
1395                         if row[enumerations.MARK_COLUMN]:
1396                                 self.w_deselect_menuitem.set_sensitive(True)
1397                                 return
1398                 self.w_deselect_menuitem.set_sensitive(False)
1399                 return
1400 
1401 
1402         def __catalog_refresh(self, reload_gui=True):
1403                 """Update image's catalogs."""
1404                 full_refresh = True
1405                 try:
1406                         self.api_o.refresh(full_refresh)
1407                         self.api_o.img.load_catalogs(self.pr)
1408                 except api_errors.UnrecognizedAuthorityException:
1409                         # In current implementation, this will never happen
1410                         # We are not refrehsing specific authority
1411                         self.__catalog_refresh_done()
1412                         raise
1413                 except api_errors.PermissionsException:
1414                         #Error will already have been reported in 
1415                         #Manage Repository dialog
1416                         self.__catalog_refresh_done()
1417                         return -1
1418                 except api_errors.CatalogRefreshException, cre:
1419                         total = cre.total
1420                         succeeded = cre.succeeded
1421                         ermsg = self._("Network problem.\n\n")
1422                         ermsg += self._("Details:\n")
1423                         ermsg += "%s/%s" % (succeeded, total) 
1424                         ermsg += self._(" catalogs successfully updated:\n") 
1425                         for auth, err in cre.failed:
1426                                 if isinstance(err, HTTPError):
1427                                         ermsg += "   %s: %s - %s\n" % \
1428                                             (err.filename, err.code, err.msg)
1429                                 elif isinstance(err, URLError):
1430                                         if err.args[0][0] == 8:
1431                                                 ermsg += "    %s: %s\n" % \
1432                                                     (urlparse.urlsplit(
1433                                                         auth["origin"])[1].split(":")[0],


1451                             None, gtk.MESSAGE_INFO)
1452                         self.__catalog_refresh_done()
1453                         return -1
1454 
1455                 except api_errors.UnrecognizedAuthorityException:
1456                         self.__catalog_refresh_done()
1457                         raise
1458                 except Exception:
1459                         self.__catalog_refresh_done()
1460                         raise
1461                 if reload_gui:
1462                         self.__catalog_refresh_done()
1463                 return 0
1464 
1465         def __get_image_from_directory(self, api_o, progressdialog_progress):
1466                 """ This method set up image from the given directory and
1467                 returns the image object or None"""
1468                 application_list = self.__get_new_application_liststore()
1469                 category_list = self.__get_new_category_liststore()
1470                 repositories_list = self.__get_new_repositories_liststore()
1471                 authority = api_o.img.get_default_authority()
1472                 most_recent = {}
1473                 installed = []
1474                 try:
1475                         pkgs_known = api_o.img.inventory(all_known=True)
1476                         for pfmri, state in pkgs_known:
1477                                 if state["state"] == "installed":
1478                                         installed.append((pfmri, state))
1479                                 hv = pfmri.get_pkg_stem(include_pkg=False)
1480                                 if hv in most_recent:
1481                                         stored_pfmri, stored_state = \
1482                                             most_recent[hv]
1483                                         if pfmri.is_successor(stored_pfmri):
1484                                                 most_recent[hv] = (pfmri, state)
1485                                 else:
1486                                         most_recent[hv] = (pfmri, state)
1487                         pkgs_known = installed + most_recent.values()
1488 
1489                         # This method is necessary because fmri.__cmp__ does
1490                         # not provide the desired ordering. It uses the same
1491                         # ordering on package names as fmri.__cmp__ but it
1492                         # reverse sorts on version, so that 98 comes before 97.
1493                         # Also, authorities are taken into account so that
1494                         # preferred authorities come before others. Finally,
1495                         # authorties are presented in alphabetical order.
1496                         def __fmri_cmp((f1, s1), (f2, s2)):
1497                                 t = cmp(f1.pkg_name, f2.pkg_name)
1498                                 if t != 0:
1499                                         return t
1500                                 t = cmp(f2, f1)
1501                                 if t != 0:
1502                                         return t
1503                                 if f1.preferred_authority():
1504                                         return -1
1505                                 if f2.preferred_authority():
1506                                         return 1
1507                                 return cmp(f1.get_authority(),
1508                                     f2.get_authority())
1509                         
1510                         pkgs_known.sort(cmp=__fmri_cmp)
1511                 except api_errors.InventoryException:
1512                         # Can't happen when all_known is true and no args,
1513                         # but here for completeness.
1514                         err = self._("Error occured while getting list of packages")
1515                         gobject.idle_add(self.w_progress_dialog.hide)
1516                         gobject.idle_add(self.error_occured, err)
1517                         return
1518 
1519                 #Only one instance of those icons should be in memory
1520                 update_available_icon = self.get_icon_pixbuf("status_newupdate")
1521                 installed_icon = self.get_icon_pixbuf("status_installed")
1522                 #Imageinfo for categories
1523                 imginfo = imageinfo.ImageInfo()
1524                 sectioninfo = imageinfo.ImageInfo()
1525                 catalogs = api_o.img.catalogs
1526                 categories = {}
1527                 sections = {}
1528                 share_path = "/usr/share/package-manager/data/"
1529                 for cat in catalogs:
1530                         category = imginfo.read(self.application_dir +
1531                             share_path + cat)
1532                         if len(category) == 0:
1533                                 category = imginfo.read(self.application_dir +
1534                                     share_path + "opensolaris.org")
1535                         categories[cat] = category
1536                         section = sectioninfo.read(self.application_dir +
1537                             share_path + cat + ".sections")
1538                         if len(section) == 0:
1539                                 section = sectioninfo.read(self.application_dir +
1540                                     share_path + "opensolaris.org.sections")
1541                         sections[cat] = section









1542                 icon_path = self.application_dir + \
1543                     "/usr/share/package-manager/data/pixmaps/"

1544                 pkg_count = 0
1545                 progress_percent = INITIAL_PROGRESS_TOTAL_PERCENTAGE
1546                 total_pkg_count = len(pkgs_known)
1547                 progress_increment = \
1548                         total_pkg_count / PACKAGE_PROGRESS_TOTAL_INCREMENTS

1549                 self.progress_stop_timer_thread = True
1550                 while gtk.events_pending():
1551                         gtk.main_iteration(False)
1552                 prev_pfmri_str = ""
1553                 prev_state = None
1554                 for pkg, state in pkgs_known:
1555                         if prev_pfmri_str and \
1556                             prev_pfmri_str == pkg.get_short_fmri() and \
1557                             prev_state == state:
1558                                 continue
1559                         prev_pfmri_str = pkg.get_short_fmri()
1560                         prev_state = state
1561 
1562                         if progress_increment > 0 and pkg_count % progress_increment == 0:
1563                                 progress_percent += PACKAGE_PROGRESS_PERCENT_INCREMENT
1564                                 if progress_percent <= PACKAGE_PROGRESS_PERCENT_TOTAL:
1565                                         progressdialog_progress(progress_percent,
1566                                             pkg_count, total_pkg_count)
1567                                 while gtk.events_pending():
1568                                         gtk.main_iteration(False)

1569 






1570                         status_icon = None
1571                         pkg_name = pkg.get_name()
1572                         pkg_stem = pkg.get_pkg_stem()
1573                         package_icon = self.__get_pixbuf_from_path(icon_path, pkg_name) 
1574                         pkg_state = enumerations.NOT_INSTALLED
1575                         if state["state"] == "installed":
1576                                 pkg_state = enumerations.INSTALLED
1577                                 if state["upgradable"] == True:
1578                                         status_icon = update_available_icon
1579                                         pkg_state = enumerations.UPDATABLE


1580                                 else:
1581                                         status_icon = installed_icon





1582                         app = \
1583                             [
1584                                 False, status_icon, package_icon, pkg_name,
1585                                 '...', pkg_state, pkg, pkg_stem, None, True, None


1586                             ]
1587                         row_iter = application_list.insert(pkg_count, app)
1588                         pkg_count += 1








1589                         apc = self.__add_package_to_category
1590                         app_ls = application_list
1591                         for cat in categories:
1592                                 if cat in categories:
1593                                         if pkg_name in categories[cat]:
1594                                                 pkg_categories = categories[cat][pkg_name]
1595                                                 for pcat in pkg_categories.split(","):




1596                                                         if pcat:
1597                                                                 apc(self._(pcat), None,
1598                                                                     None, row_iter,
1599                                                                     app_ls, category_list)
























































1600                 for authority in sections:
1601                         for section in sections[authority]:
1602                                 for category in sections[authority][section].split(","):
1603                                         self.__add_category_to_section(self._(category),
1604                                             self._(section), category_list)
1605  
1606                 #1915 Sort the Categories into alphabetical order and prepend All Category
1607                 if len(category_list) > 0:
1608                         rows = [tuple(r) + (i,) for i, r in enumerate(category_list)]
1609                         rows.sort(self.__sort)
1610                         r = []
1611                         category_list.reorder([r[-1] for r in rows])
1612                 category_list.prepend([0, self._('All'), None, None, True, None])
1613 
1614                 progressdialog_progress(PACKAGE_PROGRESS_PERCENT_TOTAL, total_pkg_count,
1615                     total_pkg_count)
1616                 gobject.idle_add(self.process_package_list_end, api_o,
1617                     application_list, category_list, repositories_list)
1618                 return
1619 
1620         def __add_package_to_category(self, category_name, category_description, \
1621             category_icon, package, application_list, category_list):
1622                 if not package or category_name == self._('All'):
1623                         return
1624                 if not category_name:
1625                         return
1626                         # XXX check if needed
1627                         # category_name = self._('All')
1628                         # category_description = self._('All packages')
1629                         # category_icon = None
1630                 category_ref = None
1631                 for category in category_list:
1632                         if category[enumerations.CATEGORY_NAME] == category_name:
1633                                 category_ref = category.iter
1634                 if not category_ref:                       # Category not exists
1635                         category_ref = category_list.append([len( \
1636                             category_list)+1, category_name, category_description, \
1637                             category_icon, True, None])
1638                 if category_ref:
1639                         if application_list.get_value(package, \
1640                             enumerations.CATEGORY_LIST_COLUMN):
1641                                 a = application_list.get_value(package, \
1642                                     enumerations.CATEGORY_LIST_COLUMN)
1643                                 a.append(category_ref)
1644                         else:
1645                                 category_list = []
1646                                 category_list.append(category_ref)
1647                                 application_list.set(package, \
1648                                     enumerations.CATEGORY_LIST_COLUMN, category_list)
1649 
1650         def __add_category_to_section(self, category_name, section_name, category_list):
1651                 '''Adds the section to section list in category. If there is no such 
1652                 section, than it is not added. If there was already section than it
1653                 is skipped. Sections must be case sensitive'''
1654                 if not category_name:
1655                         return
1656                 for section in self.section_list:
1657                         if section[enumerations.SECTION_NAME] == section_name:
1658                                 for category in category_list:
1659                                         if category[enumerations.CATEGORY_NAME] == \
1660                                             category_name:
1661                                                 if not category[ \
1662                                                     enumerations.SECTION_LIST_OBJECT]:
1663                                                         category[ \
1664                                                             enumerations. \
1665                                                             SECTION_LIST_OBJECT] = \
1666                                                             [section[ \
1667                                                             enumerations.SECTION_ID], ]
1668                                                 else:


1773         @staticmethod
1774         def cell_data_function(column, renderer, model, itr, data):
1775                 '''Function which sets the background colour to black if package is 
1776                 selected'''
1777                 if itr:
1778                         if model.get_value(itr, enumerations.MARK_COLUMN):
1779                                 renderer.set_property("cell-background", "#ffe5cc")
1780                                 renderer.set_property("cell-background-set", True)
1781                         else:
1782                                 renderer.set_property("cell-background-set", False)
1783 
1784         @staticmethod
1785         def combobox_separator(model, itr):
1786                 return model.get_value(itr, enumerations.FILTER_NAME) == ""
1787 
1788         @staticmethod
1789         def combobox_id_separator(model, itr):
1790                 return model.get_value(itr, 0) == -1
1791 
1792         @staticmethod










1793         def category_filter(model, itr):
1794                 '''This function filters category in the main application view'''
1795                 return model.get_value(itr, enumerations.CATEGORY_VISIBLE)
1796 
1797         @staticmethod
1798         def get_datetime(version):
1799                 dt = None
1800                 try:
1801                         dt = version.get_datetime()
1802                 except AttributeError:
1803                         dt = version.get_timestamp()
1804                 return dt
1805 
1806         @staticmethod
1807         def get_installed_version(api_o, pkg):
1808                 return api_o.img.get_version_installed(pkg)
1809 
1810         @staticmethod
1811         def get_manifest(img, package, filtered = True):
1812                 '''helper function'''


1837 # Public Methods
1838 #-----------------------------------------------------------------------------#
1839         def setup_progressdialog_show(self):
1840                 self.w_progress_dialog.set_title(self._("Loading Repository Information"))
1841                 self.w_progressinfo_label.set_text(
1842                     self._( "Fetching package entries ..."))
1843                 self.w_progress_cancel.hide()
1844                 self.w_progress_dialog.show()
1845                 Thread(target = self.__progressdialog_progress_time).start()
1846         
1847         def init_sections(self):
1848                 self.__init_sections()                   #Initiates sections
1849 
1850         def init_show_filter(self):
1851                 self.__init_show_filter()                #Initiates filter
1852 
1853         def reload_packages(self):
1854                 self.api_o = self.__get_api_object(self.image_directory, self.pr)
1855                 self.__on_reload(None)
1856 
1857         def set_busy_cursor(self):
1858                 self.gdk_window.show()
1859     
1860         def unset_busy_cursor(self):
1861                 self.gdk_window.hide()
1862 
1863         def process_package_list_start(self, image_directory):
1864                 self.cancelled = True
1865                 self.setup_progressdialog_show()
1866                 while gtk.events_pending():
1867                         gtk.main_iteration(False)
1868                 self.image_directory = image_directory
1869                 # Create our image object based on image directory.
1870                 api_o = self.__get_api_object(image_directory, self.pr)
1871                 api_o.img.load_catalogs(self.pr)
1872                 self.api_o = api_o
1873                 # Acquire image contents and update progress bar as you do so.
1874                 Thread(target = self.__get_image_from_directory, args = (api_o,
1875                         self.__progressdialog_progress_percent)).start()
1876 
1877         @staticmethod
1878         def __get_api_object(img_dir, progtrack):
1879                 api_o = None
1880                 try:
1881                         api_o = api.ImageInterface(img_dir, \
1882                             CLIENT_API_VERSION, \


1906                 self.w_progress_dialog.hide()
1907 
1908         def __get_manifests_thread(self):
1909                 Thread(target = self.get_manifests_for_packages,
1910                     args = ()).start()
1911 
1912         def get_icon_pixbuf(self, icon_name):
1913                 #2821: The get_icon_pixbuf should use PACKAGE_MANAGER_ROOT
1914                 return self.__get_pixbuf_from_path(self.application_dir + \
1915                     "/usr/share/icons/package-manager/", icon_name)
1916                 
1917         def get_manifests_for_packages(self):
1918                 ''' Function, which get's manifest for packages. If the manifest is not
1919                 locally tries to retrieve it. For installed packages gets manifest
1920                 for the particular version (local operation only), if the package is 
1921                 not installed than the newest one'''
1922                 time.sleep(3)
1923                 count = 0
1924                 self.description_thread_running = True
1925                 img = self.api_o.img

1926                 for pkg in self.application_list:
1927                         if self.cancelled:
1928                                 self.description_thread_running = False
1929                                 return
1930                         info = None
1931                         package = pkg[enumerations.FMRI_COLUMN]

1932                         if (img and package):
1933                                 man = self.get_manifest(img, package, filtered = True)
1934                                 if man:
1935                                         info = man.get("description", "")







1936                         gobject.idle_add(self.update_desc, info, pkg)
1937                         count += 1
1938                         if count % 2 ==  0:
1939                                 time.sleep(0.001)
1940                 img.history.operation_name = "info"

1941                 img.history.operation_result = history.RESULT_SUCCEEDED
1942                 self.description_thread_running = False
1943                 
1944         def update_statusbar(self):
1945                 '''Function which updates statusbar'''
1946                 installed = 0
1947                 selected = 0
1948                 broken = 0
1949                 for pkg_row in self.application_list:
1950                         if pkg_row[enumerations.STATUS_COLUMN] == enumerations.INSTALLED \
1951                             or pkg_row[enumerations.STATUS_COLUMN] == \
1952                             enumerations.UPDATABLE:
1953                                 installed = installed + 1
1954                         if pkg_row[enumerations.MARK_COLUMN]:
1955                                 selected = selected + 1
1956                 listed_str = self._('%d packages listed') % len(self.application_list)
1957                 inst_str = self._('%d installed') % installed
1958                 sel_str = self._('%d selected') % selected
1959                 broken_str = self._('%d broken') % broken
1960                 self.w_main_statusbar.push(0, listed_str + ', ' + inst_str + ', ' + \
1961                     sel_str + ', ' + broken_str + '.')
1962 
1963 
1964         def update_package_list(self, update_list):
1965                 img = self.api_o.img
1966                 img.clear_pkg_state()
1967                 img.load_catalogs(self.pr)
1968                 installed_icon = self.get_icon_pixbuf("status_installed")
1969                 for row in self.application_list:
1970                         if row[enumerations.NAME_COLUMN] in update_list:
1971                                 pkg = row[enumerations.FMRI_COLUMN]
1972                                 pkg_stem = row[enumerations.STEM_COLUMN]

1973                                 package_installed = \
1974                                     self.get_installed_version(self.api_o, pkg)

1975                                 if package_installed:
1976                                         inst_stem = package_installed.get_pkg_stem()
1977                                         if inst_stem == pkg_stem:
1978                                                 row[enumerations.STATUS_COLUMN] = \
1979                                                     enumerations.INSTALLED




1980                                                 row[enumerations.STATUS_ICON_COLUMN] = \
1981                                                     installed_icon








1982                                 else:
1983                                         row[enumerations.STATUS_COLUMN] = \
1984                                             enumerations.NOT_INSTALLED
1985                                         row[enumerations.STATUS_ICON_COLUMN] = \
1986                                             None
1987                                 row[enumerations.MARK_COLUMN] = False
1988                 self.w_installupdate_button.set_sensitive(False)
1989                 self.w_installupdate_menuitem.set_sensitive(False)
1990                 self.w_remove_button.set_sensitive(False)
1991                 self.w_remove_menuitem.set_sensitive(False)
1992                 self.__enable_disable_selection_menus()
1993                 self.update_statusbar()
1994 
1995         def shutdown_after_ips_update(self):    
1996 
1997                 # 2790: As IPS and IPS-GUI have been updated the IPS GUI must be shutdown 
1998                 # and restarted
1999                 msgbox = gtk.MessageDialog(parent = self.w_main_window, \
2000                     buttons = gtk.BUTTONS_OK, \
2001                     flags = gtk.DIALOG_MODAL, type = gtk.MESSAGE_INFO, \
2002                     message_format = self._("SUNWipkg and SUNWipkg-gui have been " \
2003                     "updated and Package Manager will now be restarted.\n\nAfter " \
2004                     "restart select Update All to continue."))
2005                 msgbox.set_title(self._("Update All"))
2006                 msgbox.run()
2007                 msgbox.destroy()