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