src/packagemanager.py
author Padraig O'Briain <padraig.obriain@sun.com>
Thu, 25 Feb 2010 13:45:12 +0000
changeset 1791 b2a37ff09e8c
parent 1790 5733e097d823
child 1799 b31d77bedd8c
permissions -rw-r--r--
13994 References to package names may need to change

#!/usr/bin/python2.6
#
# CDDL HEADER START
#
# The contents of this file are subject to the terms of the
# Common Development and Distribution License (the "License").
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
# or http://www.opensolaris.org/os/licensing.
# See the License for the specific language governing permissions
# and limitations under the License.
#
# When distributing Covered Code, include this CDDL HEADER in each
# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
# If applicable, add the following below this CDDL HEADER, with the
# fields enclosed by brackets "[]" replaced with your own identifying
# information: Portions Copyright [yyyy] [name of copyright owner]
#
# CDDL HEADER END
#
# Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
# Use is subject to license terms.
#

MAX_INFO_CACHE_LIMIT = 100                # Max number of package descriptions to cache
NOTEBOOK_PACKAGE_LIST_PAGE = 0            # Main Package List page index
NOTEBOOK_START_PAGE = 1                   # Main View Start page index
INFO_NOTEBOOK_LICENSE_PAGE = 3            # License Tab index
OPEN_LINK = 'usr/lib/pm-openlink'
PUBLISHER_INSTALLED = 0                   # Index for "All Publishers (Installed)" string
PUBLISHER_ALL = 1                         # Index for "All Publishers (Search)" string
PUBLISHER_ADD = 2                         # Index for "Add..." string
SHOW_INFO_DELAY = 600       # Delay before showing selected package information
SHOW_LICENSE_DELAY = 600    # Delay before showing license information
RESIZE_DELAY = 600          # Delay before handling resize for startpage
SEARCH_STR_FORMAT = "<%s>"
MIN_APP_WIDTH = 750                       # Minimum application width
MIN_APP_HEIGHT = 500                      # Minimum application height
SECTION_ID_OFFSET = 10000                 # Offset to allow Sections to be identified 
                                          # in category tree
RECENT_SEARCH_ID_OFFSET = 10999           # Offset to allow Recent Search Sections
                                          # to be identified in category tree
RECENT_SEARCH_ID = RECENT_SEARCH_ID_OFFSET + 1 #  Recent Search Section ID
CATEGORY_TOGGLE_ICON_WIDTH = 16           # Width of category toggle icon
PACKAGEMANAGER_PREFERENCES = "/apps/packagemanager/preferences"
MAX_SEARCH_COMPLETION_PREFERENCES = \
        "/apps/packagemanager/preferences/max_search_completion"
INITIAL_APP_WIDTH_PREFERENCES = "/apps/packagemanager/preferences/initial_app_width"
INITIAL_APP_HEIGHT_PREFERENCES = "/apps/packagemanager/preferences/initial_app_height"
INITIAL_APP_HPOS_PREFERENCES = "/apps/packagemanager/preferences/initial_app_hposition"
INITIAL_APP_VPOS_PREFERENCES = "/apps/packagemanager/preferences/initial_app_vposition"
INITIAL_SHOW_FILTER_PREFERENCES = "/apps/packagemanager/preferences/initial_show_filter"
INITIAL_SECTION_PREFERENCES = "/apps/packagemanager/preferences/initial_section"
LAST_EXPORT_SELECTION_PATH = \
        "/apps/packagemanager/preferences/last_export_selections_path"
SHOW_STARTPAGE_PREFERENCES = "/apps/packagemanager/preferences/show_startpage"
SHOW_IMAGE_UPDATE_CONFIRMATION = "/apps/packagemanager/preferences/imageupdate_confirm"
SHOW_INSTALL_CONFIRMATION = "/apps/packagemanager/preferences/install_confirm"
SHOW_REMOVE_CONFIRMATION = "/apps/packagemanager/preferences/remove_confirm"
SAVE_STATE_PREFERENCES = "/apps/packagemanager/preferences/save_state"
START_INSEARCH_PREFERENCES = "/apps/packagemanager/preferences/start_insearch"
LASTSOURCE_PREFERENCES = "/apps/packagemanager/preferences/lastsource"
API_SEARCH_ERROR_PREFERENCES = "/apps/packagemanager/preferences/api_search_error"
STATUS_COLUMN_INDEX = 2   # Index of Status Column in Application TreeView
SEARCH_TXT_GREY_STYLE = "#757575" #Close to DimGrey
SEARCH_TXT_BLACK_STYLE = "#000000"
GDK_2BUTTON_PRESS = 5     # gtk.gdk._2BUTTON_PRESS causes pylint warning
GDK_RIGHT_BUTTON = 3      # normally button 3 = right click

# Location for themable icons
ICON_LOCATION = "usr/share/package-manager/icons"
# Load Start Page from lang dir if available
START_PAGE_CACHE_LANG_BASE = "var/pkg/gui_cache/startpagebase/%s/%s"
START_PAGE_LANG_BASE = "usr/share/package-manager/data/startpagebase/%s/%s"
START_PAGE_HOME = "startpage.html" # Default page
START_PAGE_IMAGES_BASE = "/usr/share/package-manager/data/startpagebase/C"

# StartPage Action support for url's on StartPage pages
PM_ACTION = 'pm-action'          # Action field for StartPage url's

# Internal Example: <a href="pm?pm-action=internal&uri=top_picks.html">
ACTION_INTERNAL = 'internal'   # Internal Action value: pm-action=internal
INTERNAL_URI = 'uri'           # Internal field: uri to navigate to in StartPage
                               # without protocol scheme specified
INTERNAL_SEARCH = 'search'     # Internal field: search support page action
INTERNAL_SEARCH_VIEW_RESULTS = "view_recent_search"
                               # Internal field: view recent search results
INTERNAL_SEARCH_VIEW_PUB ="view_pub_packages" # Internal field: view publishers packages
INTERNAL_SEARCH_VIEW_ALL = "view_all_packages_filter" # Internal field: change to View 
                                                      # All Packages
INTERNAL_SEARCH_ALL_PUBS = "search_all_publishers" #Internal field: search all publishers
INTERNAL_SEARCH_ALL_PUBS_INSTALLED = "search_all_publishers_installed"
                               #Internal field: search all publishers installed
INTERNAL_SEARCH_HELP = "search_help" # Internal field: display search help

# External Example: <a href="pm?pm-action=external&uri=www.opensolaris.com">
ACTION_EXTERNAL = 'external'   # External Action value: pm-action=external
EXTERNAL_URI = 'uri'           # External field: uri to navigate to in external
                               # default browser without protocol scheme specified
EXTERNAL_PROTOCOL = 'protocol' # External field: optional protocol scheme,
                               # defaults to http
DEFAULT_PROTOCOL = 'http'
INFORMATION_PAGE_HEADER = (
            "<table border='0' cellpadding='3' style='table-layout:fixed' >"
            "<TR><TD><IMG SRC = '%s/dialog-information.png' style='border-style: none' "
            ) % START_PAGE_IMAGES_BASE                  

import getopt
import pwd
import os
import subprocess
import sys
import time
import locale
import itertools
import urllib
import urlparse
import socket
import gettext
import signal
import threading
import re
import stat
import tempfile
from xml.sax import saxutils
from threading import Thread
from threading import Lock
from collections import deque
from gettext import ngettext
import traceback
from cStringIO import StringIO

try:
        import gobject
        import gnome
        gobject.threads_init()
        import gconf
        import gtk
        import gtk.glade
        import pygtk
        pygtk.require("2.0")
        import gtkhtml2
        import pango
        from glib import GError
except ImportError:
        sys.exit(1)
import pkg.misc as misc
import pkg.client.progress as progress
import pkg.client.api_errors as api_errors
import pkg.client.api as api
import pkg.client.publisher as publisher
import pkg.portable as portable
import pkg.fmri as fmri
import pkg.gui.repository as repository
import pkg.gui.beadmin as beadm
import pkg.gui.cache as cache
import pkg.gui.misc as gui_misc
import pkg.gui.imageinfo as imageinfo
import pkg.gui.installupdate as installupdate
import pkg.gui.enumerations as enumerations
import pkg.gui.parseqs as parseqs
import pkg.gui.webinstall as webinstall
from pkg.client import global_settings

logger = global_settings.logger

# Put _() in the global namespace
import __builtin__
__builtin__._ = gettext.gettext

(
DISPLAY_LINK,
CLICK_LINK,
) = range(2)

REGEX_BOLD_MARKUP = re.compile(r'^<b>')
REGEX_STRIP_MARKUP = re.compile(r'<.*?>')
REGEX_STRIP_RESULT = re.compile(r'\(\d+\) ?')

class PackageManager:
        def __init__(self):
                self.before_start = True
                signal.signal(signal.SIGINT, self.__main_application_quit)
                self.user_rights = portable.is_admin()
                self.original_user = None
                self.__reset_home_dir()
                self.api_o = None
                self.cache_o = None
                self.img_timestamp = None
                self.client = gconf.client_get_default()
                try:
                        self.max_search_completion = \
                            self.client.get_int(MAX_SEARCH_COMPLETION_PREFERENCES)
                        self.initial_show_filter = \
                            self.client.get_int(INITIAL_SHOW_FILTER_PREFERENCES)
                        self.initial_section = \
                            self.client.get_int(INITIAL_SECTION_PREFERENCES)
                        self.last_export_selection_path = \
                            self.client.get_string(LAST_EXPORT_SELECTION_PATH)
                        self.show_startpage = \
                            self.client.get_bool(SHOW_STARTPAGE_PREFERENCES)
                        self.save_state = \
                            self.client.get_bool(SAVE_STATE_PREFERENCES)
                        self.show_image_update = \
                            self.client.get_bool(SHOW_IMAGE_UPDATE_CONFIRMATION)
                        self.show_install = \
                            self.client.get_bool(SHOW_INSTALL_CONFIRMATION)
                        self.show_remove = \
                            self.client.get_bool(SHOW_REMOVE_CONFIRMATION)
                        self.start_insearch = \
                            self.client.get_bool(START_INSEARCH_PREFERENCES)
                        self.lastsource = \
                            self.client.get_string(LASTSOURCE_PREFERENCES)
                        self.gconf_not_show_repos = \
                            self.client.get_string(API_SEARCH_ERROR_PREFERENCES)
                        self.initial_app_width = \
                            self.client.get_int(INITIAL_APP_WIDTH_PREFERENCES)
                        self.initial_app_height = \
                            self.client.get_int(INITIAL_APP_HEIGHT_PREFERENCES)
                        self.initial_app_hpos = \
                            self.client.get_int(INITIAL_APP_HPOS_PREFERENCES)
                        self.initial_app_vpos = \
                            self.client.get_int(INITIAL_APP_VPOS_PREFERENCES)
                        self.client.add_dir(PACKAGEMANAGER_PREFERENCES,
                            gconf.CLIENT_PRELOAD_NONE)
                        self.client.notify_add(SHOW_IMAGE_UPDATE_CONFIRMATION,
                            self.__show_image_update_changed)
                        self.client.notify_add(SHOW_INSTALL_CONFIRMATION,
                            self.__show_install_changed)
                        self.client.notify_add(SHOW_REMOVE_CONFIRMATION,
                            self.__show_remove_changed)
                        self.client.notify_add(SAVE_STATE_PREFERENCES,
                            self.__save_state_changed)
                except GError:
                        # Default values - the same as in the 
                        # packagemanager-preferences.schemas
                        self.max_search_completion = 20
                        self.initial_show_filter = 0
                        self.initial_section = 2
                        self.last_export_selection_path = ""
                        self.show_startpage = True
                        self.show_image_update = True
                        self.show_install = True
                        self.show_remove = True
                        self.save_state = True
                        self.start_insearch = False
                        self.lastsource = ""
                        self.gconf_not_show_repos = ""
                        self.initial_app_width = 800
                        self.initial_app_height = 600
                        self.initial_app_hpos = 200
                        self.initial_app_vpos = 320

                self.__fix_initial_values()

                self.set_section = 0
                self.after_install_remove = False
                self.in_search_mode = False
                self.in_recent_search = False
                self.recent_searches = {}
                self.recent_searches_cat_iter = None
                self.adding_recent_search = False
                self.recent_searches_list = []
                self.previous_search_text = None
                
                global_settings.client_name = gui_misc.get_pm_name()

                # This call only affects sockets created by Python.  The
                # transport framework uses the defaults in global_settings,
                # which may be overridden in the environment.  The default
                # socket module should only be used in rare cases by ancillary
                # code, making it safe to code the value here, at least for now.
                socket.setdefaulttimeout(30) # in secs

                try:
                        self.application_dir = os.environ["PACKAGE_MANAGER_ROOT"]
                except KeyError:
                        self.application_dir = "/"
                misc.setlocale(locale.LC_ALL, "")
                for module in (gettext, gtk.glade):
                        module.bindtextdomain("pkg", os.path.join(
                            self.application_dir,
                            "usr/share/locale"))
                        module.textdomain("pkg")
                gui_misc.init_for_help(self.application_dir)
                self.main_window_title = _('Package Manager')
                self.gdk_window = None
                self.cancelled = False                    # For background processes
                self.description_queue = deque()
                self.description_thread_running = False
                self.image_directory = None
                gtk.rc_parse('~/.gtkrc-1.2-gnome2')       # Load gtk theme
                self.progress_stop_thread = True
                self.update_all_proceed = False
                self.application_path = None
                self.default_publisher = None
                self.current_repos_with_search_errors = []
                self.exiting = False
                self.first_run = True
                self.selected_pkgstem = None
                self.selected_model = None
                self.selected_path = None
                self.info_cache = {}
                self.all_selected = 0
                self.selected_pkgs = {}
                self.package_names = {}
                self.special_package_names = []
                self.link_load_page = ""
                self.start_page_url = None
                self.to_install_update = {}
                self.to_remove = {}
                self.in_startpage_startup = self.show_startpage
                self.lang = None
                self.lang_root = None
                self.visible_status_id = 0
                self.same_publisher_on_setup = False
                self.force_reload_packages = True
                self.icon_theme = gtk.icon_theme_get_default()
                icon_location = os.path.join(self.application_dir, ICON_LOCATION)
                self.icon_theme.append_search_path(icon_location)
                self.installed_icon = gui_misc.get_icon(self.icon_theme,
                    'status_installed')
                self.not_installed_icon = gui_misc.get_icon(self.icon_theme,
                    'status_notinstalled')
                self.update_available_icon = gui_misc.get_icon(self.icon_theme,
                    'status_newupdate')
                self.window_icon = gui_misc.get_icon(self.icon_theme,
                    'packagemanager', 48)
                self.filter_options = [
                    (enumerations.FILTER_ALL,
                    gui_misc.get_icon(self.icon_theme, 'filter_all'),
                    _('All Packages')),
                    (enumerations.FILTER_INSTALLED, self.installed_icon,
                    _('Installed Packages')),
                    (enumerations.FILTER_UPDATES, self.update_available_icon,
                    _('Updates')),
                    (enumerations.FILTER_NOT_INSTALLED, self.not_installed_icon,
                    _('Not Installed Packages')),
                    (-1, None, ""),
                    (enumerations.FILTER_SELECTED,
                    gui_misc.get_icon(self.icon_theme, 'filter_selected'),
                    _('Selected Packages'))
                    ]
                self.publisher_options = { 
                    PUBLISHER_INSTALLED : _("All Publishers (Installed)"),
                    PUBLISHER_ALL : _("All Publishers (Search)"),
                    PUBLISHER_ADD : _("Add...")
                    }
                self.pubs_info = {}
                self.pubs_display_name = {}
                self.last_visible_publisher = None
                self.publisher_changed = True
                self.search_start = 0
                self.search_time_sec = 0
                self.search_all_pub_being_searched = None
                self.section_list = None
                self.filter_list = self.__get_new_filter_liststore()
                self.length_visible_list = 0
                self.application_list = None
                self.a11y_application_treeview = None
                self.application_treeview_range = None
                self.application_treeview_initialized = False
                self.categories_treeview_range = None
                self.categories_treeview_initialized = False
                self.category_list = None
                self.repositories_list = None
                self.repo_combobox_all_pubs_installed_index = 0
                self.repo_combobox_all_pubs_index = 0
                self.repo_combobox_add_index = 0
                self.pr = progress.NullProgressTracker()
                self.pylintstub = None
                self.__image_activity_lock = Lock()
                self.category_expanded_paths = {}
                self.category_active_paths = {}
                self.error_logged = False
                
                self.use_cache = False # Turns off Details Description cache
                                       # Search history cache is always on
                                       # Caching package list is removed

                # Create Widgets and show gui
                self.gladefile = os.path.join(self.application_dir,
                    "usr/share/package-manager/packagemanager.glade")
                w_tree_main = gtk.glade.XML(self.gladefile, "mainwindow")
                w_tree_preferences = gtk.glade.XML(self.gladefile, "preferencesdialog")
                w_tree_api_search_error = gtk.glade.XML(self.gladefile,
                    "api_search_error")
                self.w_preferencesdialog = \
                    w_tree_preferences.get_widget("preferencesdialog")
                self.w_preferencesdialog.set_icon(self.window_icon)
                self.w_startpage_checkbutton = \
                    w_tree_preferences.get_widget("startpage_checkbutton")
                self.w_exit_checkbutton = \
                    w_tree_preferences.get_widget("exit_checkbutton")
                self.w_confirm_updateall_checkbutton = \
                    w_tree_preferences.get_widget("confirm_updateall_checkbutton")
                self.w_confirm_install_checkbutton = \
                    w_tree_preferences.get_widget("confirm_install_checkbutton")
                self.w_confirm_remove_checkbutton = \
                    w_tree_preferences.get_widget("confirm_remove_checkbutton")
                self.api_search_error_dialog = \
                    w_tree_api_search_error.get_widget("api_search_error")
                self.api_search_error_textview = \
                    w_tree_api_search_error.get_widget("api_search_error_text")
                self.api_search_checkbox = \
                    w_tree_api_search_error.get_widget("api_search_checkbox")
                self.api_search_button = \
                    w_tree_api_search_error.get_widget("api_search_button")
                infobuffer = self.api_search_error_textview.get_buffer()
                infobuffer.create_tag("bold", weight=pango.WEIGHT_BOLD)
                w_tree_confirm = gtk.glade.XML(self.gladefile, "confirmationdialog")
                self.w_exportconfirm_dialog = \
                    w_tree_confirm.get_widget("confirmationdialog")
                self.w_exportconfirm_dialog.set_icon(self.window_icon)
                self.w_confirmok_button = w_tree_confirm.get_widget("ok_conf")
                self.w_confirmhelp_button = w_tree_confirm.get_widget("help_conf")
                self.w_confirm_textview = w_tree_confirm.get_widget("confirmtext")
                self.w_confirm_label = w_tree_confirm.get_widget("confirm_label")
                w_confirm_image = w_tree_confirm.get_widget("confirm_image")
                w_confirm_image.set_from_stock(gtk.STOCK_DIALOG_INFO,
                    gtk.ICON_SIZE_DND)
                self.__setup_export_selection_dialog()

                w_log = gtk.glade.XML(self.gladefile,
                    "view_log_dialog")
                self.w_view_log_dialog = \
                    w_log.get_widget("view_log_dialog")
                self.w_view_log_dialog.set_icon(self.window_icon)
                self.w_view_log_dialog.set_title(_("Logs"))
                self.w_log_info_textview = w_log.get_widget("log_info_textview")
                self.w_log_errors_textview = w_log.get_widget("log_errors_textview")
                infobuffer = self.w_log_info_textview.get_buffer()
                infobuffer.create_tag("bold", weight=pango.WEIGHT_BOLD)                
                infobuffer = self.w_log_errors_textview.get_buffer()
                infobuffer.create_tag("bold", weight=pango.WEIGHT_BOLD)                
                self.w_log_close_button = w_log.get_widget("log_close_button")
                
                w_version_info = gtk.glade.XML(self.gladefile,
                    "version_info_dialog")
                self.w_version_info_dialog = \
                    w_version_info.get_widget("version_info_dialog")
                self.w_info_name_label = w_version_info.get_widget("info_name")
                self.w_info_installed_label = w_version_info.get_widget("info_installed")
                self.w_info_installable_label = w_version_info.get_widget(
                    "info_installable")
                self.w_info_installable_prefix_label = w_version_info.get_widget(
                    "info_installable_label")
                self.w_info_ok_button = w_version_info.get_widget("info_ok_button")
                self.w_info_expander = w_version_info.get_widget("version_info_expander")
                self.w_info_textview = w_version_info.get_widget("infotextview")
                infobuffer = self.w_info_textview.get_buffer()
                infobuffer.create_tag("bold", weight=pango.WEIGHT_BOLD)                
                self.w_main_window = w_tree_main.get_widget("mainwindow")
                self.w_main_window.set_icon(self.window_icon)
                self.w_main_hpaned = \
                    w_tree_main.get_widget("main_hpaned")
                self.w_main_vpaned = \
                    w_tree_main.get_widget("main_vpaned")

                self.w_application_treeview = \
                    w_tree_main.get_widget("applicationtreeview")
                self.w_application_treeview.connect('key_press_event',
                    self.__on_applicationtreeview_button_and_key_events)
                self.w_application_treeview.set_enable_search(True)
                self.w_application_treeview.set_search_equal_func(
                      self.__applicationtreeview_compare_func)

                self.w_categories_treeview = w_tree_main.get_widget("categoriestreeview")
                self.w_categories_treeview.set_search_equal_func(
                    self.__categoriestreeview_compare_func)

                self.w_info_notebook = w_tree_main.get_widget("details_notebook")
                self.w_generalinfo_textview = \
                    w_tree_main.get_widget("generalinfotextview")
                self.w_generalinfo_textview.get_buffer().create_tag(
                    "bold", weight=pango.WEIGHT_BOLD)
                self.w_installedfiles_textview = \
                    w_tree_main.get_widget("installedfilestextview")
                self.w_installedfiles_textview.get_buffer().create_tag(
                    "bold", weight=pango.WEIGHT_BOLD)
                self.w_license_textview = \
                    w_tree_main.get_widget("licensetextview")
                self.w_dependencies_textview = \
                    w_tree_main.get_widget("dependenciestextview")
                self.w_dependencies_textview.get_buffer().create_tag(
                    "bold", weight=pango.WEIGHT_BOLD)
                self.w_general_info_label = \
                    w_tree_main.get_widget("general_info_label")
                self.w_startpage_scrolled_window = \
                    w_tree_main.get_widget("startpage_scrolled_window")
                self.w_startpage_eventbox = \
                    w_tree_main.get_widget("startpage_eventbox")
                self.w_startpage_eventbox.modify_bg(gtk.STATE_NORMAL,
                    gtk.gdk.color_parse("white"))

                self.w_main_statusbar = w_tree_main.get_widget("statusbar")
                #Allow markup in StatusBar
                self.w_main_statusbar_label = \
                        self.__get_statusbar_label(self.w_main_statusbar)
                if self.w_main_statusbar_label != None:
                        self.w_main_statusbar_label.set_use_markup(True) 
    
                self.w_statusbar_hbox = w_tree_main.get_widget("statusbar_hbox")
                self.w_infosearch_frame = w_tree_main.get_widget("infosearch_frame")

                self.w_progress_frame = w_tree_main.get_widget("progress_frame")
                self.w_status_progressbar = w_tree_main.get_widget("status_progressbar")
                self.w_status_progressbar.set_pulse_step(0.1)
                self.w_progress_frame.hide()

                self.w_main_view_notebook = \
                    w_tree_main.get_widget("main_view_notebook")
                self.w_searchentry = w_tree_main.get_widget("searchentry")
                self.entry_embedded_icons_supported = True
                try:
                        self.w_searchentry.set_property("secondary-icon-stock", None)
                except TypeError:
                        self.entry_embedded_icons_supported = False
                self.search_text_style = -1
                self.__set_search_text_mode(enumerations.SEARCH_STYLE_PROMPT)
                self.search_completion = gtk.ListStore(str)
                self.w_package_menu = w_tree_main.get_widget("package_menu")
                self.w_reload_button = w_tree_main.get_widget("reload_button")
                self.w_installupdate_button = \
                    w_tree_main.get_widget("install_update_button")
                self.w_remove_button = w_tree_main.get_widget("remove_button")
                self.w_updateall_button = w_tree_main.get_widget("update_all_button")
                self.w_repository_combobox = w_tree_main.get_widget("repositorycombobox")
                self.w_filter_combobox = w_tree_main.get_widget("filtercombobox")
                self.w_packageicon_image = w_tree_main.get_widget("packageimage")
                self.w_reload_menuitem = w_tree_main.get_widget("file_reload")
                self.__set_icon(self.w_reload_button, self.w_reload_menuitem,
                    'pm-refresh')
                self.w_version_info_menuitem = \
                    w_tree_main.get_widget("package_version_info")
                self.w_version_info_menuitem.set_sensitive(False)
                self.w_installupdate_menuitem = \
                    w_tree_main.get_widget("package_install_update")
                self.__set_icon(self.w_installupdate_button, 
                    self.w_installupdate_menuitem, 'pm-install_update')
                self.w_remove_menuitem = w_tree_main.get_widget("package_remove")
                self.__set_icon(self.w_remove_button, self.w_remove_menuitem, 
                    'pm-remove')
                self.w_updateall_menuitem = w_tree_main.get_widget("package_update_all")
                self.__set_icon(self.w_updateall_button,
                    self.w_updateall_menuitem, 'pm-update_all')
                self.w_export_selections_menuitem = w_tree_main.get_widget(
                    "file_export_selections")
                self.w_cut_menuitem = w_tree_main.get_widget("edit_cut")
                self.w_copy_menuitem = w_tree_main.get_widget("edit_copy")
                self.w_paste_menuitem = w_tree_main.get_widget("edit_paste")
                self.w_delete_menuitem = w_tree_main.get_widget("edit_delete")
                self.w_selectall_menuitem = w_tree_main.get_widget("edit_select_all")
                self.w_selectupdates_menuitem = \
                    w_tree_main.get_widget("edit_select_updates")
                self.w_deselect_menuitem = w_tree_main.get_widget("edit_deselect")
                self.w_clear_search_menuitem = w_tree_main.get_widget("clear")
                self.w_main_clipboard =  gtk.clipboard_get(gtk.gdk.SELECTION_CLIPBOARD)
                self.saved_filter_combobox_active = self.initial_show_filter
                self.search_button = w_tree_main.get_widget("do_search")
                self.progress_cancel = w_tree_main.get_widget("progress_cancel")
                self.is_all_publishers = False
                self.is_all_publishers_installed = False
                self.saved_repository_combobox_active = -1
                self.saved_section_active = 0
                self.saved_application_list = None
                self.saved_application_list_filter = None
                self.saved_application_list_sort = None
                self.saved_category_list = None
                self.saved_section_list = None
                self.saved_selected_application_path = None
                self.section_categories_list = {}
                self.statusbar_message_id = 0
                toolbar =  w_tree_main.get_widget("toolbutton2")
                toolbar.set_expand(True)
                self.__init_repository_tree_view()
                self.w_main_window.set_title(self.main_window_title)

                # Setup Start Page
                self.document = None
                self.view = None
                self.current_url = None
                self.opener = None
                self.__setup_startpage(self.show_startpage)

                try:
                        dic_mainwindow = \
                            {
                                "on_mainwindow_delete_event": \
                                    self.__on_mainwindow_delete_event,
                                "on_mainwindow_check_resize": \
                                    self.__on_mainwindow_check_resize,
                                "on_mainwindow_key_press_event": \
                                    self.__on_mainwindow_key_press_event,
                                "on_mainwindow_style_set": \
                                    self.__on_mainwindow_style_set,
                                "on_searchentry_changed":self.__on_searchentry_changed,
                                "on_searchentry_focus_in_event": \
                                    self.__on_searchentry_focus_in,
                                "on_searchentry_focus_out_event": \
                                    self.__on_searchentry_focus_out,
                                "on_searchentry_activate": \
                                    self.__do_search,
                                "on_filtercombobox_changed": \
                                    self.__on_filtercombobox_changed,
                                "on_repositorycombobox_changed": \
                                    self.__on_repositorycombobox_changed,
                                #menu signals
                                "on_file_export_selections": \
                                        self.__on_file_export_selections,
                                "on_file_quit_activate":self.__on_file_quit_activate,
                                "on_file_be_activate":self.__on_file_be_activate,
                                "on_package_version_info_activate": \
                                    self.__on_version_info,
                                "on_package_install_update_activate": \
                                    self.__on_install_update,
                                "on_file_manage_publishers_activate": \
                                    self.__on_file_manage_publishers,
                                "on_file_add_publisher_activate": \
                                    self.__on_file_add_publisher,
                                "on_package_remove_activate":self.__on_remove,
                                "on_help_about_activate":self.__on_help_about,
                                "on_help_help_activate":self.__on_help_help,
                                "on_edit_paste_activate":self.__on_edit_paste,
                                "on_edit_delete_activate":self.__on_delete,
                                "on_edit_copy_activate":self.__on_copy,
                                "on_edit_cut_activate":self.__on_cut,
                                "on_edit_search_activate":self.__on_edit_search_clicked,
                                "on_goto_list_activate":self.__on_goto_list_clicked,
                                "on_clear_search_activate":self.__on_clear_search,
                                "on_clear_search_clicked":self.__on_clear_search,
                                "on_do_search_clicked":self.__do_search,
                                "on_do_search_button_press_event":self.__do_search,
                                "on_progress_cancel_clicked": \
                                    self.__on_progress_cancel_clicked,
                                "on_edit_select_all_activate":self.__on_select_all,
                                "on_edit_select_updates_activate": \
                                    self.__on_select_updates,
                                "on_edit_deselect_activate":self.__on_deselect,
                                "on_edit_preferences_activate":self.__on_preferences,
                                "on_log_activate":self.__on_log_activate,
                                # XXX disabled until new API
                                "on_package_update_all_activate":self.__on_update_all,
                                #toolbar signals
                                # XXX disabled until new API
                                "on_update_all_button_clicked":self.__on_update_all,
                                "on_reload_button_clicked":self.__on_reload,
                                "on_install_update_button_clicked": \
                                    self.__on_install_update,
                                "on_remove_button_clicked":self.__on_remove,
                                "on_help_start_page_activate":self.__on_startpage,
                                "on_details_notebook_switch_page": \
                                    self.__on_notebook_change,
                                "on_infosearch_eventbox_button_press_event": \
                                    self.__on_infosearch_button_press_event,
                                "on_applicationtreeview_button_press_event": \
                                    self.__on_applicationtreeview_button_and_key_events,
                                "on_applicationtreeview_query_tooltip": \
                                    self.__on_applicationtreeview_query_tooltip,
                            }
                        dic_preferences = \
                            {
                                "on_preferencesdialog_delete_event": \
                                    self.__on_preferencesdialog_delete_event,
                                "on_startpage_checkbutton_toggled": \
                                    self.__on_startpage_checkbutton_toggled,
                                "on_exit_checkbutton_toggled": \
                                    self.__on_exit_checkbutton_toggled,
                                "on_confirm_updateall_checkbutton_toggled": \
                                    self.on_confirm_updateall_checkbutton_toggled,
                                "on_confirm_install_checkbutton_toggled": \
                                    self.on_confirm_install_checkbutton_toggled,
                                "on_confirm_remove_checkbutton_toggled": \
                                    self.on_confirm_remove_checkbutton_toggled,
                                "on_preferenceshelp_clicked": \
                                    self.__on_preferenceshelp_clicked,
                                "on_preferencesclose_clicked": \
                                    self.__on_preferencesclose_clicked,
                            }
                        dic_api_search_error = \
                            {
                                "on_api_search_checkbox_toggled": \
                                    self.__on_api_search_checkbox_toggled,
                                "on_api_search_button_clicked": \
                                    self.__on_api_search_button_clicked,
                                "on_api_search_error_delete_event": \
                                    self.__on_api_search_error_delete_event,
                            }

                        dic_confirm = \
                            {
                                "on_confirmationdialog_delete_event": \
                                    self.__on_confirmation_dialog_delete_event,
                                "on_help_conf_clicked": \
                                    self.__on_confirm_help_button_clicked,
                                "on_ok_conf_clicked": \
                                    self.__on_confirm_proceed_button_clicked,
                                "on_cancel_conf_clicked": \
                                    self.__on_confirm_cancel_button_clicked,
                            }        
                            
                        dic_version_info = \
                            {
                                "on_info_ok_clicked": \
                                    self.__on_info_ok_button_clicked,
                                "on_info_help_clicked": \
                                    self.__on_info_help_button_clicked,
                                "on_version_info_dialog_delete_event": \
                                    self.__on_version_info_dialog_delete_event,
                            }
                            
                        dic_log = \
                            {
                                "on_log_close_button_clicked": \
                                    self.__on_log_close_button_clicked,
                                "on_view_log_dialog_delete_event": \
                                    self.__on_log_dialog_delete_event
                            }
                            
                        w_tree_confirm.signal_autoconnect(dic_confirm)
                        w_tree_main.signal_autoconnect(dic_mainwindow)
                        w_tree_preferences.signal_autoconnect(dic_preferences)
                        w_tree_api_search_error.signal_autoconnect(
                            dic_api_search_error)
                        w_version_info.signal_autoconnect(dic_version_info)
                        w_log.signal_autoconnect(dic_log)
                except AttributeError, error:
                        print _(
                            "GUI will not respond to any event! %s. "
                            "Check declare_signals()") \
                            % error

                self.package_selection = None
                self.application_list_filter = None
                self.application_list_sort = None
                self.application_refilter_id = 0
                self.application_refilter_idle_id = 0
                self.last_status_id = 0
                self.last_show_info_id = 0
                self.show_info_id = 0
                self.last_show_licenses_id = 0
                self.show_licenses_id = 0
                self.resize_id = 0
                self.last_resize = (0, 0)
                self.showing_empty_details = False
                self.in_setup = True
                self.__set_initial_sizes()
                self.w_main_window.show_all()
                self.__setup_busy_cursor()
                if self.show_startpage:
                        self.w_main_view_notebook.set_current_page(NOTEBOOK_START_PAGE)
                else:
                        self.w_main_view_notebook.set_current_page(
                            NOTEBOOK_PACKAGE_LIST_PAGE)
                gui_misc.set_modal_and_transient(self.api_search_error_dialog,
                    self.w_main_window)
                gui_misc.set_modal_and_transient(self.w_version_info_dialog,
                    self.w_main_window)
                gui_misc.set_modal_and_transient(self.w_view_log_dialog,
                    self.w_main_window)
                gui_misc.set_modal_and_transient(self.w_preferencesdialog,
                    self.w_main_window)

                self.__setup_text_signals()
                gui_misc.setup_logging(gui_misc.get_pm_name())
                
        def __set_initial_sizes(self):
                if self.initial_app_width >= MIN_APP_WIDTH and \
                        self.initial_app_height >= MIN_APP_HEIGHT:
                        self.w_main_window.resize(self.initial_app_width,
                            self.initial_app_height)
                if self.initial_app_hpos > 0:
                        self.w_main_hpaned.set_position(self.initial_app_hpos)
                if self.initial_app_vpos > 0:
                        self.w_main_vpaned.set_position(self.initial_app_vpos)

        def __setup_busy_cursor(self):
                gdk_win = self.w_main_window.get_window()
                self.gdk_window = gtk.gdk.Window(gdk_win, gtk.gdk.screen_width(),
                    gtk.gdk.screen_height(), gtk.gdk.WINDOW_CHILD, 0, gtk.gdk.INPUT_ONLY)
                gdk_cursor = gtk.gdk.Cursor(gtk.gdk.WATCH)

                self.gdk_window.set_cursor(gdk_cursor)

        def __fix_initial_values(self):
                if self.initial_app_width == -1:
                        self.initial_app_width = 800
                if self.initial_app_height == -1:
                        self.initial_app_height = 600
                if self.initial_app_hpos == -1:
                        self.initial_app_hpos = 200
                if self.initial_app_vpos == -1:
                        self.initial_app_vpos = 320

                if not self.gconf_not_show_repos:
                        self.gconf_not_show_repos = ""
        @staticmethod
        def __set_icon(button, menuitem, icon_name):
                icon_source = gtk.IconSource()
                icon_source.set_icon_name(icon_name)
                icon_set = gtk.IconSet()
                icon_set.add_source(icon_source)
                image_widget = gtk.image_new_from_icon_set(icon_set,
                    gtk.ICON_SIZE_SMALL_TOOLBAR)
                button.set_icon_widget(image_widget)
                image_widget = gtk.image_new_from_icon_set(icon_set,
                    gtk.ICON_SIZE_MENU)
                menuitem.set_image(image_widget)

        @staticmethod
        def __get_statusbar_label(statusbar):
                sb_frame = None
                sb_label = None
                children = statusbar.get_children()
                if len(children) > 0:
                        sb_frame = children[0]
                if sb_frame and isinstance(sb_frame, gtk.Frame):
                        children = sb_frame.get_children()
                        if len(children) > 0:
                                sb_label = children[0]
                        if sb_label and isinstance(sb_label, gtk.Label):
                                return sb_label
                return None
                
        def __setup_export_selection_dialog(self):
                infobuffer = self.w_confirm_textview.get_buffer()
                infobuffer.create_tag("bold", weight=pango.WEIGHT_BOLD)
                self.w_exportconfirm_dialog.set_title(_("Export Selections Confirmation"))
                self.w_confirm_label.set_markup(
                    _("<b>Export the following to a Web Install .p5i file:</b>"))
                self.w_confirmhelp_button.set_property('visible', True)

        def __on_confirmation_dialog_delete_event(self, widget, event):
                self.__on_confirm_cancel_button_clicked(None)
                return True

        @staticmethod
        def __on_confirm_help_button_clicked(widget):
                gui_misc.display_help("webinstall-export")

        def __on_confirm_cancel_button_clicked(self, widget):
                self.w_exportconfirm_dialog.hide()

        def __on_confirm_proceed_button_clicked(self, widget):
                self.w_exportconfirm_dialog.hide()
                self.__export_selections()

        def __on_file_export_selections(self, menuitem):
                if self.selected_pkgs == None or len(self.selected_pkgs) == 0:
                        return
                        
                infobuffer = self.w_confirm_textview.get_buffer()
                infobuffer.set_text("")
                textiter = infobuffer.get_end_iter()
                
                for pub_name, pkgs in self.selected_pkgs.items():
                        name = self.__get_publisher_name_from_prefix(pub_name)
                        if name == pub_name:
                                infobuffer.insert_with_tags_by_name(textiter,
                                    "%s\n" % pub_name, "bold")
                        else:
                                infobuffer.insert_with_tags_by_name(textiter,
                                    "%s" % name, "bold")
                                infobuffer.insert(textiter, " (%s)\n" % pub_name)
                        for pkg in pkgs.keys():
                                infobuffer.insert(textiter,
                                    "\t%s\n" % fmri.extract_pkg_name(pkg))
                self.w_confirmok_button.grab_focus()                
                self.w_exportconfirm_dialog.show()

        def __export_selections(self):
                filename = self.__get_export_p5i_filename()
                if not filename:
                        return
                try:
                        fobj = open(filename, 'w')
                        self.api_o.write_p5i(fobj, pkg_names=self.selected_pkgs,
                            pubs=self.selected_pkgs.keys())
                except IOError, ex:
                        err = str(ex)
                        self.error_occurred(err, _("Export Selections Error"))
                        return
                except api_errors.ApiException, ex:
                        fobj.close()
                        err = str(ex)
                        self.error_occurred(err, _("Export Selections Error"))
                        return
                fobj.close()
                os.chmod(filename, stat.S_IRUSR | stat.S_IWUSR | stat.S_IRGRP |
                    stat.S_IWGRP | stat.S_IROTH | stat.S_IWOTH )

        def __get_export_p5i_filename(self):
                filename = None
                chooser = gtk.FileChooserDialog(_("Export Selections"), 
                    self.w_main_window,
                    gtk.FILE_CHOOSER_ACTION_SAVE,
                    (gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL,
                    gtk.STOCK_SAVE, gtk.RESPONSE_OK))
        
                file_filter = gtk.FileFilter()
                file_filter.set_name(_("p5i Files"))
                file_filter.add_pattern("*.p5i")
                chooser.add_filter(file_filter)
                file_filter = gtk.FileFilter()
                file_filter.set_name(_("All Files"))
                file_filter.add_pattern("*")
                chooser.add_filter(file_filter)
                
                path = tempfile.gettempdir()
                name = _("my_packages")
                if self.last_export_selection_path and \
                        self.last_export_selection_path != "":
                        path, name_plus_ext = os.path.split(
                            self.last_export_selection_path)
                        name, ext = os.path.splitext(name_plus_ext)
                        self.pylintstub = ext

                #Check name
                base_name = None
                m = re.match("(.*)(-\d+)$", name)
                if m == None and os.path.exists(path + os.sep + name + '.p5i'):
                        base_name = name
                if m and len(m.groups()) == 2:
                        base_name = m.group(1)
                name = name + '.p5i'
                if base_name:
                        for i in range(1, 99):
                                full_path = path + os.sep + base_name + '-' + \
                                        str(i) + '.p5i'
                                if not os.path.exists(full_path):
                                        name = base_name + '-' + str(i) + '.p5i'
                                        break
                chooser.set_current_folder(path)
                chooser.set_current_name(name)
                chooser.set_do_overwrite_confirmation(True)

                response = chooser.run()
                if response == gtk.RESPONSE_OK:
                        filename = chooser.get_filename()
                        self.last_export_selection_path = filename
                chooser.destroy()

                return filename

        @staticmethod
        def __on_mainwindow_style_set(widget, previous_style):
                ''' This is called when theme is changed.
                We need to change the status icons in the Package List,
                the search icon and the icons in the filter list'''
                return
                
        def __set_search_text_mode(self, style):
                if style == enumerations.SEARCH_STYLE_NORMAL:
                        self.w_searchentry.modify_text(gtk.STATE_NORMAL,
                                gtk.gdk.color_parse(SEARCH_TXT_BLACK_STYLE))
                        if self.search_text_style == enumerations.SEARCH_STYLE_PROMPT or\
                                self.w_searchentry.get_text() == _("Search (Ctrl-F)"):
                                self.w_searchentry.set_text("")
                        self.search_text_style = enumerations.SEARCH_STYLE_NORMAL
                        
                else:
                        self.w_searchentry.modify_text(gtk.STATE_NORMAL,
                                gtk.gdk.color_parse(SEARCH_TXT_GREY_STYLE))
                        self.search_text_style = enumerations.SEARCH_STYLE_PROMPT
                        self.w_searchentry.set_text(_("Search (Ctrl-F)"))
        
        def __search_completion_cb(self, entry):
                text = entry.get_text()
                if text:
                        if text not in [row[0] for row in self.search_completion]:
                                len_search_completion = len(self.search_completion)
                                if len_search_completion > 0 and \
                                        len_search_completion >= \
                                                self.max_search_completion:
                                        itr = self.search_completion.get_iter_first()
                                        if itr:
                                                self.search_completion.remove(itr)
                                self.search_completion.append([text])
                return
                
        def __setup_text_signals(self):
                self.w_generalinfo_textview.get_buffer().connect(
                    "notify::has-selection", self.__on_text_buffer_has_selection)
                self.w_installedfiles_textview.get_buffer().connect(
                    "notify::has-selection", self.__on_text_buffer_has_selection)
                self.w_dependencies_textview.get_buffer().connect(
                    "notify::has-selection", self.__on_text_buffer_has_selection)
                self.w_license_textview.get_buffer().connect(
                    "notify::has-selection", self.__on_text_buffer_has_selection)
                self.w_searchentry.connect(
                    "notify::cursor-position", self.__on_searchentry_selection)
                self.w_searchentry.connect(
                    "notify::selection-bound", self.__on_searchentry_selection)
                self.w_generalinfo_textview.connect(
                    "focus-in-event", self.__on_textview_focus_in)
                self.w_installedfiles_textview.connect(
                    "focus-in-event", self.__on_textview_focus_in)
                self.w_dependencies_textview.connect(
                    "focus-in-event", self.__on_textview_focus_in)
                self.w_license_textview.connect(
                    "focus-in-event", self.__on_textview_focus_in)
                self.w_generalinfo_textview.connect(
                    "focus-out-event", self.__on_textview_focus_out)
                self.w_installedfiles_textview.connect(
                    "focus-out-event", self.__on_textview_focus_out)
                self.w_dependencies_textview.connect(
                    "focus-out-event", self.__on_textview_focus_out)
                self.w_license_textview.connect(
                    "focus-out-event", self.__on_textview_focus_out)

        def __on_textview_focus_in(self, widget, event):
                char_count = widget.get_buffer().get_char_count()
                if char_count > 0:
                        self.w_selectall_menuitem.set_sensitive(True)
                else:
                        self.w_selectall_menuitem.set_sensitive(False)
                bounds = widget.get_buffer().get_selection_bounds()
                if bounds:
                        offset1 = bounds[0].get_offset() 
                        offset2 = bounds[1].get_offset() 
                        if abs(offset2 - offset1) == char_count:
                                self.w_selectall_menuitem.set_sensitive(False)
                        self.w_deselect_menuitem.set_sensitive(True)
                        self.w_copy_menuitem.set_sensitive(True)
                else:
                        self.w_deselect_menuitem.set_sensitive(False)

        def __on_textview_focus_out(self, widget, event):
                self.__enable_disable_select_all()
                self.__enable_disable_deselect()
                self.w_copy_menuitem.set_sensitive(False)

        def __on_text_buffer_has_selection(self, obj, pspec):
                if obj.get_selection_bounds():
                        self.w_copy_menuitem.set_sensitive(True)
                        self.w_deselect_menuitem.set_sensitive(True)
                else:
                        self.w_copy_menuitem.set_sensitive(False)
                        self.w_deselect_menuitem.set_sensitive(False)

        def __set_all_publishers_mode(self):
                if self.is_all_publishers:
                        return
                self.__setup_before_all_publishers_mode()

        def __setup_startpage(self, show_startpage):
                self.opener = urllib.FancyURLopener()
                self.document = gtkhtml2.Document()
                self.document.connect('request_url', self.__request_url)
                self.document.connect('link_clicked', self.__handle_link)
                self.document.clear()

                self.view = gtkhtml2.View()
                self.view.set_document(self.document)
                self.view.connect('request_object', self.__request_object)
                self.view.connect('on_url', self.__on_url)

                try:
                        self.lang, encode = locale.getlocale(locale.LC_CTYPE)
                        if debug:
                                print "Lang: %s: Encode: %s" % (self.lang, encode)
                except locale.Error:
                        self.lang = "C"
                if self.lang == None or self.lang == "":
                        self.lang = "C"
                self.lang_root = self.lang.split('_')[0]
                # Load Start Page to setup base URL to allow loading images in other pages
                self.__load_startpage()
                if show_startpage:
                        self.w_main_view_notebook.set_current_page(
                                NOTEBOOK_START_PAGE)
                else:
                        if self.start_insearch:
                                self.document.clear()
                        self.w_main_view_notebook.set_current_page(
                                NOTEBOOK_PACKAGE_LIST_PAGE)
                self.w_startpage_scrolled_window.add(self.view)

        # Stub handler required by GtkHtml widget
        def __request_object(self, *vargs):
                pass

        def __load_startpage(self):
                self.link_load_page = ""
                if self.__load_startpage_locale(START_PAGE_CACHE_LANG_BASE):
                        return
                if self.__load_startpage_locale(START_PAGE_LANG_BASE):
                        return                        
                self.__handle_startpage_load_error(self.start_page_url)

        def __load_startpage_locale(self, start_page_lang_base):
                self.start_page_url = os.path.join(self.application_dir,
                        start_page_lang_base % (self.lang, START_PAGE_HOME))
                if self.__load_uri(self.document, self.start_page_url):
                        return True
                        
                if self.lang_root != None and self.lang_root != self.lang:
                        start_page_url = os.path.join(self.application_dir,
                                start_page_lang_base % (self.lang_root, START_PAGE_HOME))
                        if self.__load_uri(self.document, start_page_url):
                                return True

                start_page_url = os.path.join(self.application_dir,
                        start_page_lang_base % ("C", START_PAGE_HOME))
                if self.__load_uri(self.document, start_page_url):
                        return True
                return False

        def __handle_startpage_load_error(self, start_page_url):
                self.document.open_stream('text/html')
                self.document.write_stream(_(
                    "<html><head></head><body><H2>Welcome to"
                    "PackageManager!</H2><br>"
                    "<font color='#0000FF'>Warning: Unable to "
                    "load Start Page:<br>%s</font></body></html>")
                    % (start_page_url))
                self.document.close_stream()

        def __process_api_search_error(self, error):
                self.current_repos_with_search_errors = []

                for pub, err in error.failed_servers:
                        logger.error(_("Publisher:") + " " + pub + ": " +
                            _("failed to respond") + "\n" + str(err))
                        gui_misc.notify_log_error(self)
                for pub in error.invalid_servers:
                        logger.error(_("Publisher:") + " " + pub + ": " +
                            _("invalid response") + "\n" +
                            _("A valid response was not returned."))
                        gui_misc.notify_log_error(self)
                for pub, err in error.unsupported_servers:
                        self.current_repos_with_search_errors.append(
                            (pub, _("unsupported search"), err))

        def __on_infosearch_button_press_event(self, widget, event):
                if len(self.current_repos_with_search_errors) > 0:
                        self.__handle_api_search_error(True)
                        return
                if self.error_logged:
                        self.__on_log_activate(None)

        def __handle_api_search_error(self, show_all=False):
                if self.exiting:
                        return
                if len(self.current_repos_with_search_errors) == 0:
                        if not self.error_logged:
                                self.w_infosearch_frame.hide()
                        return

                repo_count = 0
                for pub, err_type, err_str in self.current_repos_with_search_errors:
                        if show_all or (pub not in self.gconf_not_show_repos):
                                repo_count += 1
                if repo_count == 0:
                        if not self.error_logged:
                                self.w_infosearch_frame.hide()
                        return

                self.w_infosearch_frame.set_tooltip_text(
                    _("Search Errors: click to view"))

                self.w_infosearch_frame.show()
                infobuffer = self.api_search_error_textview.get_buffer()
                infobuffer.set_text("")
                textiter = infobuffer.get_end_iter()
                for pub, err_type, err_str in self.current_repos_with_search_errors:

                        if show_all or (pub not in self.gconf_not_show_repos):
                                infobuffer.insert_with_tags_by_name(textiter,
                                    "%(pub)s (%(err_type)s)\n" % {"pub": pub,
                                    "err_type": err_type}, "bold")
                                infobuffer.insert(textiter, "%s\n" % (err_str))

                self.api_search_checkbox.set_active(False)
                self.api_search_error_dialog.show()
                self.api_search_button.grab_focus()

        def __on_url(self, view, link):
                # Handle mouse over events on links and reset when not on link
                if link == None or link == "":
                        self.update_statusbar()
                else:
                        display_link = self.__handle_link(None, link, DISPLAY_LINK)
                        if display_link != None:
                                self.__update_statusbar_message(display_link)
                        else:
                                self.update_statusbar()

        @staticmethod
        def __is_relative_to_server(url):
                parts = urlparse.urlparse(url)
                if parts[0] or parts[1]:
                        return 0
                return 1

        def __open_url(self, url):
                uri = self.__resolve_uri(url)
                return self.opener.open(uri)

        def __resolve_uri(self, uri):
                if self.__is_relative_to_server(uri) and self.current_url != uri:
                        return urlparse.urljoin(self.current_url, uri)
                return uri

        def __request_url(self, document, url, stream):
                try:
                        f = self.__open_url(url)
                except  (IOError, OSError), err:
                        logger.error(str(err))
                        gui_misc.notify_log_error(self)
                        return
                stream.set_cancel_func(self.__stream_cancel)
                stream.write(f.read())

        # Stub handler required by GtkHtml widget or widget will assert
        def __stream_cancel(self, *vargs):
                pass

        def __load_uri(self, document, link):
                self.__update_statusbar_message(_("Loading... %s") % link)
                try:
                        f = self.__open_url(link)
                except  (IOError, OSError), err:
                        if debug:
                                print "err: %s" % (err)
                        self.__update_statusbar_message(_("Stopped"))
                        return False
                self.current_url = self.__resolve_uri(link)

                self.document.clear()
                headers = f.info()
                mime = headers.getheader('Content-type').split(';')[0]
                if mime:
                        self.document.open_stream(mime)
                else:
                        self.document.open_stream('text/plain')

                self.document.write_stream(f.read())
                self.document.close_stream()
                self.__update_statusbar_message(_("Done"))
                return True

        def __link_load_error(self, link):
                self.document.clear()
                self.document.open_stream('text/html')
                # The replace startpage_star.png is done as a change after
                # l10n code freeze.
                self.document.write_stream((_(
                    "<html><head></head><body><font color='#000000'>\
                    <a href='stub'></a></font>\
                    <a href='pm?%s=internal&uri=%s'>\
                    <IMG SRC = '%s/startpage_star.png' \
                    style='border-style: none'></a> <br><br>\
                    <h2><font color='#0000FF'>Warning: Unable to \
                    load URL</font></h2><br>%s</body></html>") % (PM_ACTION,
                    START_PAGE_HOME, START_PAGE_IMAGES_BASE, link)
                    ).replace("/startpage_star.png' ","/dialog-warning.png' "))
                self.document.close_stream()

        def __get_publisher_combobox_index(self, pub_name):
                index = -1
                model = self.w_repository_combobox.get_model()
                for entry in model:
                        if entry[enumerations.REPOSITORY_PREFIX] == pub_name:
                                index = entry[enumerations.REPOSITORY_ID]
                                break
                return index

        def __handle_browse_publisher(self, index):
                if index == -1:
                        return
                self.w_repository_combobox.grab_focus()
                self.w_repository_combobox.set_active(index)
                
        def __handle_search_all_publishers(self, term):
                self.__set_search_start()
                self.is_all_publishers_installed = False
                self.w_repository_combobox.set_active(self.repo_combobox_all_pubs_index)
                self.__set_search_text_mode(enumerations.SEARCH_STYLE_NORMAL)
                self.w_searchentry.set_text(term)
                gobject.idle_add(self.__do_search)

        def __handle_view_all_publishers_installed(self):
                self.w_filter_combobox.set_active(enumerations.FILTER_ALL)
                self.__set_main_view_package_list()
                self.update_statusbar()
                
        def __handle_link(self, document, link, handle_what = CLICK_LINK):
                query_dict = self.__urlparse_qs(link)

                action = None
                if query_dict.has_key(PM_ACTION):
                        action = query_dict[PM_ACTION][0]
                elif handle_what == DISPLAY_LINK:
                        return link
                ext_uri = ""
                protocol = None

                search_action = None
                if action == ACTION_INTERNAL:
                        if query_dict.has_key(INTERNAL_SEARCH):
                                search_action = query_dict[INTERNAL_SEARCH][0]
                
                if self.w_main_statusbar_label:
                        s1 = "<b>"
                        e1 = "</b>"
                else:
                        s1 = e1 = '"'

                # Browse a Publisher
                if search_action and search_action.find(INTERNAL_SEARCH_VIEW_PUB) > -1:
                        pub = re.findall(r'<b>(.*)<\/b>', search_action)[0]
                        if handle_what == DISPLAY_LINK:
                                pub_name = self.__get_publisher_display_name_from_prefix(
                                    pub)
                                return _("View packages in %(s1)s%(pub)s%(e1)s") % \
                                        {"s1": s1, "pub": \
                                        pub_name, "e1": e1}
                        index = self.__get_publisher_combobox_index(pub)
                        gobject.idle_add(self.__handle_browse_publisher, index)
                        return
                # Search in All Publishers
                if search_action and search_action == INTERNAL_SEARCH_ALL_PUBS:
                        if handle_what == DISPLAY_LINK:
                                return _("Search within %(s1)sAll Publishers%(e1)s") % \
                                        {"s1": s1, "e1": e1}
                        self.__handle_search_all_publishers(self.previous_search_text)
                        return
                # Change view to All Publishers (Installed)
                if search_action and search_action == INTERNAL_SEARCH_ALL_PUBS_INSTALLED:
                        if handle_what == DISPLAY_LINK:
                                return _("View installed packages for %(s1)sAll "
                                    "Publishers%(e1)s") % {"s1": s1, "e1": e1}
                        self.__handle_view_all_publishers_installed()
                        return
                # Change View to All Packages
                if search_action and search_action == INTERNAL_SEARCH_VIEW_ALL:
                        if handle_what == DISPLAY_LINK:
                                return _("Change View to %(s1)sAll Packages%(e1)s") % \
                                        {"s1": s1, "e1": e1}
                        self.w_filter_combobox.set_active(enumerations.FILTER_ALL)
                        self.w_filter_combobox.grab_focus()
                        return                        
                # Launch Search Help
                if search_action and search_action == INTERNAL_SEARCH_HELP:
                        if handle_what == DISPLAY_LINK:
                                return _("Display %(s1)sSearch Help%(e1)s") % \
                                        {"s1": s1, "e1": e1}
                        self.__update_statusbar_message(
                            _("Loading %(s1)sSearch Help%(e1)s ...") %
                            {"s1": s1, "e1": e1})
                        gui_misc.display_help("search-pkg")
                        return
                # View Recent Search Results
                if search_action and \
                        search_action.find(INTERNAL_SEARCH_VIEW_RESULTS) > -1:
                        recent_search = \
                                re.findall(r'<span>(.*)<\/span>', search_action)[0]
                        if handle_what == DISPLAY_LINK:
                                return _("View results for %s") % recent_search
                        category_tree = self.w_categories_treeview.get_model()
                        if category_tree == None:
                                return
                        rs_iter = category_tree.iter_children(
                            self.recent_searches_cat_iter)
                        while rs_iter:
                                rs_value = category_tree.get_value(rs_iter,
                                    enumerations.CATEGORY_VISIBLE_NAME)
                                if rs_value == recent_search:
                                        path = category_tree.get_path(rs_iter)
                                        self.w_categories_treeview.set_cursor(path)
                                        self.w_categories_treeview.scroll_to_cell(path)
                                        return
                                rs_iter = category_tree.iter_next(rs_iter)
                        return

                # Internal Browse
                if action == ACTION_INTERNAL:
                        if query_dict.has_key(INTERNAL_URI):
                                int_uri = query_dict[INTERNAL_URI][0]
                                if handle_what == DISPLAY_LINK:
                                        return int_uri
                        else:
                                if handle_what == CLICK_LINK:
                                        self.__link_load_error(_("No URI specified"))
                                return
                        if handle_what == CLICK_LINK and \
                            not self.__load_uri(document, int_uri):
                                self.__link_load_error(int_uri)
                        return
                # External browse
                elif action == ACTION_EXTERNAL:
                        if query_dict.has_key(EXTERNAL_URI):
                                ext_uri = query_dict[EXTERNAL_URI][0]
                        else:
                                if handle_what == CLICK_LINK:
                                        self.__link_load_error(_("No URI specified"))
                                return
                        if query_dict.has_key(EXTERNAL_PROTOCOL):
                                protocol = query_dict[EXTERNAL_PROTOCOL][0]
                        else:
                                protocol = DEFAULT_PROTOCOL

                        if handle_what == DISPLAY_LINK:
                                return protocol + "://" + ext_uri
                        self.__open_link(protocol + "://" + ext_uri)
                elif handle_what == DISPLAY_LINK:
                        return None
                elif action == None:
                        if link and link.endswith(".p5i"):
                                self.set_busy_cursor()
                                gobject.spawn_async([self.application_path, "-i", link])
                                gobject.timeout_add(1500, self.unset_busy_cursor)
                                return
                        self.__open_link(link)
                # Handle empty and unsupported actions
                elif action == "":
                        self.__link_load_error(_("Empty Action not supported"))
                        return
                elif action != None:
                        self.__link_load_error(_("Action not supported: %s") % action)
                        return

        def __open_link(self, link):
                self.set_busy_cursor()
                if self.original_user == None:
                        if self.user_rights:
                                self.__link_load_error(link)
                                self.unset_busy_cursor()
                        else:
                                try:
                                        gnome.url_show(link)
                                        gobject.timeout_add(1000, self.unset_busy_cursor)
                                except gobject.GError:
                                        self.__link_load_error(link)
                                        self.unset_busy_cursor()
                else: 
                        prog = os.path.join(self.application_dir, OPEN_LINK)
                        try:
                                return_code = subprocess.call([prog, 
                                    self.original_user, link])
                                gobject.timeout_add(1000, self.unset_busy_cursor)
                        except OSError:
                                return_code = 1
                        if return_code != 0:
                                self.__link_load_error(link)
                                self.unset_busy_cursor()

        def __link_load_page(self, text =""):
                self.link_load_page = text
                self.document.clear()
                self.document.open_stream('text/html')
                display = ("<html><head><meta http-equiv='Content-Type' "
                        "content='text/html; charset=UTF-8'></head><body>%s</body>"
                        "</html>" % text)
                self.document.write_stream(display)
                self.document.close_stream()

        @staticmethod
        def __urlparse_qs(url, keep_blank_values=0, strict_parsing=0):
                scheme, netloc, url, params, querystring, fragment = urlparse.urlparse(
                    url)
                if debug:
                        print ("Query: scheme %s, netloc %s, url %s, params %s,"
                            "querystring %s, fragment %s"
                            % (scheme, netloc, url, params, querystring, fragment))
                return parseqs.parse_qs(querystring)

        @staticmethod
        def __get_new_application_liststore():
                return gtk.ListStore(
                        gobject.TYPE_BOOLEAN,     # enumerations.MARK_COLUMN
                        gtk.gdk.Pixbuf,           # enumerations.STATUS_ICON_COLUMN
                        gobject.TYPE_STRING,      # enumerations.NAME_COLUMN
                        gobject.TYPE_STRING,      # enumerations.DESCRIPTION_COLUMN
                        gobject.TYPE_INT,         # enumerations.STATUS_COLUMN
                        gobject.TYPE_PYOBJECT,    # enumerations.FMRI_COLUMN
                        gobject.TYPE_STRING,      # enumerations.STEM_COLUMN
                        gobject.TYPE_STRING,      # enumerations.DISPLAY_NAME_COLUMN
                        gobject.TYPE_BOOLEAN,     # enumerations.IS_VISIBLE_COLUMN
                        gobject.TYPE_PYOBJECT,    # enumerations.CATEGORY_LIST_COLUMN
                        gobject.TYPE_STRING,      # enumerations.PUBLISHER_COLUMN
                        gobject.TYPE_STRING       # enumerations.PUBLISHER_PREFIX_COLUMN
                        )

        @staticmethod
        def __get_new_category_liststore():
                return gtk.TreeStore(
                        gobject.TYPE_INT,         # enumerations.CATEGORY_ID
                        gobject.TYPE_STRING,      # enumerations.CATEGORY_NAME
                        gobject.TYPE_STRING,      # enumerations.CATEGORY_VISIBLE_NAME
                        gobject.TYPE_STRING,      # enumerations.CATEGORY_DESCRIPTION
                        gobject.TYPE_PYOBJECT,    # enumerations.SECTION_LIST_OBJECT
                        gobject.TYPE_BOOLEAN,     # enumerations.CATEGORY_IS_VISIBLE
                        )

        @staticmethod
        def __get_new_section_liststore():
                return gtk.ListStore(
                        gobject.TYPE_INT,         # enumerations.SECTION_ID
                        gobject.TYPE_STRING,      # enumerations.SECTION_NAME
                        gobject.TYPE_BOOLEAN,     # enumerations.SECTION_ENABLED
                        )

        @staticmethod
        def __get_new_filter_liststore():
                return gtk.ListStore(
                        gobject.TYPE_INT,         # enumerations.FILTER_ID
                        gtk.gdk.Pixbuf,           # enumerations.FILTER_ICON
                        gobject.TYPE_STRING,      # enumerations.FILTER_NAME
                        )

        @staticmethod
        def __get_new_repositories_liststore():
                return gtk.ListStore(
                        gobject.TYPE_INT,         # enumerations.REPOSITORY_ID
                        gobject.TYPE_STRING,      # enumerations.REPOSITORY_DISPLAY_NAME
                        gobject.TYPE_STRING,      # enumerations.REPOSITORY_PREFIX
                        gobject.TYPE_STRING,      # enumerations.REPOSITORY_ALIAS
                        )

        def __init_application_tree_view(self, application_list,
            application_list_filter, application_list_sort,
            application_sort_column):
                ##APPLICATION MAIN TREEVIEW
                if application_list_filter == None:
                        application_list_filter = application_list.filter_new()
                if application_list_sort == None:
                        application_list_sort = \
                            gtk.TreeModelSort(application_list_filter)
                        application_list_sort.set_sort_column_id(
                            application_sort_column, gtk.SORT_ASCENDING)
                        application_list_sort.set_sort_func(
                            enumerations.STATUS_ICON_COLUMN, 
                            self.__column_sort_func, 
                            enumerations.STATUS_ICON_COLUMN)
                        application_list_sort.set_sort_func(
                            enumerations.DESCRIPTION_COLUMN, 
                            self.__column_sort_func, 
                            enumerations.DESCRIPTION_COLUMN)
                toggle_renderer = gtk.CellRendererToggle()

                column = gtk.TreeViewColumn("", toggle_renderer,
                    active = enumerations.MARK_COLUMN)
                column.set_cell_data_func(toggle_renderer, self.cell_data_function, None)
                column.set_clickable(True)
                column.connect('clicked', self.__select_column_clicked)
                self.w_application_treeview.append_column(column)
                select_image = gtk.Image()
                select_image.set_from_pixbuf(gui_misc.get_icon(
                    self.icon_theme, 'selection'))
                select_image.set_tooltip_text(_("Click to toggle selections"))
                select_image.show()
                column.set_widget(select_image)

                name_renderer = gtk.CellRendererText()
                column = gtk.TreeViewColumn(_("Name"), name_renderer,
                    text = enumerations.NAME_COLUMN)
                column.set_resizable(True)
                column.set_min_width(150)
                column.set_sort_column_id(enumerations.NAME_COLUMN)
                column.set_sort_indicator(True)
                column.set_cell_data_func(name_renderer, self.cell_data_function, None)
                column.connect_after('clicked',
                    self.__application_treeview_column_sorted, None)
                self.w_application_treeview.append_column(column)
                column = self.__create_icon_column(_("Status"), True,
                    enumerations.STATUS_ICON_COLUMN, True)
                column.set_sort_column_id(enumerations.STATUS_ICON_COLUMN)
                column.set_sort_indicator(True)
                column.connect_after('clicked',
                    self.__application_treeview_column_sorted, None)
                self.w_application_treeview.append_column(column)
                if self.is_all_publishers or self.is_all_publishers_installed or \
                        self.in_recent_search:
                        repository_renderer = gtk.CellRendererText()
                        column = gtk.TreeViewColumn(_('Publisher'),
                            repository_renderer,
                            markup = enumerations.PUBLISHER_COLUMN)
                        column.set_sort_column_id(enumerations.PUBLISHER_COLUMN)
                        column.set_resizable(True)
                        column.set_sort_indicator(True)
                        column.set_cell_data_func(repository_renderer,
                            self.cell_data_function, None)
                        column.connect_after('clicked',
                            self.__application_treeview_column_sorted, None)
                        self.w_application_treeview.append_column(column)
                        application_list_sort.set_sort_func(
                            enumerations.PUBLISHER_COLUMN, 
                            self.__column_sort_func, 
                            enumerations.PUBLISHER_COLUMN)
                description_renderer = gtk.CellRendererText()
                column = gtk.TreeViewColumn(_('Description'),
                    description_renderer,
                    text = enumerations.DESCRIPTION_COLUMN)
                column.set_sort_column_id(enumerations.DESCRIPTION_COLUMN)
                column.set_resizable(True)
                column.set_sort_indicator(True)
                column.set_cell_data_func(description_renderer,
                    self.cell_data_function, None)
                column.connect_after('clicked',
                    self.__application_treeview_column_sorted, None)
                self.w_application_treeview.append_column(column)
                #Added selection listener
                self.package_selection = self.w_application_treeview.get_selection()
                self.application_list = application_list
                self.application_list_filter = application_list_filter
                self.application_list_sort = application_list_sort
                toggle_renderer.connect('toggled', self.__active_pane_toggle,
                    application_list_sort)

        def __init_tree_views(self, application_list, category_list, 
            section_list, application_list_filter = None, 
            application_list_sort = None, 
            application_sort_column = enumerations.NAME_COLUMN):
                '''This function connects treeviews with their models and also applies
                filters'''
                if self.exiting:
                        return
                if category_list == None:
                        self.w_application_treeview.set_model(None)
                        self.__remove_treeview_columns(self.w_application_treeview)
                elif application_list == None:
                        self.w_categories_treeview.set_model(None)
                        self.__remove_treeview_columns(self.w_categories_treeview)
                else:
                        self.__disconnect_models()
                        self.__remove_treeview_columns(self.w_application_treeview)
                        self.__remove_treeview_columns(self.w_categories_treeview)
                # The logic for set section needs to be here as some sections
                # might be not enabled. In such situation we are setting the set
                # section to "All Categories" one.
                if section_list != None:
                        row = section_list[self.set_section]
                        if row[enumerations.SECTION_ENABLED] and \
                            self.set_section >= 0 and \
                            self.set_section < len(section_list):
                                if row[enumerations.SECTION_ID] != self.set_section:
                                        self.set_section = 0
                        else:
                                self.set_section = 0

                if application_list != None:
                        self.__init_application_tree_view(application_list,
                            application_list_filter, application_list_sort, 
                            application_sort_column)

                if self.first_run:
                        # When vadj changes we need to set image descriptions
                        # on visible status icons. This catches moving the scroll bars
                        # and scrolling up and down using keyboard.
                        vadj = self.w_application_treeview.get_vadjustment()
                        vadj.connect('value-changed',
                            self.__application_treeview_vadjustment_changed, None)

                        # When the size of the application_treeview changes
                        # we need to set image descriptions on visible status icons.
                        self.w_application_treeview.connect('size-allocate',
                            self.__application_treeview_size_allocate, None)

                category_selection = self.w_categories_treeview.get_selection()
                if category_list != None:
                        ##CATEGORIES TREEVIEW
                        enumerations.CATEGORY_VISIBLE_NAME_r = gtk.CellRendererText()
                        column = gtk.TreeViewColumn(_('Name'),
                            enumerations.CATEGORY_VISIBLE_NAME_r,
                            markup = enumerations.CATEGORY_VISIBLE_NAME)
                        enumerations.CATEGORY_VISIBLE_NAME_r.set_property("xalign", 0.0)
                        self.w_categories_treeview.append_column(column)
                        #Added selection listener
                        category_selection.set_mode(gtk.SELECTION_SINGLE)
                        self.w_categories_treeview.set_search_column(
                            enumerations.CATEGORY_VISIBLE_NAME)

                if section_list != None:
                        self.section_list = section_list
                if category_list != None:
                        self.category_list = category_list

                if application_list != None:
                        self.w_application_treeview.set_model(
                            self.application_list_sort)
                        if application_list_filter == None:
                                self.application_list_filter.set_visible_func(
                                    self.__application_filter)

                if self.first_run:
                        category_selection.connect("changed",
                            self.__on_category_selection_changed, None)
                        self.w_categories_treeview.connect("row-activated",
                            self.__on_category_row_activated, None)
                        self.w_categories_treeview.connect("focus-in-event",
                            self.__on_category_focus_in, None)
                        self.w_categories_treeview.connect("button_press_event",
                            self.__on_categoriestreeview_button_press_event, None)
                        self.w_categories_treeview.connect("row-collapsed",
                            self.__on_categoriestreeview_row_collapsed, None)
                        self.w_categories_treeview.connect("row-expanded",
                            self.__on_categoriestreeview_row_expanded, None)
                        self.package_selection.set_mode(gtk.SELECTION_SINGLE)
                        self.package_selection.connect("changed",
                            self.__on_package_selection_changed, None)
                if category_list != None and section_list != None:
                        self.__add_categories_to_tree(category_list, section_list)
                self.a11y_application_treeview = \
                    self.w_application_treeview.get_accessible()
                obj = self.a11y_application_treeview.get_column_header(0)
                if obj != None:
                        obj.set_name(_("all selection toggle"))
                self.process_package_list_end()

        def __setup_filter_combobox(self):
                render_pixbuf = gtk.CellRendererPixbuf()
                self.w_filter_combobox.pack_start(render_pixbuf, expand = True)
                self.w_filter_combobox.add_attribute(render_pixbuf, "pixbuf", 
                    enumerations.FILTER_ICON)
                self.w_filter_combobox.set_cell_data_func(render_pixbuf,
                    self.filter_cell_data_function, enumerations.FILTER_ICON)

                cell = gtk.CellRendererText()
                self.w_filter_combobox.pack_start(cell, True)
                self.w_filter_combobox.add_attribute(cell, 'text',
                    enumerations.FILTER_NAME)
                self.w_filter_combobox.set_cell_data_func(cell,
                    self.filter_cell_data_function, enumerations.FILTER_NAME)
                self.w_filter_combobox.set_row_separator_func(
                    self.combobox_filter_id_separator)
                self.w_filter_combobox.set_model(self.filter_list)
                self.w_filter_combobox.set_active(self.initial_show_filter)

        def __select_column_clicked(self, data):
                self.set_busy_cursor()
                gobject.idle_add(self.__toggle_select_all,
                    self.w_selectall_menuitem.props.sensitive)

        def __application_treeview_column_sorted(self, widget, user_data):
                self.__set_visible_status(False)

        def __init_repository_tree_view(self):
                cell = gtk.CellRendererText()
                self.w_repository_combobox.pack_start(cell, True)
                self.w_repository_combobox.add_attribute(cell, 'text',
                    enumerations.REPOSITORY_DISPLAY_NAME)
                self.w_repository_combobox.set_row_separator_func(
                    self.combobox_id_separator)

        def __application_treeview_size_allocate(self, widget, allocation, user_data):
                # We ignore any changes in the size during initialization.
                if self.visible_status_id == 0:
                        self.visible_status_id = gobject.idle_add(
                            self.__set_visible_status)

        def __application_treeview_vadjustment_changed(self, widget, user_data):
                self.__set_visible_status()

        def __set_accessible_status(self, model, itr):
                status = model.get_value(itr, enumerations.STATUS_COLUMN)
                if status == api.PackageInfo.INSTALLED:
                        desc = _("Installed")
                elif status == api.PackageInfo.KNOWN:
                        desc = _("Not Installed")
                elif status == api.PackageInfo.UPGRADABLE:
                        desc = _("Updates Available")
                else:
                        desc = None
                if desc != None:
                        obj = self.a11y_application_treeview.ref_at(
                            int(model.get_string_from_iter(itr)),
                            STATUS_COLUMN_INDEX)
                        obj.set_image_description(desc)

        def __set_visible_status(self, check_range = True):
                self.visible_status_id = 0
                if self.w_main_view_notebook.get_current_page() != \
                    NOTEBOOK_PACKAGE_LIST_PAGE:
                        return
                if self.__doing_search():
                        return

                a11y_enabled = False
                if self.a11y_application_treeview.get_n_accessible_children() != 0:
                        a11y_enabled = True

                if not a11y_enabled:
                        return

                visible_range = self.w_application_treeview.get_visible_range()
                if visible_range == None:
                        return
                a11y_start = visible_range[0][0]
                a11y_end = visible_range[1][0]

                # We use check_range only for accessibility purposes to
                # reduce the amount of processing to be done in that case.
                # Switching Publishers need to use default range
                if self.publisher_changed:
                        check_range = False
                        self.publisher_changed = False
                if self.in_search_mode:
                        check_range = False
                
                if self.application_treeview_range != None:
                        if check_range and a11y_enabled:
                                old_start = self.application_treeview_range[0][0]
                                old_end = self.application_treeview_range[1][0]
                                 # Old range is the same or smaller than new range
                                 # so do nothing
                                if (a11y_start >= old_start and 
                                    a11y_end <= old_end):
                                        a11y_end =  a11y_start - 1
                                else:
                                        if a11y_start < old_end:
                                                if a11y_end < old_end:
                                                        if a11y_end >= old_start:
                                                                a11y_end = old_start
                                                else:
                                                        a11y_start = old_end
                self.application_treeview_range = visible_range

                sort_filt_model = \
                    self.w_application_treeview.get_model() #gtk.TreeModelSort

                if a11y_enabled:
                        sf_itr = sort_filt_model.get_iter_from_string(
                            str(a11y_start))                
                        while a11y_start <= a11y_end:
                                self.__set_accessible_status(sort_filt_model, sf_itr)
                                a11y_start += 1
                                sf_itr = sort_filt_model.iter_next(sf_itr)

        def __doing_search(self):
                return self.search_start > 0
                
        def __create_icon_column(self, name, expand_pixbuf, enum_value, set_data_func):
                column = gtk.TreeViewColumn()
                column.set_title(name)
                #Commented, since there was funny jumping of the icons
                #column.set_sizing(gtk.TREE_VIEW_COLUMN_AUTOSIZE)
                render_pixbuf = gtk.CellRendererPixbuf()
                column.pack_start(render_pixbuf, expand = expand_pixbuf)
                column.add_attribute(render_pixbuf, "pixbuf", enum_value)
                column.set_fixed_width(32)
                if set_data_func:
                        column.set_cell_data_func(render_pixbuf,
                            self.cell_data_function, None)
                return column

        def __disconnect_models(self):
                if self.w_application_treeview:
                        self.w_application_treeview.set_model(None)
                if self.w_categories_treeview:
                        self.w_categories_treeview.set_model(None)

        def __disconnect_repository_model(self):
                self.w_repository_combobox.set_model(None)

        @staticmethod
        def __column_sort_func(treemodel, iter1, iter2, column):
                get_val = treemodel.get_value
                get_val = treemodel.get_value
                status1 = get_val(iter1, column)
                status2 = get_val(iter2, column)
                ret = cmp(status1, status2)
                if ret != 0:
                        return ret
                name1 = get_val(iter1, enumerations.NAME_COLUMN)
                name2 = get_val(iter2, enumerations.NAME_COLUMN)
                return cmp(name1, name2)

        @staticmethod
        def __remove_treeview_columns(treeview):
                columns = treeview.get_columns()
                if columns:
                        for column in columns:
                                treeview.remove_column(column)

        @staticmethod
        def __init_sections(section_list):
                '''This function is for initializing the sections list'''
                enabled = True
                # Only enable the first section. Later other sections are enabled
                # in __add_category_to_section() if the section contains any categories
                # which in turn contain some packages.
                section_list.append([0, _('All Categories'), enabled ])
                enabled = False
                section_list.append([1, _('Meta Packages'), enabled ])
                section_list.append([2, _('Applications'), enabled ])
                section_list.append([3, _('Desktop (GNOME)'), enabled ])
                section_list.append([4, _('Development'), enabled ])
                section_list.append([5, _('Distributions'), enabled ])
                section_list.append([6, _('Drivers'), enabled ])
                section_list.append([7, _('System'), enabled ])
                section_list.append([8, _('Web Services'), enabled ])

        def __init_show_filter(self):
                max_length = 0
                for filter_id, pixbuf, label in self.filter_options:
                        self.filter_list.append([filter_id, pixbuf, label, ])
                        if filter_id == -1:
                                continue
                        max_length = self.__get_max_text_length(
                            max_length, label, self.w_filter_combobox)
                
                if self.initial_show_filter >= enumerations.FILTER_ALL and \
                    self.initial_show_filter < len(self.filter_list):
                        row = self.filter_list[self.initial_show_filter]
                        if row[enumerations.SECTION_ID] != self.initial_show_filter:
                                self.initial_show_filter = enumerations.FILTER_ALL
                else:
                        self.initial_show_filter = enumerations.FILTER_ALL
                return max_length

        @staticmethod
        def __get_max_text_length(length_to_check, text, widget):
                if widget == None:
                        return 0
                context = widget.get_pango_context()
                metrics = context.get_metrics(context.get_font_description())
                current_length = pango.PIXELS(
                    metrics.get_approximate_char_width() * len(text))
                if current_length > length_to_check:
                        return current_length
                else:
                        return length_to_check

        def __on_mainwindow_key_press_event(self, widget, event):
                if self.is_busy_cursor_set():
                        if event.type == gtk.gdk.KEY_PRESS:
                                keyname = gtk.gdk.keyval_name(event.keyval)
                                if keyname == "Escape" and self.api_o.can_be_canceled():
                                        Thread(target = self.api_o.cancel,
                                            args = ()).start()
                        return True
                else:
                        return False

        def __on_mainwindow_delete_event(self, widget, event):
                ''' handler for delete event of the main window '''
                if self.__check_if_something_was_changed() == True:
                        # XXX Change this to not quit and show dialog
                        # XXX if some changes were applied:
                        self.__main_application_quit()
                        return True
                else:
                        self.__main_application_quit()

        def __handle_resize(self, widget):
                if self.last_resize == widget.get_size():
                        return
                self.last_resize = widget.get_size()

                if self.w_main_view_notebook.get_current_page() == NOTEBOOK_START_PAGE:
                        if self.link_load_page == "":
                                self.__load_startpage()
                        else:
                                self.__link_load_page(self.link_load_page)
                
        def __on_mainwindow_check_resize(self, widget):
                if not widget or not self.gdk_window:
                        return
                if self.resize_id != 0:
                        gobject.source_remove(self.resize_id)
                        self.resize_id = 0

                self.resize_id = \
                            gobject.timeout_add(RESIZE_DELAY,
                                self.__handle_resize, widget)
                                
                status_height = self.w_statusbar_hbox.get_allocation().height
                self.gdk_window.move_resize(0, 0, widget.get_size()[0],
                    widget.get_size()[1]-status_height)

        def __on_api_search_error_delete_event(self, widget, event):
                self.__on_api_search_button_clicked(None)

        def __on_preferencesdialog_delete_event(self, widget, event):
                self.__on_preferencesclose_clicked(None)
                return True

        def __on_api_search_button_clicked(self, widget):
                self.api_search_error_dialog.hide()

        def __on_file_quit_activate(self, widget):
                ''' handler for quit menu event '''
                self.__on_mainwindow_delete_event(None, None)

        def __on_file_manage_publishers(self, widget):
                ''' handler for manage publishers menu event '''
                repository.Repository(self, self.image_directory,
                    action=enumerations.MANAGE_PUBLISHERS,
                    main_window = self.w_main_window)

        def __on_file_add_publisher(self, widget):
                ''' handler for add publisher menu event '''
                repository.Repository(self, self.image_directory,
                    action=enumerations.ADD_PUBLISHER,
                    main_window = self.w_main_window)

        def __on_file_be_activate(self, widget):
                ''' handler for be menu event '''
                beadm.Beadmin(self)

        def __on_searchentry_changed(self, widget):
                if widget.get_text_length() > 0 and \
                        self.search_text_style != enumerations.SEARCH_STYLE_PROMPT:
                        if self.entry_embedded_icons_supported:
                                self.w_searchentry.set_property("secondary-icon-stock", 
                                    gtk.STOCK_CANCEL)
                                self.w_searchentry.set_property(
                                   "secondary-icon-sensitive", True)
                        self.w_clear_search_menuitem.set_sensitive(True)
                else:
                        if self.entry_embedded_icons_supported:
                                self.w_searchentry.set_property("secondary-icon-stock", 
                                    None)
                        self.w_clear_search_menuitem.set_sensitive(False)
                self.__enable_disable_entry_selection(widget)

        def __update_statusbar_for_search(self):
                if self.is_all_publishers:
                        self.__update_statusbar_message(_("Search all publishers"))
                else:
                        self.__update_statusbar_message(_("Search current publisher"))

        def __remove_statusbar_message(self):
                if self.statusbar_message_id > 0:
                        try:
                                self.w_main_statusbar.remove_message(0,
                                    self.statusbar_message_id)
                        except AttributeError:
                                self.w_main_statusbar.remove(0,
                                    self.statusbar_message_id)
                        self.statusbar_message_id = 0
        
        def __update_statusbar_message(self, message):
                if self.exiting:
                        return
                self.__remove_statusbar_message()
                self.statusbar_message_id = self.w_main_statusbar.push(0, message)
                if self.w_main_statusbar_label:
                        self.w_main_statusbar_label.set_markup(message)

        def __setup_before_all_publishers_mode(self):
                self.is_all_publishers_installed = False
                self.is_all_publishers = True
                self.w_infosearch_frame.hide()
                if not self.w_searchentry.is_focus():
                        self.__set_searchentry_to_prompt()
                
                self.__save_setup_before_search()
                first_run = self.first_run
                self.first_run = False
                self.__clear_before_search(False)
                # Show the Search all page if not showing the Start Page on startup
                show_search_all_page = not first_run or (first_run 
                    and not self.show_startpage)
                if show_search_all_page:
                        gobject.idle_add(self.__setup_search_all_page)
                elif self.show_startpage:
                        gobject.idle_add(self.w_main_view_notebook.set_current_page,
                            NOTEBOOK_START_PAGE)
                self.__update_statusbar_for_search()
                
        def __set_searchentry_to_prompt(self):
                if not self.first_run and self.search_text_style != \
                        enumerations.SEARCH_STYLE_PROMPT:
                        self.__set_search_text_mode(enumerations.SEARCH_STYLE_PROMPT)
  
        def __setup_search_all_page(self):
                header = INFORMATION_PAGE_HEADER
                header += _("alt='[Information]' title='Information' ALIGN='bottom'></TD>"
                    "<TD><h3><b>Search All Publishers</b></h3><TD></TD></TR>"
                    "<TR><TD></TD><TD> Use the Search field to search for packages "
                    "within the following Publishers:</TD></TR>"
                    )
                body = "<TR><TD></TD><TD>"
                pub_browse_list = ""
                model = self.w_repository_combobox.get_model()
                for pub in model:
                        prefix = pub[enumerations.REPOSITORY_PREFIX]
                        if (prefix and prefix not in self.publisher_options.values()):
                                pub_alias = pub[enumerations.REPOSITORY_ALIAS]
                                if pub_alias != None and len(pub_alias) > 0:
                                        pub_name = "%s (%s)" % (
                                            pub_alias, prefix)
                                else:
                                        pub_name = prefix
                                body += "<li style='padding-left:7px'>%s</li>" \
                                    % pub_name
                                pub_browse_list += "<li style='padding-left:7px'><a href="
                                pub_browse_list += "'pm?pm-action=internal&search=%s" % \
                                        INTERNAL_SEARCH_VIEW_PUB
                                if pub_alias != None and len(pub_alias) > 0:
                                        pub_browse_list += " <b>%s</b>'>%s</a></li>" % \
                                                (prefix, pub_alias)
                                else:
                                        pub_browse_list += " <b>%s</b>'>%s</a></li>" % \
                                                (prefix, pub_name)
                              
                body += "<TD></TD></TR>"
                body += _("<TR><TD></TD><TD></TD></TR>"
                    "<TR><TD></TD><TD>Click on the Publishers below to view their list "
                    "of packages:</TD></TR>"
                    )
                body += "<TR><TD></TD><TD>"
                body += pub_browse_list
                body += "<TD></TD></TR>"
                footer = "</table>"
                self.__link_load_page(header + body + footer)
                self.w_main_view_notebook.set_current_page(NOTEBOOK_START_PAGE)


        def __setup_search_installed_page(self, text):
                header = INFORMATION_PAGE_HEADER
                header += _("alt='[Information]' title='Information' ALIGN='bottom'></TD>"
                    "<TD><h3><b>Search in All Publishers (Installed)</b></h3><TD></TD>"
                    "</TR><TR><TD></TD><TD> Search is <b>not</b> supported in "
                    "All Publishers (Installed).</TD></TR>"
                    )

                body = _("<TR><TD></TD><TD<TD></TD></TR><TR><TD></TD><TD<TD></TD></TR>"
                    "<TR><TD></TD><TD<TD><b>Suggestions:</b><br></TD></TR>"
                    "<TR><TD></TD><TD<TD>"
                    )

                body += _("<li style='padding-left:7px'>Return to view packages for "
                    "All Publishers <a href='pm?pm-action=internal&search="
                    "%s'>(Installed)</a></li>")  % INTERNAL_SEARCH_ALL_PUBS_INSTALLED
                body += _("<li style='padding-left:7px'>Search for <b>%(text)s"
                    "</b> using All Publishers <a href='pm?pm-action=internal&search="
                    "%(all_pubs)s'>(Search)</a></li>")  % \
                    {"text": text, "all_pubs": INTERNAL_SEARCH_ALL_PUBS}

                body += _("<li style='padding-left:7px'>"
                    "See <a href='pm?pm-action=internal&search="
                    "%s'>Search Help</a></li></TD></TR>") % INTERNAL_SEARCH_HELP
                footer = "</table>"
                self.__link_load_page(header + body + footer)
                self.w_main_view_notebook.set_current_page(NOTEBOOK_START_PAGE)
                self.__set_focus_on_searchentry()

        def __setup_recent_search_page(self):
                header = INFORMATION_PAGE_HEADER
                header += _("alt='[Information]' title='Information' ALIGN='bottom'></TD>"
                    "<TD><h3><b>Recent Searches</b></h3><TD></TD></TR>"
                    "<TR><TD></TD><TD> Access stored results from recent searches "
                    "in this session.</TD></TR>"
                    )
                body = "<TR><TD></TD><TD>"
                search_list = ""
                for search in self.recent_searches_list:
                        search_list += "<li style='padding-left:7px'>%s: <a href=" % \
                                search
                        search_list += "'pm?pm-action=internal&search=%s" % \
                                INTERNAL_SEARCH_VIEW_RESULTS
                        search_list += " <span>%s</span>'>" % search
                        search_list += _("results")
                        search_list += "</a></li>"

                if len(self.recent_searches_list) > 0:
                        body += "<TR><TD></TD><TD></TD></TR><TR><TD></TD><TD>"
                        body += ngettext(
                            "Click on the search results link below to view the stored "
                            "results:", "Click on one of the search results links below "
                            "to view the stored results:",
                            len(self.recent_searches_list)
                            )
                        body += "</TD></TR><TR><TD></TD><TD>"
                        body += search_list
                body += "<TD></TD></TR>"
                footer = "</table>"
                self.__link_load_page(header + body + footer)
                self.w_main_view_notebook.set_current_page(NOTEBOOK_START_PAGE)
                    
        def __setup_zero_filtered_results_page(self):
                header = INFORMATION_PAGE_HEADER
                active_filter = self.w_filter_combobox.get_active()
                header += _("alt='[Information]' title='Information' ALIGN='bottom'></TD>"
                    "<TD><h3><b>View Packages</b></h3><TD></TD></TR><TR><TD></TD><TD>")
                header += ngettext(
                    "There is one package in this category, "
                    "however it is not visible in the selected View:\n"
                    "<li style='padding-left:7px'><b>%s</b></li>",
                    "There are a number of packages in this category, "
                    "however they are not visible in the selected View:\n"
                    "<li style='padding-left:7px'><b>%s</b></li>",
                    self.length_visible_list) % \
                        self.__get_filter_combobox_description(active_filter)

                body = _("<TR><TD></TD><TD<TD></TD></TR><TR><TD></TD><TD<TD></TD></TR>"
                    "<TR><TD></TD><TD<TD><b>Suggestions:</b><br></TD></TR>"
                    "<TR><TD></TD><TD<TD>"
                    )
                body += _("<li style='padding-left:7px'>"
                    "<a href='pm?pm-action=internal&"
                    "search=%s'>Change View to All Packages</a></li>") % \
                    INTERNAL_SEARCH_VIEW_ALL
                footer = "</TD></TR></table>"
                self.__link_load_page(header + body + footer)
                self.w_main_view_notebook.set_current_page(NOTEBOOK_START_PAGE)

        def __setup_search_zero_filtered_results_page(self, text, num):
                header = INFORMATION_PAGE_HEADER
                active_filter = self.w_filter_combobox.get_active()
                header += _("alt='[Information]' title='Information' ALIGN='bottom'></TD>"
                    "<TD><h3><b>Search Results</b></h3><TD></TD></TR><TR><TD></TD><TD>")
                header += ngettext(
                    "Found <b>%(num)s</b> package matching <b>%(text)s</b> "
                    "in All Packages, however it is not listed in the "
                    "<b>%(filter)s</b> View.",
                    "Found <b>%(num)s</b> packages matching <b>%(text)s</b> "
                    "in All Packages, however they are not listed in the "
                    "<b>%(filter)s</b> View.", num) % {"num": num, "text": text,
                    "filter": self.__get_filter_combobox_description(active_filter)}

                body = _("<TR><TD></TD><TD<TD></TD></TR><TR><TD></TD><TD<TD></TD></TR>"
                    "<TR><TD></TD><TD<TD><b>Suggestions:</b><br></TD></TR>"
                    "<TR><TD></TD><TD<TD>"
                    )
                body += _("<li style='padding-left:7px'>"
                    "<a href='pm?pm-action=internal&"
                    "search=%s'>Change View to All Packages</a></li>") % \
                    INTERNAL_SEARCH_VIEW_ALL
                footer = "</TD></TR></table>"
                self.__link_load_page(header + body + footer)
                self.w_main_view_notebook.set_current_page(NOTEBOOK_START_PAGE)
                self.__set_focus_on_searchentry()

        def __get_filter_combobox_description(self, index):
                description = None
                model = self.w_filter_combobox.get_model()
                for entry in model:
                        if entry[enumerations.FILTER_ID] == index:
                                description = entry[enumerations.FILTER_NAME]
                                break
                return description
                
        def __setup_search_zero_results_page(self, pub, text):
                name =  self.__get_publisher_name_from_prefix(pub)
                header = INFORMATION_PAGE_HEADER
                header += _("alt='[Information]' title='Information' ALIGN='bottom'></TD>"
                    "<TD><h3><b>Search Results</b></h3><TD></TD></TR>"
                    "<TR><TD></TD><TD>No packages found in <b>%(pub)s</b> "
                    "matching <b>%(text)s</b></TD></TR>") % {"pub": name, "text": text}

                body = _("<TR><TD></TD><TD<TD></TD></TR><TR><TD></TD><TD<TD></TD></TR>"
                    "<TR><TD></TD><TD<TD><b>Suggestions:</b><br></TD></TR>"
                    "<TR><TD></TD><TD<TD>"
                    "<li style='padding-left:7px'>Check your spelling</li>"
                    "<li style='padding-left:7px'>Try new search terms</li>"
                    )
                if not self.is_all_publishers:
                        body += _("<li style='padding-left:7px'>Search for <b>%(text)s"
                            "</b> within <a href='pm?pm-action=internal&search="
                            "%(all_pubs)s'>All Publishers</a></li>")  % \
                            {"text": text, "all_pubs": INTERNAL_SEARCH_ALL_PUBS}
                        self.previous_search_text = text

                body += _("<li style='padding-left:7px'>"
                    "See <a href='pm?pm-action=internal&search="
                    "%s'>Search Help</a></li></TD></TR>") % INTERNAL_SEARCH_HELP
                footer = "</table>"
                self.__link_load_page(header + body + footer)
                self.w_main_view_notebook.set_current_page(NOTEBOOK_START_PAGE)
                self.__set_focus_on_searchentry()

        def __set_focus_on_searchentry(self):
                self.w_searchentry.grab_focus()
                if self.w_searchentry.get_text() > 0:
                        start, end = self.w_searchentry.get_selection_bounds()
                        self.w_searchentry.select_region(end, end)
                        self.pylintstub = start
                
        def __setup_search_wildcard_page(self):
                header = _(
                    "<table border='0' cellpadding='3' style='table-layout:fixed' >"
                    "<TR><TD><IMG SRC = '%s/dialog-warning.png' style='border-style: "
                    "none' alt='[Warning]' title='Warning' ALIGN='bottom'></TD>"
                    "<TD><h3><b>Search Warning</b></h3><TD></TD></TR>"
                    "<TR><TD></TD><TD>Search using only the wildcard character, "
                    "<b>*</b>, is not supported in All Publishers</TD></TR>"
                    ) % START_PAGE_IMAGES_BASE
                body = _("<TR><TD></TD><TD<TD></TD></TR><TR><TD></TD><TD<TD></TD></TR>"
                    "<TR><TD></TD><TD<TD><b>Suggestions:</b><br></TD></TR>"
                    "<TR><TD></TD><TD<TD>"
                    "<li style='padding-left:7px'>Try new search terms</li>"
                    )
                body += _("<li style='padding-left:7px'>"
                    "See <a href='pm?pm-action=internal&search="
                    "%s'>Search Help</a></li></TD></TR>") % INTERNAL_SEARCH_HELP
                footer = "</table>"
                self.__link_load_page(header + body + footer)
                self.w_main_view_notebook.set_current_page(NOTEBOOK_START_PAGE)
                self.__set_focus_on_searchentry()

        def __clear_before_search(self, show_list=True, in_setup=True, unselect_cat=True):
                self.in_setup = in_setup
                application_list = self.__get_new_application_liststore()
                self.__set_empty_details_panel()
                self.__set_main_view_package_list(show_list)
                self.__init_tree_views(application_list, None, None)
                if unselect_cat:
                        self.__unselect_category()

        def __restore_setup_for_browse(self):
                self.in_search_mode = False
                self.in_recent_search = False
                self.is_all_publishers = False
                self.w_infosearch_frame.hide()
                if self.last_visible_publisher == \
                        self.publisher_options[PUBLISHER_INSTALLED]:
                        self.is_all_publishers_installed = True
                else:
                        self.is_all_publishers_installed = False 
                self.set_busy_cursor()
                if (self.w_repository_combobox.get_active() != 
                    self.saved_repository_combobox_active):
                        self.w_repository_combobox.set_active(
                            self.saved_repository_combobox_active)
                self.set_section = self.saved_section_active
                # Reset MARK_COLUMN        
                for pkg in self.saved_application_list:
                        pub = pkg[enumerations.PUBLISHER_PREFIX_COLUMN]
                        stem = pkg[enumerations.STEM_COLUMN]
                        marked = False
                        pkgs = None
                        if self.selected_pkgs != None:
                                pkgs = self.selected_pkgs.get(pub)
                        if pkgs != None:
                                if stem in pkgs:
                                        marked = True
                        # When switching after Manage Publisher dialog
                        # this assignment can cause bogus refilter
                        if pkg[enumerations.MARK_COLUMN] != marked:
                                pkg[enumerations.MARK_COLUMN] = marked
                if self.saved_category_list == self.category_list:
                        self.__restore_category_state()
                        self.__init_tree_views(self.saved_application_list,
                            None, None,
                            self.saved_application_list_filter,
                            self.saved_application_list_sort)
                else:
                        self.__init_tree_views(self.saved_application_list,
                            self.saved_category_list, self.saved_section_list,
                            self.saved_application_list_filter,
                            self.saved_application_list_sort)

                self.__set_main_view_package_list()

        def __save_application_list(self, app_list):
                self.saved_application_list = app_list
                                
        def __save_setup_before_search(self, single_search=False):
                #Do not save search data models
                if self.in_search_mode:
                        return
                self.__save_application_list(self.application_list)
                self.saved_application_list_sort = \
                        self.application_list_sort
                self.saved_application_list_filter = \
                        self.application_list_filter
                self.saved_category_list = self.category_list
                self.saved_section_list = self.section_list

                pub_index = self.w_repository_combobox.get_active()
                if pub_index != self.repo_combobox_all_pubs_index and \
                        pub_index != self.repo_combobox_add_index:
                        self.saved_repository_combobox_active = pub_index

        def __do_search(self, widget=None, ev=None):
                self.in_recent_search = False
                self.__reset_search_start()
                if self.search_text_style == enumerations.SEARCH_STYLE_PROMPT or \
                        self.w_searchentry.get_text_length() == 0:
                        return

                txt = self.w_searchentry.get_text()
                if len(txt.strip()) == 0:
                        self.w_searchentry.set_text("")
                        return
                if self.is_all_publishers_installed:
                        gobject.idle_add(self.__setup_search_installed_page, txt)
                        return                
                contains_asterix = txt.count("*") > 0
                contains_asterix_only = False
                if contains_asterix:
                        contains_asterix_only = len(txt.replace("*", " ").strip()) == 0
                if contains_asterix_only:
                        self.w_searchentry.set_text("*")
                        self.__set_focus_on_searchentry()
                        if self.is_all_publishers:
                                gobject.idle_add(self.__setup_search_wildcard_page)
                        else:
                                if self.in_search_mode:
                                        self.__unset_search(True)
                                if self.w_categories_treeview.get_model() != None:
                                        self.w_categories_treeview.set_cursor(0)
                        return
                if not self.is_all_publishers:
                        self.__save_setup_before_search(single_search=True)
                self.__clear_before_search()
                self.__set_focus_on_searchentry()
                self.set_busy_cursor()
                self.in_search_mode = True
                        
                self.w_infosearch_frame.hide()
                gobject.idle_add(self.__set_main_view_package_list)
                Thread(target = self.__do_api_search,
                    args = (self.is_all_publishers, )).start()

        def __get_selection_and_category_path(self):
                selection = self.w_categories_treeview.get_selection()
                if not selection:
                        return None, (0,)
                model, itr = selection.get_selected()
                if not model or not itr:
                        return None, (0,)
                return selection, model.get_path(itr)

        def __unselect_category(self):
                selection, path = self.__get_selection_and_category_path()
                if selection:
                        self.__save_active_category(path)
                        selection.unselect_all()

        def __process_after_cancel(self):
                if self.is_all_publishers:
                        self.__setup_before_all_publishers_mode()
                else:
                        self.__unset_search(True)

        def __process_after_search_failure(self):
                self.__reset_search_start()
                self.search_time_sec = 0
                self.application_list = []
                gobject.idle_add(self.update_statusbar)
                gobject.idle_add(self.unset_busy_cursor)
                self.in_setup = False

        @staticmethod
        def __get_origin_uri(repo):
                if repo == None:
                        return None
                origin_uri = repo.origins[0]
                ret_uri = None
                if isinstance(origin_uri, str):
                        if len(origin_uri) > 0:
                                ret_uri = origin_uri.strip("/")
                elif isinstance(origin_uri, publisher.RepositoryURI):
                        uri = origin_uri.uri
                        if uri != None and len(uri) > 0:
                                ret_uri = uri.strip("/")
                return ret_uri


        def __do_api_search(self, search_all = True):
                self.__set_search_start()
                gobject.idle_add(self.update_statusbar)
                self.search_time_sec = 0
                text = self.w_searchentry.get_text()
                # Here we call the search API to get the results
                searches = []
                servers = []
                result = []
                pargs = []
                search_str = SEARCH_STR_FORMAT % text
                pargs.append(search_str)
                if search_all:
                        self.search_all_pub_being_searched = _("All Publishers")
                        servers = None
                        try:
                                pref_pub = self.api_o.get_preferred_publisher()
                                pub_prefix = pref_pub.prefix
                        except api_errors.ApiException, ex:
                                err = str(ex)
                                gobject.idle_add(self.error_occurred, err,
                                    None, gtk.MESSAGE_INFO)
                                gobject.idle_add(self.unset_busy_cursor)
                                return
                else:
                        pub_prefix = self.__get_selected_publisher()
                        try:
                                if pub_prefix != None:
                                        pub = self.api_o.get_publisher(prefix=pub_prefix)
                                else:
                                        pub = self.api_o.get_preferred_publisher()
                        except api_errors.ApiException, ex:
                                err = str(ex)
                                gobject.idle_add(self.error_occurred, err,
                                    None, gtk.MESSAGE_INFO)
                                gobject.idle_add(self.unset_busy_cursor)
                                return
                        origin_uri = self.__get_origin_uri(pub.selected_repository)
                        servers.append({"origin": origin_uri})
                        self.search_all_pub_being_searched = \
                                self.__get_publisher_display_name_from_prefix(pub.prefix)
                if debug:
                        print "Search: pargs %s servers: %s" % (pargs, servers)

                #TBD If we ever search just Installed pkgs should allow for a local search
                case_sensitive = False
                return_actions = True

                last_name = ""
                # Sorting results by Name gives best overall appearance and flow
                sort_col = enumerations.NAME_COLUMN
                try:
                        searches.append(self.api_o.remote_search(
                            [api.Query(" ".join(pargs), case_sensitive, return_actions)],
                            servers=servers))
                        if debug:
                                print "Search Args: %s : cs: %s : retact: %s" % \
                                        ("".join(pargs), case_sensitive, return_actions)
                        for query_num, pub, (v, return_type, tmp) in \
                            itertools.chain(*searches):
                                if v < 1 or return_type != api.Query.RETURN_PACKAGES:
                                        self.__process_after_search_failure()
                                        return

                                active_pub = None
                                if pub is not None \
                                    and "prefix" in pub:
                                        active_pub = pub["prefix"]
                                name = fmri.PkgFmri(str(tmp)).get_name()
                                if last_name != name:
                                        if debug:
                                                print "Result Name: %s (%s)" \
                                                    % (name, active_pub)
                                        a_res = name, active_pub
                                        result.append(a_res)
                                        #Ignore Status when fetching
                                        application_list = \
                                                self.__get_min_list_from_search(result)
                                        self.in_setup = True
                                        gobject.idle_add(self.__init_tree_views, 
                                            application_list, None, None, None, None,
                                            sort_col)
                                last_name = name
                                self.pylintstub = query_num
                except api_errors.ProblematicSearchServers, ex:
                        self.__process_api_search_error(ex)
                        gobject.idle_add(self.__handle_api_search_error)
                        if len(result) == 0:
                                if search_all:
                                        self.__process_after_search_with_zero_results(
                                                _("All Publishers"), text)
                                else:
                                        self.__process_after_search_with_zero_results(
                                                pub_prefix, text)
                                return
                except api_errors.CanceledException:
                        self.__reset_search_start()
                        gobject.idle_add(self.unset_busy_cursor)
                        gobject.idle_add(self.__process_after_cancel)
                        return
                except api_errors.ImageLockedError, ex:
                        err = str(ex)
                        gobject.idle_add(self.error_occurred, err,
                                None, gtk.MESSAGE_INFO)
                        self.__process_after_search_failure()
                        return
                except Exception, aex:
                        err = str(aex)
                        logger.error(err)
                        gui_misc.notify_log_error(self)
                        self.__process_after_search_failure()
                        return
                if debug:
                        print "Number of search results:", len(result)
                if len(result) == 0:
                        if debug:
                                print "No search results"
                        if search_all:
                                self.__process_after_search_with_zero_results(
                                        _("All Publishers"), text)
                        else:
                                self.__process_after_search_with_zero_results(
                                        pub_prefix, text)
                        return
                #Now fetch full result set with Status
                if self.exiting:
                        return
                self.in_setup = True
                if debug_perf:
                        print "Time for search:", time.time() - self.search_start
                application_list = self.__get_full_list_from_search(result)
                gobject.idle_add(self.__add_recent_search, text, pub_prefix,
                    application_list)
                if self.search_start > 0:
                        self.search_time_sec = int(time.time() - self.search_start)
                        if debug:
                                print "Search time: %d (sec)" % self.search_time_sec
                self.__reset_search_start()
                gobject.idle_add(self.__init_tree_views, application_list, None, None, \
                    None, None, sort_col)
                if self.w_filter_combobox.get_active() == enumerations.FILTER_ALL:
                        return

                gobject.idle_add(self.__check_zero_results_afterfilter, text,
                    len(application_list))

        def __check_zero_results_afterfilter(self, text, num):
                if self.length_visible_list != 0:
                        return
                self.__setup_search_zero_filtered_results_page(text, num)
                self.update_statusbar()

        def __set_search_start(self):
                self.search_start = time.time()
                
        def __reset_search_start(self):
                self.search_start = 0
                
        def __process_after_search_with_zero_results(self, pub, text):
                if self.search_start > 0:
                        self.search_time_sec = int(time.time() - self.search_start)
                self.__reset_search_start()
                gobject.idle_add(self.__setup_search_zero_results_page, pub, text)
                self.in_setup = True
                application_list = self.__get_new_application_liststore()
                gobject.idle_add(self.__set_empty_details_panel)
                gobject.idle_add(self.__init_tree_views, application_list, None, None)

        def __get_publisher_display_name_from_prefix(self, prefix):
                if self.pubs_display_name.has_key(prefix):
                        return self.pubs_display_name[prefix]
                else:
                        return prefix

        def __get_publisher_name_from_prefix(self, prefix):
                if self.pubs_info.has_key(prefix):
                        item  = self.pubs_info[prefix]
                else:
                        return prefix
                alias = item[1]
                if alias != None and len(alias) > 0:
                        return alias
                else:
                        return prefix 

        def __get_min_list_from_search(self, search_result):
                application_list = self.__get_new_application_liststore()
                for name, pub in search_result:
                        pub_name = self.__get_publisher_name_from_prefix(pub)
                        application_list.append(
                            [False, None, name, '...', api.PackageInfo.KNOWN, None, 
                            self.__get_pkg_stem(name, pub), None, True, None, 
                            pub_name, pub])
                return application_list

        def __get_full_list_from_search(self, search_result):
                application_list = self.__get_new_application_liststore()
                self.__add_pkgs_to_list_from_search(search_result,
                    application_list)
                return application_list

        def __add_pkgs_to_list_from_search(self, search_result,
            application_list):
                local_results = self.__get_info_for_search_results(search_result)
                remote_results = self.__get_info_for_search_results(search_result,
                    local_results)
                self.__add_pkgs_to_lists_from_info(local_results, 
                    remote_results, application_list)

        def __get_info_for_search_results(self, search_result, local_results = None):
                pargs = []
                results = []
                local_info = local_results == None
                for name, pub in search_result:
                        found = False
                        if local_results:
                                for result in local_results:
                                        if (name == result.pkg_stem and
                                            pub == result.publisher):
                                                found = True
                                                break
                                if not found: 
                                        pargs.append(self.__get_pkg_stem(name, pub))
                        else:
                                pargs.append(self.__get_pkg_stem(name, pub))

                try:
                        try:
                                res = self.api_o.info(pargs, 
                                          local_info, frozenset(
                                          [api.PackageInfo.IDENTITY, 
                                          api.PackageInfo.STATE, 
                                          api.PackageInfo.SUMMARY]))
                                results = res.get(0)
                        except api_errors.TransportError, tpex:
                                err = str(tpex)
                                logger.error(err)
                                gui_misc.notify_log_error(self)
                        except api_errors.InvalidDepotResponseException, idex:
                                err = str(idex)
                                logger.error(err)
                                gui_misc.notify_log_error(self)
                        except api_errors.ImageLockedError, ex:
                                err = str(ex)
                                logger.error(err)
                                gui_misc.notify_log_error(self)
                        except Exception, ex:
                                err = str(ex)
                                gobject.idle_add(self.error_occurred, err)
                finally:
                        return results

        def __application_refilter(self):
                ''' Disconnecting the model from the treeview improves
                performance when assistive technologies are enabled'''
                if self.in_setup:
                        return
                self.application_refilter_id = 0
                self.application_refilter_idle_id = 0
                model = self.w_application_treeview.get_model()
                self.w_application_treeview.set_model(None)
                app_id, order = self.application_list_sort.get_sort_column_id()
                self.application_list_sort.reset_default_sort_func()
                self.application_list_filter.refilter()
                if app_id != None:
                        self.application_list_sort.set_sort_column_id(app_id, order)
                if model != None:
                        self.w_application_treeview.set_model(model)
                self.application_treeview_initialized = True
                self.application_treeview_range = None
                if self.visible_status_id == 0:
                        self.visible_status_id = gobject.idle_add(
                            self.__set_visible_status)
                self.categories_treeview_initialized = True
                self.categories_treeview_range = None
                len_filtered_list = len(self.application_list_filter)
                if len_filtered_list > 0 and \
                        self.length_visible_list != len_filtered_list:
                        self.update_statusbar()
                self.__set_empty_details_panel()
                self.__enable_disable_selection_menus()
                self.__enable_disable_install_remove()
                if not self.in_search_mode and self.length_visible_list > 0 and \
                        len_filtered_list == 0 and \
                        self.w_filter_combobox.get_active() != \
                        (enumerations.FILTER_SELECTED):
                        self.__setup_zero_filtered_results_page()
                        self.update_statusbar()
                return False

        def __on_edit_paste(self, widget):
                self.w_searchentry.paste_clipboard()

        def __on_delete(self, widget):
                bounds = self.w_searchentry.get_selection_bounds()
                self.w_searchentry.delete_text(bounds[0], bounds[1])
                return

        def __on_copy(self, widget):
                focus_widget = self.w_main_window.get_focus()
                if focus_widget == self.w_searchentry:
                        self.w_searchentry.copy_clipboard()
                        self.w_paste_menuitem.set_sensitive(True)
                elif self.__is_a_textview(focus_widget):
                        focus_widget.get_buffer().copy_clipboard(
                            self.w_main_clipboard)

        def __on_cut(self, widget):
                self.w_searchentry.cut_clipboard()
                self.w_paste_menuitem.set_sensitive(True)

        def __on_goto_list_clicked(self, widget):
                if self.w_main_view_notebook.get_current_page() == NOTEBOOK_START_PAGE:
                        if self.view:
                                self.view.grab_focus()
                else:
                        self.__set_main_view_package_list()
                        self.w_application_treeview.grab_focus()

        def __on_edit_search_clicked(self, widget):
                self.w_searchentry.grab_focus()

        def __on_clear_search(self, widget, icon_pos=0, event=None):
                self.w_searchentry.set_text("")
                self.__clear_search_results()

        def __clear_search_results(self):
                # Only clear out search results
                if self.in_search_mode or self.is_all_publishers:
                        self.__clear_before_search()
                        self.__update_statusbar_message(_("Search cleared"))
                if self.is_all_publishers:
                        if self.w_main_view_notebook.get_current_page() \
                                != NOTEBOOK_START_PAGE:
                                gobject.idle_add(self.__setup_search_all_page)
                else:
                        self.__unset_search(self.in_search_mode)
                return

        def __on_progress_cancel_clicked(self, widget):
                Thread(target = self.api_o.cancel, args = ()).start()

        def __on_startpage(self, widget):
                self.__load_startpage()
                self.w_main_view_notebook.set_current_page(NOTEBOOK_START_PAGE)

        def __on_notebook_change(self, widget, event, pagenum):
                if (pagenum == INFO_NOTEBOOK_LICENSE_PAGE and 
                    not self.showing_empty_details):
                        licbuffer = self.w_license_textview.get_buffer()
                        leg_txt = _("Fetching legal information...")
                        licbuffer.set_text(leg_txt)
                        if self.show_licenses_id != 0:
                                gobject.source_remove(self.show_licenses_id)
                                self.show_licenses_id = 0
                        self.last_show_licenses_id = self.show_licenses_id = \
                            gobject.timeout_add(SHOW_LICENSE_DELAY,
                                self.__show_licenses)

        def __is_a_textview(self, widget):
                if (widget == self.w_generalinfo_textview or
                    widget == self.w_installedfiles_textview or
                    widget == self.w_dependencies_textview or
                    widget == self.w_license_textview):
                        return True
                else:
                        return False

        def __toggle_select_all(self, select_all=True):
                focus_widget = self.w_main_window.get_focus()
                if self.__is_a_textview(focus_widget):
                        focus_widget.emit('select-all', select_all)
                        self.w_selectall_menuitem.set_sensitive(False)
                        self.w_deselect_menuitem.set_sensitive(True)
                        self.unset_busy_cursor()
                        return
                elif focus_widget == self.w_searchentry:
                        if select_all:
                                focus_widget.select_region(0, -1)
                        else:
                                focus_widget.select_region(0, 0)
                        self.w_selectall_menuitem.set_sensitive(False)
                        self.w_deselect_menuitem.set_sensitive(True)
                        self.unset_busy_cursor()
                        return

                sort_filt_model = \
                    self.w_application_treeview.get_model() #gtk.TreeModelSort
                filt_model = sort_filt_model.get_model() #gtk.TreeModelFilter
                model = filt_model.get_model() #gtk.ListStore
                iter_next = sort_filt_model.get_iter_first()
                list_of_paths = []
                while iter_next != None:
                        sorted_path = sort_filt_model.get_path(iter_next)
                        filtered_path = \
                            sort_filt_model.convert_path_to_child_path(sorted_path)
                        path = filt_model.convert_path_to_child_path(filtered_path)
                        if select_all:
                                list_of_paths.append(path)
                        else:
                                filtered_iter = \
                                        sort_filt_model.convert_iter_to_child_iter(None,
                                            iter_next)
                                app_iter = filt_model.convert_iter_to_child_iter(
                                    filtered_iter)
                                if model.get_value(app_iter, enumerations.MARK_COLUMN):
                                        list_of_paths.append(path)
                        iter_next = sort_filt_model.iter_next(iter_next)
                for path in list_of_paths:
                        itr = model.get_iter(path)
                        mark_value = model.get_value(itr, enumerations.MARK_COLUMN)
                        if select_all and not mark_value:
                                model.set_value(itr, enumerations.MARK_COLUMN, True)
                                pkg_stem = model.get_value(itr,
                                    enumerations.STEM_COLUMN)
                                pkg_status = model.get_value(itr,
                                    enumerations.STATUS_COLUMN)
                                pkg_publisher = model.get_value(itr,
                                    enumerations.PUBLISHER_PREFIX_COLUMN)
                                pkg_description = model.get_value(itr,
                                    enumerations.DESCRIPTION_COLUMN)
                                pkg_name = model.get_value(itr,
                                    enumerations.NAME_COLUMN)
                                self.__add_pkg_stem_to_list(pkg_stem, pkg_name, 
                                    pkg_status, pkg_publisher, pkg_description)
                        elif not select_all and mark_value:
                                model.set_value(itr, enumerations.MARK_COLUMN, False)
                                pkg_stem = model.get_value(itr,
                                    enumerations.STEM_COLUMN)
                                self.__remove_pkg_stem_from_list(pkg_stem)
                
                self.w_selectall_menuitem.set_sensitive(not select_all)
                self.w_deselect_menuitem.set_sensitive(select_all)
                self.__enable_disable_selection_menus()
                self.update_statusbar()
                self.__enable_disable_install_remove()
                self.unset_busy_cursor()
                        
        def __on_select_all(self, widget):
                self.set_busy_cursor()
                gobject.idle_add(self.__toggle_select_all, True)
                return

        def __on_select_updates(self, widget):
                sort_filt_model = \
                    self.w_application_treeview.get_model() #gtk.TreeModelSort
                filt_model = sort_filt_model.get_model() #gtk.TreeModelFilter
                model = filt_model.get_model() #gtk.ListStore
                iter_next = sort_filt_model.get_iter_first()
                list_of_paths = []
                while iter_next != None:
                        sorted_path = sort_filt_model.get_path(iter_next)
                        filtered_iter = sort_filt_model.convert_iter_to_child_iter(None, \
                            iter_next)
                        app_iter = filt_model.convert_iter_to_child_iter(filtered_iter)

                        filtered_path = \
                            sort_filt_model.convert_path_to_child_path(sorted_path)
                        path = filt_model.convert_path_to_child_path(filtered_path)
                        if model.get_value(app_iter, \
                            enumerations.STATUS_COLUMN) == api.PackageInfo.UPGRADABLE:
                                list_of_paths.append(path)
                        iter_next = sort_filt_model.iter_next(iter_next)
                for path in list_of_paths:
                        itr = model.get_iter(path)
                        model.set_value(itr, enumerations.MARK_COLUMN, True)
                        pkg_stem = model.get_value(itr, enumerations.STEM_COLUMN)
                        pkg_status = model.get_value(itr, enumerations.STATUS_COLUMN)
                        pkg_publisher = model.get_value(itr,
                            enumerations.PUBLISHER_PREFIX_COLUMN)
                        pkg_description = model.get_value(itr,
                            enumerations.DESCRIPTION_COLUMN)
                        pkg_name = model.get_value(itr,
                            enumerations.NAME_COLUMN)
                        self.__add_pkg_stem_to_list(pkg_stem, pkg_name, pkg_status,
                            pkg_publisher, pkg_description)
                self.__enable_disable_selection_menus()
                self.update_statusbar()
                self.__enable_disable_install_remove()

        def __on_deselect(self, widget):
                self.set_busy_cursor()
                gobject.idle_add(self.__toggle_select_all, False)
                return

        def __save_state_changed(self, client, connection_id, entry, arguments):
                self.save_state = entry.get_value().get_bool()

        def __show_image_update_changed(self, client, connection_id, entry, arguments):
                self.show_image_update = entry.get_value().get_bool()

        def __show_install_changed(self, client, connection_id, entry, arguments):
                self.show_install = entry.get_value().get_bool()

        def __show_remove_changed(self, client, connection_id, entry, arguments):
                self.show_remove = entry.get_value().get_bool()

        def __on_preferences(self, widget):
                self.w_startpage_checkbutton.set_active(self.show_startpage)
                self.w_exit_checkbutton.set_active(self.save_state)
                self.w_confirm_updateall_checkbutton.set_active(self.show_image_update)
                self.w_confirm_install_checkbutton.set_active(self.show_install)
                self.w_confirm_remove_checkbutton.set_active(self.show_remove)
                self.w_preferencesdialog.show()

        def __on_preferencesclose_clicked(self, widget):
                self.w_preferencesdialog.hide()

        @staticmethod
        def __on_preferenceshelp_clicked(widget):
                gui_misc.display_help("pkg-mgr-prefs")

        def __on_startpage_checkbutton_toggled(self, widget):
                self.show_startpage = self.w_startpage_checkbutton.get_active()
                try:
                        self.client.set_bool(SHOW_STARTPAGE_PREFERENCES,
                            self.show_startpage)
                except GError:
                        pass

        def __on_exit_checkbutton_toggled(self, widget):
                self.save_state = self.w_exit_checkbutton.get_active()
                try:
                        self.client.set_bool(SAVE_STATE_PREFERENCES,
                            self.save_state)
                except GError:
                        pass

        def on_confirm_updateall_checkbutton_toggled(self, widget, reverse = False):
                active = widget.get_active()
                if reverse:
                        active = not active
                self.show_image_update = active
                try:
                        self.client.set_bool(SHOW_IMAGE_UPDATE_CONFIRMATION,
                            self.show_image_update)
                except GError:
                        pass

        def on_confirm_install_checkbutton_toggled(self, widget, reverse = False):
                active = widget.get_active()
                if reverse:
                        active = not active
                self.show_install = active
                try:
                        self.client.set_bool(SHOW_INSTALL_CONFIRMATION,
                            self.show_install)
                except GError:
                        pass

        def on_confirm_remove_checkbutton_toggled(self, widget, reverse = False):
                active = widget.get_active()
                if reverse:
                        active = not active
                self.show_remove = active
                try:
                        self.client.set_bool(SHOW_REMOVE_CONFIRMATION,
                            self.show_remove)
                except GError:
                        pass

        def __on_api_search_checkbox_toggled(self, widget):
                active = self.api_search_checkbox.get_active()
                if len(self.current_repos_with_search_errors) > 0:
                        if active:
                                for pub, err_type, err_str in \
                                        self.current_repos_with_search_errors:
                                        if pub not in self.gconf_not_show_repos:
                                                self.gconf_not_show_repos += pub + ","
                                        self.pylintstub = err_type
                                        self.pylintstub = err_str
                        else:
                                for pub, err_type, err_str in \
                                        self.current_repos_with_search_errors:
                                        self.gconf_not_show_repos = \
                                            self.gconf_not_show_repos.replace(
                                            pub + ",", "")
                        try:
                                self.client.set_string(API_SEARCH_ERROR_PREFERENCES,
                                    self.gconf_not_show_repos)
                        except GError:
                                pass

        def __on_searchentry_focus_in(self, widget, event):
                self.__set_search_text_mode(enumerations.SEARCH_STYLE_NORMAL)
                if self.w_main_clipboard.wait_is_text_available():
                        self.w_paste_menuitem.set_sensitive(True)
                char_count = widget.get_text_length()
                if char_count > 0:
                        self.w_selectall_menuitem.set_sensitive(True)
                else:
                        self.w_selectall_menuitem.set_sensitive(False)
                bounds = widget.get_selection_bounds()
                if bounds:
                        offset1 = bounds[0]
                        offset2 = bounds[1] 
                        if abs(offset2 - offset1) == char_count:
                                self.w_selectall_menuitem.set_sensitive(False)
                        self.w_deselect_menuitem.set_sensitive(True)
                        self.w_copy_menuitem.set_sensitive(True)
                else:
                        self.w_deselect_menuitem.set_sensitive(False)

        def __on_searchentry_focus_out(self, widget, event):
                if self.w_searchentry.get_text_length() == 0:
                        self.__set_search_text_mode(enumerations.SEARCH_STYLE_PROMPT)
                self.w_paste_menuitem.set_sensitive(False)
                self.__enable_disable_select_all()
                self.__enable_disable_deselect()
                self.w_cut_menuitem.set_sensitive(False)
                self.w_copy_menuitem.set_sensitive(False)
                self.w_delete_menuitem.set_sensitive(False)
                return False

        def __on_searchentry_selection(self, widget, pspec):
                self.__enable_disable_entry_selection(widget)

        def __enable_disable_entry_selection(self, widget):
                char_count = widget.get_text_length()
                bounds = widget.get_selection_bounds()
                if bounds:
                        #enable selection functions
                        self.w_cut_menuitem.set_sensitive(True)
                        self.w_copy_menuitem.set_sensitive(True)
                        self.w_delete_menuitem.set_sensitive(True)
                        if char_count == abs(bounds[1] - bounds[0]):
                                self.w_selectall_menuitem.set_sensitive(False)
                        else:
                                self.w_selectall_menuitem.set_sensitive(True)
                        self.w_deselect_menuitem.set_sensitive(True)
                else:
                        self.w_cut_menuitem.set_sensitive(False)
                        self.w_copy_menuitem.set_sensitive(False)
                        self.w_delete_menuitem.set_sensitive(False)
                        self.w_deselect_menuitem.set_sensitive(False)
                        if char_count == 0:
                                self.w_selectall_menuitem.set_sensitive(False)
                        else:
                                self.w_selectall_menuitem.set_sensitive(True)

        def __refilter_on_idle(self):
                if self.application_refilter_id != 0:
                        gobject.source_remove(self.application_refilter_id)
                        self.application_refilter_id = 0
                if self.application_refilter_idle_id == 0:
                        self.application_refilter_idle_id = gobject.idle_add(
                            self.__application_refilter)

        def __on_category_focus_in(self, widget, event, user):
                self.__on_category_row_activated(None, None, None, user)

        def __on_category_row_activated(self, view, path, col, user):
                '''This function is for handling category double click activations'''
                # Activated sub node in Recent Searches category
                if self.in_recent_search:
                        return
                # User activated Recent Searches Top Level category
                model = self.w_categories_treeview.get_model()
                if model != None and self.recent_searches_cat_iter:
                        rs_path = model.get_path(self.recent_searches_cat_iter)
                        selection, curr_path = self.__get_selection_and_category_path()
                        self.pylintstub = selection
                        if curr_path == rs_path:
                                self.__setup_recent_search_page()
                                return
                if self.category_list == None:
                        self.__set_main_view_package_list()
                        return
                if self.w_filter_combobox.get_model():
                        self.w_filter_combobox.set_active(
                            self.saved_filter_combobox_active)
                if self.in_search_mode or self.is_all_publishers:
                        self.__unset_search(True)
                        return
                self.__set_main_view_package_list()
                self.set_busy_cursor()
                self.__refilter_on_idle()

        def __set_main_view_package_list(self, show_list=True):
                # Only switch from Start Page View to List view if we are not in startup
                if self.in_startpage_startup:
                        return
                if show_list:
                        self.w_main_view_notebook.set_current_page(
                                NOTEBOOK_PACKAGE_LIST_PAGE)
                else:
                        self.w_main_view_notebook.set_current_page(
                                NOTEBOOK_START_PAGE)

        def __on_categoriestreeview_row_collapsed(self, treeview, itr, path, data):
                self.w_categories_treeview.set_cursor(path)
                self.__save_expanded_path(path, False)
                self.__save_active_category(path)
                
        def __on_categoriestreeview_row_expanded(self, treeview, itr, path, data):
                if self.in_setup and not self.first_run:
                        return
                self.w_categories_treeview.set_cursor(path)
                self.__save_expanded_path(path, True)
                self.__save_active_category(path)

        def __on_categoriestreeview_button_press_event(self, treeview, event, data):
                if event.type != gtk.gdk.BUTTON_PRESS:
                        return 1
                x = int(event.x)
                y = int(event.y)
                pthinfo = treeview.get_path_at_pos(x, y)
                if pthinfo is not None:
                        path = pthinfo[0]
                        cellx = pthinfo[2]
                        #Clicking on row toggle icon just select the path
                        if cellx <= CATEGORY_TOGGLE_ICON_WIDTH:
                                self.w_categories_treeview.set_cursor(path)
                                self.w_categories_treeview.scroll_to_cell(path)
                                return
                        #Collapse expand Top level Sections only
                        tree_view = self.w_categories_treeview
                        if path != 0 and len(path) == 1:
                                if tree_view.row_expanded(path) and \
                                        self.w_main_view_notebook.get_current_page() == \
                                        NOTEBOOK_START_PAGE:
                                        self.__on_category_selection_changed(
                                            tree_view.get_selection(), None)
                                elif tree_view.row_expanded(path):
                                        selection, sel_path = \
                                                self.__get_selection_and_category_path()
                                        if selection and sel_path == path:
                                                tree_view.collapse_row(path)
                                else:
                                        tree_view.expand_row(path, False)
                                self.__save_active_category(path)

        @staticmethod
        def __categoriestreeview_compare_func(model, column, key, itr):
                value = model.get_value(itr, column)
                if not value:
                        return True

                try:
                        value = re.sub(REGEX_STRIP_MARKUP, "", value)
                        value = re.sub(REGEX_STRIP_RESULT, "", value)
                        match = re.match(re.escape(key), re.escape(value), re.IGNORECASE)
                except (TypeError, re.error):
                        return True

                return match is None

        def __in_recent_searches(self, path):
                if not path or len(path) == 0:
                        return False
                model = self.w_categories_treeview.get_model()
                if model == None:
                        return False
                rs_path = model.get_path(self.recent_searches_cat_iter)
                if rs_path and len(rs_path) > 0 and path[0] == rs_path[0]:
                        return True
                return False
                
        def __save_expanded_path(self, path, expanded):
                if not path or len(path) == 0:
                        return                
                self.category_expanded_paths[(self.last_visible_publisher, path)] = \
                        expanded

        def __save_active_category(self, path):
                if self.first_run or not path or len(path) == 0 or \
                        self.__in_recent_searches(path):
                        return                
                self.category_active_paths[self.last_visible_publisher] = path
                self.saved_section_active = path[0]

        def __on_category_selection_changed(self, selection, widget):
                '''This function is for handling category selection changes'''
                if self.in_setup:
                        return
                model, itr = selection.get_selected()
                if not itr:
                        return

                path = model.get_path(itr)
                sel_category = model[path]
                if sel_category[enumerations.CATEGORY_ID] == RECENT_SEARCH_ID:
                        if not self.adding_recent_search:
                                self.__setup_recent_search_page()
                                if not self.is_all_publishers:
                                        self.__save_setup_before_search(
                                            single_search=True)
                                self.in_search_mode = True
                                self.in_recent_search = True
                        else:
                                self.__set_main_view_package_list()
                        return
                elif sel_category[enumerations.CATEGORY_ID] > RECENT_SEARCH_ID:
                        self.__restore_recent_search(sel_category)
                        return
                self.__save_active_category(path)
                if self.in_search_mode or self.is_all_publishers:
                        #Required for A11Y support because focus event not triggered
                        #when A11Y enabled and user clicks on Category after Search
                        self.__unset_search(True)
                        self.__set_main_view_package_list()
                        return
                if self.saved_filter_combobox_active != None:
                        self.w_filter_combobox.set_active(
                            self.saved_filter_combobox_active)
                self.__set_main_view_package_list()

                self.set_busy_cursor()
                self.__refilter_on_idle()

        def __on_applicationtreeview_query_tooltip(self, treeview, x, y, 
            keyboard_mode, tooltip):
                treex, treey = treeview.convert_widget_to_bin_window_coords(x, y)
                info = treeview.get_path_at_pos(treex, treey)
                if not info:
                        return False
                return self.__show_app_column_tooltip(treeview, _("Status"), 
                    info[0], info[1], tooltip)

        @staticmethod
        def __show_app_column_tooltip(treeview, col_title, path, col, tooltip):
                tip = ""
                if path and col:
                        title = col.get_title() 
                        if title != col_title:
                                return False
                        row = list(treeview.get_model()[path])
                        if row:
                                status = row[enumerations.STATUS_COLUMN]
                                if status == api.PackageInfo.INSTALLED:
                                        tip = _("Installed")
                                elif status == api.PackageInfo.KNOWN:
                                        tip = _("Not installed")
                                elif status == api.PackageInfo.UPGRADABLE:
                                        tip = _("Updates Available")

                if tip != "":
                        treeview.set_tooltip_cell(tooltip, path, col, None)
                        tooltip.set_text(tip)
                        return True
                else:
                        return False

        def __on_applicationtreeview_button_and_key_events(self, treeview, event):
                if event.type == gtk.gdk.KEY_PRESS:
                        keyname = gtk.gdk.keyval_name(event.keyval)
                        if event.state == gtk.gdk.CONTROL_MASK and keyname == "F1":
                                return True #Disable Tooltip popup using Ctrl-F1

                        if not(event.state == gtk.gdk.SHIFT_MASK and keyname == "F10"):
                                return

                        selection = self.w_application_treeview.get_selection()
                        if not selection:
                                return
                        model, itr = selection.get_selected()
                        if not model or not itr:
                                return
                        curr_time = event.time
                        path = model.get_path(itr)
                        col = treeview.get_column(1) # NAME_COLUMN
                        treeview.set_cursor(path, col, 0)

                        #Calculate popup coordinates
                        treecell_rect = treeview.get_cell_area(path, col)
                        rx, ry = treeview.tree_to_widget_coords(treecell_rect[0],
                            treecell_rect[1])
                        winx, winy  = treeview.get_bin_window().get_origin()
                        winx += rx
                        winy += ry
                        popup_position = (winx, winy)
                        self.w_package_menu.popup( None, None,
                            self.__position_package_popup, gtk.gdk.KEY_PRESS,
                            curr_time, popup_position)
                        return True

                if event.type != gtk.gdk.BUTTON_PRESS and event.type != 5:
                        return
                x = int(event.x)
                y = int(event.y)
                pthinfo = treeview.get_path_at_pos(x, y)
                if pthinfo == None:
                        return                
                path = pthinfo[0]
                col = pthinfo[1]

                #Double click
                if event.type == GDK_2BUTTON_PRESS:
                        self.__active_pane_toggle(None, path, treeview.get_model())
                        return                          
                if event.button == GDK_RIGHT_BUTTON: #Right Click
                        curr_time = event.time
                        treeview.grab_focus()
                        treeview.set_cursor( path, col, 0)
                        self.w_package_menu.popup( None, None, None, event.button,
                            curr_time)
                        return

        @staticmethod
        def __applicationtreeview_compare_func(model, column, key, itr):
                value = model.get_value(itr, enumerations.NAME_COLUMN)
                if not value:
                        return True

                value = value.lower()
                return not value.startswith(key.lower())

        @staticmethod
        def __position_package_popup(menu, position):
                #Positions popup relative to the top left corner of the currently
                #selected row's Name cell
                x, y = position

                #Offset x by 10 and y by 15 so underlying name is visible
                return (x+10, y+15, True)

        def __process_package_selection(self):
                model, itr = self.package_selection.get_selected()
                if self.show_info_id != 0:
                        gobject.source_remove(self.show_info_id)
                        self.show_info_id = 0
                if itr:
                        self.selected_pkgstem = \
                               model.get_value(itr, enumerations.STEM_COLUMN)
                        pkg = model.get_value(itr, enumerations.FMRI_COLUMN)
                        gobject.idle_add(self.__show_fetching_package_info, pkg)
                        self.showing_empty_details = False
                        self.last_show_info_id = self.show_info_id = \
                            gobject.timeout_add(SHOW_INFO_DELAY,
                                self.__show_info, model, model.get_path(itr))
                        if (self.w_info_notebook.get_current_page() == 
                            INFO_NOTEBOOK_LICENSE_PAGE):
                                self.__on_notebook_change(None, None, 
                                    INFO_NOTEBOOK_LICENSE_PAGE)
                        self.w_version_info_menuitem.set_sensitive(True)
                else:
                        self.selected_model = None
                        self.selected_path = None
                        self.selected_pkgstem = None
                        self.w_version_info_menuitem.set_sensitive(False)

        def __on_package_selection_changed(self, selection, widget):
                '''This function is for handling package selection changes'''
                if self.in_setup:
                        return
                self.__process_package_selection()

        def __on_filtercombobox_changed(self, widget):
                '''On filter combobox changed'''
                if self.first_run or self.in_setup:
                        return
                active = self.w_filter_combobox.get_active()
                if active != enumerations.FILTER_SELECTED:
                        self.saved_filter_combobox_active = active
                self.__set_main_view_package_list()
                self.set_busy_cursor()
                self.__refilter_on_idle()

        def __unset_search(self, same_repo):
                self.w_infosearch_frame.hide()
                self.__update_tooltips()
                self.in_search_mode = False
                self.in_recent_search = False
                self.is_all_publishers = False
                if same_repo:
                        self.__restore_setup_for_browse()

        def __on_repositorycombobox_changed(self, widget):
                '''On repository combobox changed'''
                if debug_perf:
                        print "Start change publisher", time.time()
                if self.same_publisher_on_setup:
                        if self.is_all_publishers:
                                self.__clear_search_results()
                        self.same_publisher_on_setup = False
                        self.unset_busy_cursor()
                        if self.in_setup:
                                self.in_setup = False
                        return
                selected_publisher = self.__get_selected_publisher()
                index =  self.w_repository_combobox.get_active()
                if self.is_all_publishers:
                        if index == self.repo_combobox_all_pubs_index:
                                return
                        if index == self.repo_combobox_add_index:
                                self.w_repository_combobox.set_active(
                                    self.repo_combobox_all_pubs_index)
                                self.__on_file_add_publisher(None)
                                return
                        same_repo = self.saved_repository_combobox_active == index
                        self.__unset_search(same_repo)
                        if same_repo:
                                self.__set_searchentry_to_prompt()
                                return
                        self.w_repository_combobox.set_active(index)
                        selected_publisher = self.__get_selected_publisher()
                if selected_publisher == self.last_visible_publisher:
                        return
                if index == self.repo_combobox_all_pubs_index:
                        self.__set_all_publishers_mode()
                        return
                        
                if index == self.repo_combobox_add_index:
                        index = self.__get_publisher_combobox_index(
                            self.last_visible_publisher)
                        self.w_repository_combobox.set_active(index)
                        self.__on_file_add_publisher(None)
                        return
                if index == self.repo_combobox_all_pubs_installed_index:
                        self.w_filter_combobox.set_active(enumerations.FILTER_ALL)
                        self.is_all_publishers_installed = True
                else:
                        self.is_all_publishers_installed = False

                self.__do_set_publisher()

        def __do_set_publisher(self):
                self.cancelled = True
                self.in_setup = True
                self.set_busy_cursor()
                self.__set_empty_details_panel()
                if self.in_search_mode:
                        self.__unset_search(False)

                pub = [self.__get_selected_publisher(), ]
                self.set_section = self.initial_section
                self.__set_searchentry_to_prompt()
                self.__disconnect_models()
                Thread(target = self.__setup_publisher, args = [pub]).start()
                self.__set_main_view_package_list()

        def __get_selected_publisher(self):
                pub_iter = self.w_repository_combobox.get_active_iter()
                if pub_iter == None:
                        return None
                return self.repositories_list.get_value(pub_iter, \
                            enumerations.REPOSITORY_PREFIX)

        def __setup_publisher(self, publishers):
                self.saved_filter_combobox_active = self.initial_show_filter
                application_list, category_list , section_list = \
                    self.__get_application_categories_lists(publishers)
                self.__unset_saved()
                self.publisher_changed = True
                self.last_visible_publisher = self.__get_selected_publisher()
                self.saved_repository_combobox_active = \
                        self.w_repository_combobox.get_active()
                gobject.idle_add(self.__init_tree_views, application_list,
                    category_list, section_list)

        def __unset_saved(self):
                self.__save_application_list(None)
                self.saved_application_list_filter = None
                self.saved_application_list_sort = None
                self.saved_category_list = None
                self.saved_section_list = None

        def __refresh_for_publisher(self, pub):
                status_str = _("Refreshing package catalog information")
                gobject.idle_add(self.__update_statusbar_message,
                    status_str)
                if self.is_all_publishers_installed: 
                        self.__do_refresh()
                else:
                        self.__do_refresh(pubs=[pub])

        def __do_refresh(self, pubs=None, immediate=False):
                success = False
                try:
                        self.api_o.reset()
                        self.api_o.refresh(pubs=pubs, immediate=immediate)
                        success = True
                except api_errors.CatalogRefreshException, cre:
                        crerr = gui_misc.get_catalogrefresh_exception_msg(cre)
                        logger.error(crerr)
                        gui_misc.notify_log_error(self)
                except api_errors.TransportError, tpex:
                        err = str(tpex)
                        logger.error(err)
                        gui_misc.notify_log_error(self)
                except api_errors.InvalidDepotResponseException, idex:
                        err = str(idex)
                        logger.error(err)
                        gui_misc.notify_log_error(self)
                except api_errors.ApiException, ex:
                        err = str(ex)
                        gobject.idle_add(self.error_occurred, err,
                            None, gtk.MESSAGE_INFO)
                except Exception, ex:
                        err = str(ex)
                        gobject.idle_add(self.error_occurred, err,
                            None, gtk.MESSAGE_INFO)
                return success

        def __get_application_categories_lists(self, publishers):
                application_list = self.__get_new_application_liststore()
                category_list = self.__get_new_category_liststore()
                section_list = self.__get_new_section_liststore()
                for pub in publishers:
                        if debug_perf:
                                a = time.time()
                        self.__refresh_for_publisher(pub)
                        if debug_perf:
                                print "Time to refresh", time.time() - a
                                a = time.time()
                        self.__add_pkgs_to_lists_from_api(pub,
                            application_list, category_list, section_list)
                        if debug_perf:
                                b = time.time()
                                print "Time to add", b - a, b
                        category_list.prepend(None, [0, _('All'), _('All'), None,
                            None, True])

                return application_list, category_list, section_list

        def __add_install_update_pkgs_for_publishers(self, install_update,
            confirmation_list):
                for pub_name in self.selected_pkgs:
                        pub_display_name = self.__get_publisher_display_name_from_prefix(
                            pub_name)
                        pkgs = self.selected_pkgs.get(pub_name)
                        if not pkgs:
                                break
                        for pkg_stem in pkgs:
                                status = pkgs.get(pkg_stem)[0]
                                if status == api.PackageInfo.KNOWN or \
                                    status == api.PackageInfo.UPGRADABLE:
                                        install_update.append(pkg_stem)
                                        if self.show_install:
                                                desc = pkgs.get(pkg_stem)[1]
                                                pkg_name = pkgs.get(pkg_stem)[2]
                                                confirmation_list.append(
                                                    [pkg_name, pub_display_name,
                                                    desc, status])
                                                    
        def __on_log_dialog_delete_event(self, widget, event):
                self.__on_log_close_button_clicked(None)
                return True
                
        def __on_log_close_button_clicked(self, widget):
                self.w_view_log_dialog.hide()
                
        def __on_log_activate(self, widget):                                
                if self.error_logged:
                        self.error_logged = False
                        self.w_infosearch_frame.hide()
                textbuffer = self.w_log_errors_textview.get_buffer()
                textbuffer.set_text(_("Loading ..."))
                textbuffer = self.w_log_info_textview.get_buffer()
                textbuffer.set_text(_("Loading ..."))
                self.w_log_close_button.grab_focus()
                self.w_view_log_dialog.show()
                gobject.idle_add(self.__load_err_view_log)
                gobject.idle_add(self.__load_info_view_log)
                
        def __load_err_view_log(self):
                textbuffer = self.w_log_errors_textview.get_buffer()
                textbuffer.set_text("")
                textiter = textbuffer.get_end_iter()
                log_dir = gui_misc.get_log_dir()
                log_err_ext = gui_misc.get_log_error_ext()
                pm_err_log = os.path.join(log_dir, gui_misc.get_pm_name() + log_err_ext)
                wi_err_log = os.path.join(log_dir, gui_misc.get_wi_name() + log_err_ext)
                um_err_log = os.path.join(log_dir, gui_misc.get_um_name() + log_err_ext)

                self.__write_to_view_log(um_err_log, 
                    textbuffer, textiter, _("None: ") + gui_misc.get_um_name() + "\n")
                self.__write_to_view_log(wi_err_log, 
                    textbuffer, textiter, _("None: ") + gui_misc.get_wi_name() + "\n")
                self.__write_to_view_log(pm_err_log, 
                    textbuffer, textiter, _("None: ") + gui_misc.get_pm_name() + "\n")
                gobject.idle_add(self.w_log_errors_textview.scroll_to_iter, textiter,
                    0.0)
                    
        def __load_info_view_log(self):
                textbuffer = self.w_log_info_textview.get_buffer()
                textbuffer.set_text("")
                textiter = textbuffer.get_end_iter()
                log_dir = gui_misc.get_log_dir()
                log_info_ext = gui_misc.get_log_info_ext()
                pm_info_log = os.path.join(log_dir, gui_misc.get_pm_name() + log_info_ext)
                wi_info_log = os.path.join(log_dir, gui_misc.get_wi_name() + log_info_ext)
                um_info_log = os.path.join(log_dir, gui_misc.get_um_name() + log_info_ext)

                self.__write_to_view_log(um_info_log, 
                    textbuffer, textiter, _("None: ") + gui_misc.get_um_name() + "\n")
                self.__write_to_view_log(wi_info_log, 
                    textbuffer, textiter, _("None: ") + gui_misc.get_wi_name() + "\n")
                self.__write_to_view_log(pm_info_log, 
                    textbuffer, textiter, _("None: ") + gui_misc.get_pm_name() + "\n")
                gobject.idle_add(self.w_log_info_textview.scroll_to_iter, textiter, 0.0)

        @staticmethod
        def __write_to_view_log(path, textbuffer, textiter, nomessages):
                infile = None
                try:
                        infile = open(path, "r")
                except IOError:
                        textbuffer.insert_with_tags_by_name(textiter, nomessages, "bold")
                        return
                if infile == None:
                        textbuffer.insert_with_tags_by_name(textiter, nomessages, "bold")
                        return
                        
                lines = infile.readlines()
                if len(lines) == 0:
                        textbuffer.insert_with_tags_by_name(textiter, nomessages, "bold")
                        return                        
                for line in lines:
                        if re.match(REGEX_BOLD_MARKUP, line):
                                line = re.sub(REGEX_STRIP_MARKUP, "", line)
                                textbuffer.insert_with_tags_by_name(textiter, line,
                                    "bold")
                        else:
                                textbuffer.insert(textiter, line)
                try:
                        infile.close()
                except IOError:
                        pass
        
        def __on_version_info(self, widget):
                model, itr = self.package_selection.get_selected()
                if itr:
                        pkg_stem = model.get_value(itr, enumerations.STEM_COLUMN)
                        name = model.get_value(itr, enumerations.NAME_COLUMN)
                        self.set_busy_cursor()
                        Thread(target = self.__get_info, args = (pkg_stem, name)).start()

        def __get_info(self, pkg_stem, name):
                if not self.__do_api_reset():
                        return
                local_info = gui_misc.get_pkg_info(self, self.api_o, pkg_stem, True)
                remote_info = gui_misc.get_pkg_info(self, self.api_o, pkg_stem, False)
                if self.exiting:
                        return
                plan_pkg = None

                installed_only = False
                if local_info:
                        if gui_misc.same_pkg_versions(local_info, remote_info):
                                installed_only = True

                if not installed_only:
                        install_update_list = []
                        stuff_to_do = False
                        install_update_list.append(pkg_stem)
                        try:
                                stuff_to_do = self.api_o.plan_install(
                                    install_update_list,
                                    refresh_catalogs = False) 
                        except api_errors.ApiException, ex:
                                err = str(ex)
                                logger.error(err)
                                gobject.idle_add(gui_misc.notify_log_error, self)
                                gobject.idle_add(self.unset_busy_cursor)
                                return
                        if stuff_to_do:
                                plan_desc = self.api_o.describe()
                                if plan_desc == None:
                                        return
                                plan = plan_desc.get_changes()
                                plan_pkg = None
                                for pkg_plan in plan:
                                        if name == pkg_plan[1].pkg_stem:
                                                plan_pkg = pkg_plan[1]
                                                break
                                if plan_pkg == None:
                                        gobject.idle_add(self.unset_busy_cursor)
                                        return
                gobject.idle_add(self.__after_get_info, local_info, remote_info,
                    plan_pkg, name)
                return

        def __hide_pkg_version_details(self):
                self.w_info_expander.hide()
                self.w_version_info_dialog.set_size_request(-1, -1)
                
        def __after_get_info(self, local_info, remote_info, plan_pkg, name):
                if self.exiting:
                        return
                self.w_info_name_label.set_text(name)
                installable_fmt = \
                    _("%(version)s (Build %(build)s-%(branch)s)")
                installed_label = ""
                installable_label = ""
                installable_prefix_label = _("<b>Installable Version:</b>")
                
                if local_info:
                        # Installed
                        installable_prefix_label = _("<b>Upgradeable Version:</b>")
                        yes_text = _("Yes, %(version)s (Build %(build)s-%(branch)s)")
                        installed_label = yes_text % \
                            {"version": local_info.version,
                            "build": local_info.build_release,
                            "branch": local_info.branch}
                        if gui_misc.same_pkg_versions(local_info, remote_info):
                                # Installed and up to date
                                installable_label = \
                                    _("Installed package is up-to-date")
                                self.__hide_pkg_version_details()
                        else:
                                if plan_pkg == None:
                                        # Installed with later version but can't upgrade
                                        # Upgradeable Version: None
                                        installable_label = _("None")
                                        self.__setup_version_info_details(name,
                                            remote_info.version,
                                            remote_info.build_release,
                                            remote_info.branch, False)
                                else:
                                        # Installed with later version and can upgrade to
                                        # Upgradeable Version: <version>
                                        # Upgradeable == Latest Version
                                        if gui_misc.same_pkg_versions(plan_pkg,
                                            remote_info):
                                                installable_label = installable_fmt % \
                                                    {"version": plan_pkg.version,
                                                    "build": plan_pkg.build_release,
                                                    "branch": plan_pkg.branch}
                                                self.__hide_pkg_version_details()
                                        else:
                                        # Installed with later version and can upgrade
                                        # Upgradeable Version: <version>
                                        # but NOT to the Latest Version
                                                installable_label = installable_fmt % \
                                                    {"version": plan_pkg.version,
                                                    "build": plan_pkg.build_release,
                                                    "branch": plan_pkg.branch}

                                                self.__setup_version_info_details(name,
                                                    remote_info.version,
                                                    remote_info.build_release,
                                                    remote_info.branch, False)
                else:
                        # Not Installed
                        installed_label = _("No")
                        if plan_pkg:
                                # Not installed with later version available to install
                                # Installable: <version>
                                # Installable == Latest Version
                                if gui_misc.same_pkg_versions(plan_pkg, remote_info):
                                        installable_label = installable_fmt % \
                                            {"version": plan_pkg.version,
                                            "build": plan_pkg.build_release,
                                            "branch": plan_pkg.branch}
                                        self.__hide_pkg_version_details()
                                else:
                                        # Not installed with later version available
                                        # Installable: <version>
                                        # but NOT to the Latest Version
                                        installable_label = installable_fmt % \
                                            {"version": plan_pkg.version,
                                            "build": plan_pkg.build_release,
                                            "branch": plan_pkg.branch}
                                            
                                        self.__setup_version_info_details(name,
                                            remote_info.version,
                                            remote_info.build_release,
                                            remote_info.branch, True)
                        else:
                                # Not Installed with later version and can't install
                                # Installable Version: None
                                installable_label = _("None")
                                self.__setup_version_info_details(name,
                                    remote_info.version,
                                    remote_info.build_release,
                                    remote_info.branch, True)
                        
                self.w_info_installed_label.set_text(installed_label)
                self.w_info_installable_label.set_text(installable_label)
                self.w_info_installable_prefix_label.set_markup(installable_prefix_label)
                self.w_info_ok_button.grab_focus()                
                self.w_version_info_dialog.show()
                self.unset_busy_cursor()

        def __setup_version_info_details(self, name, version, build_release, branch,
            to_be_installed):
                installable_fmt = \
                    _("%(version)s (Build %(build)s-%(branch)s)")
                if to_be_installed:
                        expander_fmt = _(
                            "The latest version of %s cannot be installed. "
                            "It may be possible to do so after updating your system. "
                            "Run \"Updates\" to get your system up-to-date.")
                else:
                        expander_fmt = _(
                            "Cannot upgrade to the latest version of %s. "
                            "It may be possible to do so after updating your system. "
                            "Run \"Updates\" to get your system up-to-date.")
                installable_exp = installable_fmt % \
                    {"version": version,
                    "build": build_release,
                    "branch": branch}
                expander_text = installable_exp + "\n\n"
                expander_text += expander_fmt % name   
                
                # Ensure we have enough room for the Details message
                # without requiring a scrollbar  
                self.w_info_textview.set_size_request(484, 95)
                self.w_info_expander.set_expanded(True)
                self.w_info_expander.show()

                details_buff = self.w_info_textview.get_buffer()
                details_buff.set_text("")
                itr = details_buff.get_iter_at_line(0)
                details_buff.insert_with_tags_by_name(itr,
                    _("Latest Version: "), "bold")
                details_buff.insert(itr, expander_text)
                         
        def __on_info_ok_button_clicked(self, widget):
                self.w_version_info_dialog.hide()

        @staticmethod
        def __on_info_help_button_clicked(widget):
                gui_misc.display_help("package-version")

        def __on_version_info_dialog_delete_event(self, widget, event):
                self.__on_info_ok_button_clicked(None)
                return True

        def __do_api_reset(self):
                try:
                        self.api_o.reset()
                except api_errors.ApiException, ex:
                        err = str(ex)
                        gobject.idle_add(self.error_occurred, err,
                            None, gtk.MESSAGE_INFO)
                        return False
                return True

        def __on_install_update(self, widget):
                if not self.__do_api_reset():
                        return
                install_update = []
                confirmation_list = None
                if self.show_install:
                        confirmation_list = []

                if self.all_selected > 0:
                        self.__add_install_update_pkgs_for_publishers(
                                    install_update, confirmation_list)

                if self.img_timestamp != self.cache_o.get_index_timestamp():
                        self.img_timestamp = None

                installupdate.InstallUpdate(install_update, self, \
                    self.image_directory, action = enumerations.INSTALL_UPDATE,
                    main_window = self.w_main_window,
                    confirmation_list = confirmation_list)

        def __on_update_all(self, widget):
                if not self.__do_api_reset():
                        return
                confirmation = None
                if self.show_image_update:
                        confirmation = []
                installupdate.InstallUpdate([], self,
                    self.image_directory, action = enumerations.IMAGE_UPDATE,
                    parent_name = _("Package Manager"),
                    pkg_list = [gui_misc.package_name["SUNWipkg"],
                    gui_misc.package_name["SUNWipkg-gui"]],
                    main_window = self.w_main_window,
                    icon_confirm_dialog = self.window_icon,
                    confirmation_list = confirmation)
                return

        def __on_help_about(self, widget):
                wTreePlan = gtk.glade.XML(self.gladefile, "aboutdialog")
                aboutdialog = wTreePlan.get_widget("aboutdialog")
                aboutdialog.set_icon(self.window_icon)
                aboutdialog.connect("response", lambda x = None, \
                    y = None: aboutdialog.destroy())
                aboutdialog.run()

        @staticmethod
        def __on_help_help(widget):
                gui_misc.display_help()

        def __add_remove_pkgs_for_publishers(self, remove_list, confirmation_list):
                for pub_name in self.selected_pkgs:
                        pub_display_name = self.__get_publisher_display_name_from_prefix(
                            pub_name)
                        pkgs = self.selected_pkgs.get(pub_name)
                        if not pkgs:
                                break
                        for pkg_stem in pkgs:
                                status = pkgs.get(pkg_stem)[0]
                                if status == api.PackageInfo.INSTALLED or \
                                    status == api.PackageInfo.UPGRADABLE:
                                        remove_list.append(pkg_stem)
                                        if self.show_remove:
                                                desc = pkgs.get(pkg_stem)[1]
                                                pkg_name = pkgs.get(pkg_stem)[2]
                                                confirmation_list.append(
                                                    [pkg_name, pub_display_name,
                                                    desc, status])

        def __on_remove(self, widget):
                if not self.__do_api_reset():
                        return
                remove_list = []
                confirmation_list = None
                if self.show_remove:
                        confirmation_list = []
                if self.all_selected > 0:
                        self.__add_remove_pkgs_for_publishers(remove_list, 
                            confirmation_list)

                if self.img_timestamp != self.cache_o.get_index_timestamp():
                        self.img_timestamp = None

                installupdate.InstallUpdate(remove_list, self,
                    self.image_directory, action = enumerations.REMOVE,
                    main_window = self.w_main_window,
                    confirmation_list = confirmation_list)

        def __on_reload(self, widget):
                self.force_reload_packages = True
                self.__do_reload(widget)

        def __do_reload(self, widget):
                self.w_repository_combobox.grab_focus()
                if self.force_reload_packages and (self.in_search_mode 
                    or self.is_all_publishers):
                        self.__unset_search(False)
                self.__set_empty_details_panel()
                self.in_setup = True
                self.last_visible_publisher = None
                self.set_busy_cursor()
                status_str = _("Refreshing package catalog information")
                self.__update_statusbar_message(status_str)
                Thread(target = self.__catalog_refresh).start()

        def __catalog_refresh(self):
                """Update image's catalogs."""
                success = self.__do_refresh(immediate=True)
                if not success:
                        gobject.idle_add(self.unset_busy_cursor)
                        gobject.idle_add(self.update_statusbar)
                        return -1
                gobject.idle_add(self.__clear_recent_searches)
                self.__catalog_refresh_done()
                return 0

        def __catalog_refresh_done(self):
                if not self.exiting:
                        gobject.idle_add(self.process_package_list_start)

        def __get_publisher_name_from_index(self, index):
                name = None
                if index != -1:
                        itr = self.repositories_list.iter_nth_child(None,
                            index)
                        name = self.repositories_list.get_value(itr,
                            enumerations.REPOSITORY_PREFIX)
                return name

        def __shutdown_part1(self):
                self.cancelled = True
                self.exiting = True
                self.__progress_pulse_stop()

                self.w_main_window.hide()
                gui_misc.shutdown_logging()

        def __shutdown_part2(self):
                if self.api_o and self.api_o.can_be_canceled():
                        Thread(target = self.api_o.cancel, args = ()).start()
                self.__do_exit()
                gobject.timeout_add(1000, self.__do_exit)

        def __main_application_quit(self, restart = False):
                '''quits the main gtk loop'''
                save_width, save_height = self.w_main_window.get_size()
                save_hpos = self.w_main_hpaned.get_position()
                save_vpos = self.w_main_vpaned.get_position()
                
                self.__shutdown_part1()
                pub = ""
                start_insearch = False
                width = height = hpos = vpos = -1
                if self.save_state:
                        if self.is_all_publishers:
                                start_insearch = True
                        if self.is_all_publishers or self.is_all_publishers_installed:
                                sel_pub = self.__get_publisher_name_from_index(
                                    self.saved_repository_combobox_active)
                        else:
                                sel_pub = self.__get_selected_publisher()
                        if sel_pub != None:
                                pub = sel_pub
                        width = save_width
                        height = save_height
                        hpos = save_hpos
                        vpos = save_vpos
                try:
                        if self.last_export_selection_path:
                                self.client.set_string(LAST_EXPORT_SELECTION_PATH,
                                    self.last_export_selection_path)
                        self.client.set_string(LASTSOURCE_PREFERENCES, pub)
                        self.client.set_bool(START_INSEARCH_PREFERENCES,
                            start_insearch)
                        self.client.set_int(INITIAL_APP_WIDTH_PREFERENCES, width)
                        self.client.set_int(INITIAL_APP_HEIGHT_PREFERENCES, height)
                        self.client.set_int(INITIAL_APP_HPOS_PREFERENCES, hpos)
                        self.client.set_int(INITIAL_APP_VPOS_PREFERENCES, vpos)
                except GError:
                        pass

                if restart:
                        gobject.spawn_async([self.application_path, "-R",
                            self.image_directory, "-U"])
                else:
                        if self.is_all_publishers or self.is_all_publishers_installed:
                                pub = self.__get_publisher_name_from_index(
                                    self.saved_repository_combobox_active)
                        else:
                                pub = self.__get_selected_publisher()

                if self.cache_o != None:
                        if len(self.search_completion) > 0:
                                self.cache_o.dump_search_completion_info(
                                    self.search_completion)
                        if len(self.category_active_paths) > 0:
                                self.cache_o.dump_categories_active_dict(
                                    self.category_active_paths)
                        if len(self.category_expanded_paths) > 0:
                                self.cache_o.dump_categories_expanded_dict(
                                    self.category_expanded_paths)

                self.__shutdown_part2()
                return True

        def __do_exit(self):
                if threading.activeCount() == 1:
                        if not self.before_start:
                                gtk.main_quit()
                        sys.exit(0)
                return True

        def __check_if_something_was_changed(self):
                ''' Returns True if any of the check boxes for package was changed, false
                if not'''
                if self.application_list:
                        for pkg in self.application_list:
                                if pkg[enumerations.MARK_COLUMN] == True:
                                        return True
                return False

        @staticmethod
        def __alias_clash(pubs, prefix, alias):
                clash = False
                if alias != None and len(alias) > 0:
                        for pub in pubs:
                                if pub.disabled:
                                        continue
                                if pub.prefix == prefix:
                                        continue
                                if alias == pub.prefix or alias == pub.alias:
                                        clash = True
                                        break
                return clash

        def __setup_repositories_combobox(self, api_o):
                previous_publisher = None
                previous_saved_name = None
                if not self.first_run:
                        previous_publisher = self.__get_selected_publisher()
                        if self.saved_repository_combobox_active != -1:
                                itr = self.repositories_list.iter_nth_child(None,
                                    self.saved_repository_combobox_active)
                                previous_saved_name = \
                                   self.repositories_list.get_value(itr, 
                                   enumerations.REPOSITORY_PREFIX)
                self.__disconnect_repository_model()
                self.repositories_list = self.__get_new_repositories_liststore()
                default_pub = api_o.get_preferred_publisher().prefix
                if self.default_publisher != default_pub:
                        self.__clear_pkg_selections()
                        self.default_publisher = default_pub
                selected_repos = []
                enabled_repos = []
                for repo in self.selected_pkgs:
                        selected_repos.append(repo)
                i = 0
                active = 0
                self.pubs_info = {}
                self.pubs_display_name = {}
                pubs = api_o.get_publishers()
                for pub in pubs:
                        self.pubs_info[pub.prefix] = (pub.disabled, pub.alias)
                        if pub.disabled:
                                continue
                        alias = pub.alias
                        prefix = pub.prefix
                        if self.__alias_clash(pubs, prefix, alias):
                                display_name = "%s (%s)" % (alias, prefix)
                        elif alias == None or len(alias) == 0:
                                display_name = prefix
                        else:
                                display_name = alias
                        self.pubs_display_name[pub.prefix] = display_name
                        if cmp(prefix, self.default_publisher) == 0:
                                active = i
                        self.repositories_list.append([i, display_name, prefix, alias ])
                        enabled_repos.append(prefix)
                        i = i + 1
                self.repositories_list.append([-1, "", None, None, ])
                i = i + 1
                self.repo_combobox_all_pubs_installed_index = i
                self.repositories_list.append(
                    [self.repo_combobox_all_pubs_installed_index, 
                    self.publisher_options[PUBLISHER_INSTALLED],
                    self.publisher_options[PUBLISHER_INSTALLED], None, ])
                i = i + 1
                self.repo_combobox_all_pubs_index = i
                self.repositories_list.append([self.repo_combobox_all_pubs_index, 
                    self.publisher_options[PUBLISHER_ALL],
                    self.publisher_options[PUBLISHER_ALL], None, ])
                i = i + 1
                self.repositories_list.append([-1, "", None, None, ])
                i = i + 1
                self.repo_combobox_add_index = i
                self.repositories_list.append([-1,
                    self.publisher_options[PUBLISHER_ADD],
                    self.publisher_options[PUBLISHER_ADD], None, ])
                pkgs_to_remove = []
                for repo_name in selected_repos:
                        if repo_name not in enabled_repos:
                                pkg_stems = self.selected_pkgs.get(repo_name)
                                for pkg_stem in pkg_stems:
                                        pkgs_to_remove.append(pkg_stem)
                for pkg_stem in pkgs_to_remove:
                        self.__remove_pkg_stem_from_list(pkg_stem)
                self.w_repository_combobox.set_model(self.repositories_list)
                selected_id = -1
                self.same_publisher_on_setup = False
                if self.first_run:
                        for repo in self.repositories_list:
                                if (repo[enumerations.REPOSITORY_PREFIX] == \
                                    self.lastsource and
                                    repo[enumerations.REPOSITORY_ID] != -1):
                                        selected_id = \
                                           repo[enumerations.REPOSITORY_ID]
                                        break
                else:
                        for repo in self.repositories_list:
                                if (repo[enumerations.REPOSITORY_PREFIX] ==
                                    previous_publisher and
                                    repo[enumerations.REPOSITORY_ID] != -1):
                                        selected_id = \
                                           repo[enumerations.REPOSITORY_ID]
                                        if not self.force_reload_packages:
                                                self.same_publisher_on_setup = True
                                        break
                        if self.saved_repository_combobox_active != -1:
                                self.saved_repository_combobox_active = -1
                                for repo in self.repositories_list:
                                        if (repo[enumerations.REPOSITORY_PREFIX] ==
                                            previous_saved_name):
                                                self.saved_repository_combobox_active = \
                                                   repo[enumerations.REPOSITORY_ID]
                                                break
                                # Previous publisher no longer enabled
                                if self.saved_repository_combobox_active == -1:
                                        selected_id = -1
                                        self.same_publisher_on_setup = False
                if selected_id != -1:
                        self.w_repository_combobox.set_active(selected_id)
                elif self.default_publisher:
                        self.w_repository_combobox.set_active(active)
                else:
                        self.w_repository_combobox.set_active(0)

        def __active_pane_toggle(self, cell, path, model_sort):
                '''Toggle function for column enumerations.MARK_COLUMN'''
                applicationModel = model_sort.get_model()
                applicationPath = model_sort.convert_path_to_child_path(path)
                filterModel = applicationModel.get_model()
                child_path = applicationModel.convert_path_to_child_path(applicationPath)
                itr = filterModel.get_iter(child_path)
                if itr:
                        modified = filterModel.get_value(itr, enumerations.MARK_COLUMN)
                        filterModel.set_value(itr, enumerations.MARK_COLUMN,
                            not modified)
                        pkg_status = filterModel.get_value(itr,
                            enumerations.STATUS_COLUMN)
                        pkg_stem = filterModel.get_value(itr, enumerations.STEM_COLUMN)
                        if modified:
                                self.__remove_pkg_stem_from_list(pkg_stem)
                        else:
                                pkg_publisher = filterModel.get_value(itr, 
                                    enumerations.PUBLISHER_PREFIX_COLUMN)
                                pkg_description = filterModel.get_value(itr, 
                                    enumerations.DESCRIPTION_COLUMN)
                                pkg_name = filterModel.get_value(itr,
                                    enumerations.NAME_COLUMN)
                                self.__add_pkg_stem_to_list(pkg_stem, pkg_name,
                                    pkg_status, pkg_publisher, pkg_description)
                        self.update_statusbar()
                        self.__enable_disable_selection_menus()
                        self.__enable_disable_install_remove()

        def __update_reload_button(self):
                if self.user_rights:
                        self.w_reload_menuitem.set_sensitive(True)
                        self.w_reload_button.set_sensitive(True)
                else:
                        self.w_reload_menuitem.set_sensitive(False)
                        self.w_reload_button.set_sensitive(False)

        def __add_pkg_stem_to_list(self, stem, name, status, pub, description="test"):
                if self.selected_pkgs.get(pub) == None:
                        self.selected_pkgs[pub] = {}
                self.selected_pkgs.get(pub)[stem] = [status, description, name]
                if status == api.PackageInfo.KNOWN or \
                    status == api.PackageInfo.UPGRADABLE:
                        if self.to_install_update.get(pub) == None:
                                self.to_install_update[pub] = 1
                        else:
                                self.to_install_update[pub] += 1
                if status == api.PackageInfo.UPGRADABLE or \
                    status == api.PackageInfo.INSTALLED:
                        if self.to_remove.get(pub) == None:
                                self.to_remove[pub] = 1
                        else:
                                self.to_remove[pub] += 1
                self.__update_tooltips()

        def __update_tooltips(self):
                to_remove = None
                to_install = None
                no_iter = 0
                for pub in self.to_remove:
                        packages = self.to_remove.get(pub)
                        if packages > 0:
                                if no_iter == 0:
                                        to_remove = _("Selected for Removal:")
                                to_remove += "\n   %s: %d" % (pub, packages)
                                no_iter += 1
                no_iter = 0
                for pub in self.to_install_update:
                        packages = self.to_install_update.get(pub)
                        if packages > 0:
                                if no_iter == 0:
                                        to_install = _("Selected for Install/Update:")
                                to_install += "\n   %s: %d" % (pub, packages)
                                no_iter += 1
                if not to_install:
                        to_install = _("Select packages by marking the checkbox "
                            "and click to Install/Update.")
                self.w_installupdate_button.set_tooltip_text(to_install)
                if not to_remove:
                        to_remove = _("Select packages by marking the checkbox "
                            "and click to Remove selected.")
                self.w_remove_button.set_tooltip_text(to_remove)

        def __remove_pkg_stem_from_list(self, stem):
                remove_pub = []
                for pub in self.selected_pkgs:
                        pkgs = self.selected_pkgs.get(pub)
                        status = None
                        if stem in pkgs:
                                status = pkgs.pop(stem)[0]
                        if status == api.PackageInfo.KNOWN or \
                            status == api.PackageInfo.UPGRADABLE:
                                if self.to_install_update.get(pub) == None:
                                        self.to_install_update[pub] = 0
                                else:
                                        self.to_install_update[pub] -= 1
                        if status == api.PackageInfo.UPGRADABLE or \
                            status == api.PackageInfo.INSTALLED:
                                if self.to_remove.get(pub) == None:
                                        self.to_remove[pub] = 0
                                else:
                                        self.to_remove[pub] -= 1
                        if len(pkgs) == 0:
                                remove_pub.append(pub)
                for pub in remove_pub:
                        self.selected_pkgs.pop(pub)
                self.__update_tooltips()

        def __clear_pkg_selections(self):
                # We clear the selections as the preferred repository was changed
                # and pkg stems are not valid.
                remove_pub = []
                for pub in self.selected_pkgs:
                        stems = self.selected_pkgs.get(pub)
                        for pkg_stem in stems:
                                remove_pub.append(pkg_stem)
                for pkg_stem in remove_pub:
                        self.__remove_pkg_stem_from_list(pkg_stem)

        def __set_empty_details_panel(self):
                self.showing_empty_details = True
                if self.show_info_id != 0:
                        gobject.source_remove(self.show_info_id)
                        self.show_info_id = 0
                if self.show_licenses_id != 0:
                        gobject.source_remove(self.show_licenses_id)
                        self.show_licenses_id = 0
                self.w_installedfiles_textview.get_buffer().set_text("")
                self.w_dependencies_textview.get_buffer().set_text("")
                self.w_generalinfo_textview.get_buffer().set_text("")
                self.w_license_textview.get_buffer().set_text("")
                return

        def __show_fetching_package_info(self, pkg):
                pkg_stem = pkg.get_pkg_stem()
                if self.__setting_from_cache(pkg_stem):
                        return

                instbuffer = self.w_installedfiles_textview.get_buffer()
                depbuffer = self.w_dependencies_textview.get_buffer()
                infobuffer = self.w_generalinfo_textview.get_buffer()
                fetching_text = _("Fetching information...")
                instbuffer.set_text(fetching_text)
                depbuffer.set_text(fetching_text)
                infobuffer.set_text(fetching_text)
                return

        def __setting_from_cache(self, pkg_stem):
                if not self.use_cache:
                        if debug:
                                print "DEBUG: __setting_from_cache: not using cache"
                        return False
                if len(self.info_cache) > MAX_INFO_CACHE_LIMIT:
                        self.info_cache = {}

                if self.info_cache.has_key(pkg_stem):
                        labs = self.info_cache[pkg_stem][
                            enumerations.INFO_GENERAL_LABELS]
                        text = self.info_cache[pkg_stem][
                            enumerations.INFO_GENERAL_TEXT]
                        gui_misc.set_package_details_text(labs, text,
                            self.w_generalinfo_textview,
                            self.installed_icon, self.not_installed_icon,
                            self.update_available_icon) 
                        text = self.info_cache[pkg_stem][
                            enumerations.INFO_INSTALLED_TEXT]
                        self.__set_installedfiles_text(text)
                        local_info = self.info_cache[pkg_stem][
                            enumerations.INFO_DEPEND_INFO]
                        dep_info = self.info_cache[pkg_stem][
                            enumerations.INFO_DEPEND_DEPEND_INFO]
                        installed_dep_info = self.info_cache[pkg_stem][
                            enumerations.INFO_DEPEND_DEPEND_INSTALLED_INFO]
                        self.__set_dependencies_text(local_info, dep_info,
                            installed_dep_info)
                        return True
                else:
                        return False

        def __set_installedfiles_text(self, text):
                instbuffer = self.w_installedfiles_textview.get_buffer()
                instbuffer.set_text("")
                itr = instbuffer.get_start_iter()
                instbuffer.insert(itr, text)

        def __set_dependencies_text(self, info, dep_info, installed_dep_info):
                names = []
                states = None
                installed_states = []
                if dep_info != None and len(dep_info.get(0)) >= 0:
                        states = dep_info[0]
                if installed_dep_info != None and len(installed_dep_info.get(0)) >= 0:
                        installed_states = installed_dep_info[0]
                version_fmt = _("%(version)s (Build %(build)s-%(branch)s)")
                i = 0
                for x in info.dependencies:
                        if states != None and len(states) > 0:
                                name = fmri.extract_pkg_name(x)
                                if i < len(states):
                                        version = version_fmt % \
                                            {"version": states[i].version,
                                            "build": states[i].build_release,
                                            "branch": states[i].branch}
                                else:
                                        version = version_fmt % \
                                            {"version": '0',
                                            "build": '0',
                                            "branch": '0'}
                                found = False
                                for state in installed_states:
                                        if name ==  fmri.extract_pkg_name(state.fmri):
                                                installed_version = version_fmt % \
                                                    {"version": state.version,
                                                    "build": state.build_release,
                                                    "branch": state.branch}
                                                found = True
                                                break
                                if not found:
                                        installed_version = (_("(not installed)"))
                                names.append((name, version, installed_version,
                                    found))
                                i += 1
                        else:
                                build_rel = "0"
                                pkg_fmri = fmri.PkgFmri(x, build_release=build_rel)
                                branch = pkg_fmri.version.branch
                                version_stripped = pkg_fmri.get_version().split("-%s"
                                    % branch)[0]
                                version = version_fmt % \
                                     {"version": version_stripped,
                                     "build": build_rel,
                                     "branch": branch}
                                names.append((pkg_fmri.pkg_name, version,
                                    _("(not installed)"), False))

                depbuffer = self.w_dependencies_textview.get_buffer()
                depbuffer.set_text("")
                if states == None:
                        if len(names) == 0:
                                itr = depbuffer.get_iter_at_line(0)
                                depbuffer.insert_with_tags_by_name(itr, 
                                    _("None"), "bold")
                        else:
                                for i in  range(0, len(names)):
                                        itr = depbuffer.get_iter_at_line(i)
                                        dep_str = "%s\n" % (names[i]) 
                                        depbuffer.insert(itr, dep_str)
                        return
                max_name_len = 0
                max_version_len = 0
                for (name, version, installed_version, is_installed) in names:
                        if len(name) > max_name_len:
                                max_name_len = len(name)
                        if len(version) > max_version_len:
                                max_version_len = len(version)

                style = self.w_dependencies_textview.get_style()
                font_size_in_pango_unit = style.font_desc.get_size()
                font_size_in_pixel = font_size_in_pango_unit / pango.SCALE
                tab_array = pango.TabArray(3, True)
                i = 1
                tab_array.set_tab(i, pango.TAB_LEFT,
                    max_name_len * font_size_in_pixel + 1)
                i += 1
                tab_array.set_tab(i, pango.TAB_LEFT,
                    (max_name_len + max_version_len) * 
                    font_size_in_pixel + 2)
                self.w_dependencies_textview.set_tabs(tab_array)

                itr = depbuffer.get_iter_at_line(0)
                depbuffer.insert_with_tags_by_name(itr, 
                    _("Name\tDependency\tInstalled Version\n"), "bold")
                installed_icon = None
                not_installed_icon = None
                i += 0
                for (name, version, installed_version, is_installed) in names:
                        if is_installed:
                                if installed_icon == None:
                                        installed_icon = gui_misc.resize_icon(
                                            self.installed_icon,
                                            font_size_in_pixel)
                                icon = installed_icon
                        else:
                                if not_installed_icon == None:
                                        not_installed_icon = gui_misc.resize_icon(
                                            self.not_installed_icon,
                                            font_size_in_pixel)
                                icon = not_installed_icon
                        itr = depbuffer.get_iter_at_line(i + 1)
                        dep_str = "%s\t%s\t" % (name, version)
                        depbuffer.insert(itr, dep_str)
                        end_itr = depbuffer.get_end_iter()
                        depbuffer.insert_pixbuf(end_itr, icon)
                        depbuffer.insert(end_itr, " %s\n" % installed_version)
                        i += 1

        def __update_package_info(self, pkg, local_info, remote_info, dep_info,
            installed_dep_info, info_id):
                if self.showing_empty_details or (info_id != 
                    self.last_show_info_id):
                        return
                pkg_stem = pkg.get_pkg_stem()

                if self.__setting_from_cache(pkg_stem):
                        return

                instbuffer = self.w_installedfiles_textview.get_buffer()
                depbuffer = self.w_dependencies_textview.get_buffer()
                infobuffer = self.w_generalinfo_textview.get_buffer()

                if not local_info and not remote_info:
                        network_str = \
                            _("\nThis might be caused by network problem "
                            "while accessing the repository.")
                        instbuffer.set_text( \
                            _("Files Details not available for this package...") +
                            network_str)
                        depbuffer.set_text(_(
                            "Dependencies info not available for this package...") +
                            network_str)
                        infobuffer.set_text(
                            _("Information not available for this package...") +
                            network_str)
                        return

                labs, text = gui_misc.set_package_details(pkg.get_name(), local_info,
                    remote_info, self.w_generalinfo_textview,
                    self.installed_icon, self.not_installed_icon,
                    self.update_available_icon,
                    self.is_all_publishers_installed, self.pubs_info)
                if not local_info:
                        # Package is not installed
                        local_info = remote_info

                if not remote_info:
                        remote_info = local_info

                inst_str = ""
                if local_info.dirs:
                        for x in local_info.dirs:
                                inst_str += ''.join("%s%s\n" % (
                                    self.api_o.root, x))
                if local_info.files:
                        for x in local_info.files:
                                inst_str += ''.join("%s%s\n" % (
                                    self.api_o.root, x))
                if local_info.hardlinks:
                        for x in local_info.hardlinks:
                                inst_str += ''.join("%s%s\n" % (
                                    self.api_o.root, x))
                if local_info.links:
                        for x in local_info.links:
                                inst_str += ''.join("%s%s\n" % (
                                    self.api_o.root, x))
                self.__set_installedfiles_text(inst_str)
                self.__set_dependencies_text(local_info, dep_info,
                    installed_dep_info)
                if self.use_cache:
                        self.info_cache[pkg_stem] = (labs, text, inst_str,
                            local_info, dep_info, installed_dep_info)
                self.unset_busy_cursor()

        @staticmethod
        def setup_package_license(licenses):
                lic = ""
                lic_u = ""
                if licenses == None:
                        lic_u = _("Not available")
                else:
                        for licens in licenses:
                                lic += licens.get_text()
                                lic += "\n"
                        try:
                                lic_u = unicode(lic, "utf-8")
                        except UnicodeDecodeError:
                                lic_u = _("License could not be shown "
                                    "due to conversion problem.")
                return lic_u

        def __update_package_license(self, licenses, license_id):
                if self.showing_empty_details or (license_id !=
                    self.last_show_licenses_id):
                        return
                licbuffer = self.w_license_textview.get_buffer()
                licbuffer.set_text(self.setup_package_license(licenses))

        def __show_licenses(self):
                self.show_licenses_id = 0
                Thread(target = self.__show_package_licenses,
                    args = (self.selected_pkgstem, self.last_show_licenses_id,)).start()

        def __show_package_licenses(self, selected_pkgstem, license_id):
                if selected_pkgstem == None:
                        gobject.idle_add(self.__update_package_license, None,
                            self.last_show_licenses_id)
                        return
                info = None
                try:
                        info = self.api_o.info([selected_pkgstem],
                            True, frozenset([api.PackageInfo.LICENSES]))
                except api_errors.TransportError, tpex:
                        err = str(tpex)
                        logger.error(err)
                        gui_misc.notify_log_error(self)
                except api_errors.InvalidDepotResponseException, idex:
                        err = str(idex)
                        logger.error(err)
                        gui_misc.notify_log_error(self)
                except api_errors.ImageLockedError, ex:
                        err = str(ex)
                        logger.error(err)
                        gui_misc.notify_log_error(self)
                except Exception, ex:
                        err = str(ex)
                        gobject.idle_add(self.error_occurred, err)
                if self.showing_empty_details or (license_id != 
                    self.last_show_licenses_id):
                        return
                if not info or (info and len(info.get(0)) == 0):
                        try:
                        # Get license from remote
                                info = self.api_o.info([selected_pkgstem],
                                    False, frozenset([api.PackageInfo.LICENSES]))
                        except api_errors.TransportError, tpex:
                                err = str(tpex)
                                logger.error(err)
                                gui_misc.notify_log_error(self)
                        except api_errors.InvalidDepotResponseException, idex:
                                err = str(idex)
                                logger.error(err)
                                gui_misc.notify_log_error(self)
                        except api_errors.ImageLockedError, ex:
                                err = str(ex)
                                logger.error(err)
                                gui_misc.notify_log_error(self)
                        except Exception, ex:
                                err = str(ex)
                                gobject.idle_add(self.error_occurred, err)
                if self.showing_empty_details or (license_id != 
                    self.last_show_licenses_id):
                        return
                pkgs_info = None
                package_info = None
                no_licenses = 0
                if info:
                        pkgs_info = info[0]
                if pkgs_info:
                        package_info = pkgs_info[0]
                if package_info:
                        no_licenses = len(package_info.licenses)
                if no_licenses == 0:
                        gobject.idle_add(self.__update_package_license, None, 
                            license_id)
                        return
                else:
                        gobject.idle_add(self.__update_package_license,
                            package_info.licenses, license_id)

        def __show_info(self, model, path):
                self.show_info_id = 0
                if not (model and path):
                        return
                if self.selected_model != None:
                        if (self.selected_model != model or
                            self.selected_path != path):
                        # This can happen after catalogs are loaded in
                        # enable_disable_update_all and a different
                        # package is selected before enable_disable_update_all
                        # calls __show_info. We set these variable to None
                        # so that when __show_info is called it does nothing.
                                self.selected_model = None
                                self.selected_path = None

                itr = model.get_iter(path)
                pkg = model.get_value(itr, enumerations.FMRI_COLUMN)
                pkg_stem = model.get_value(itr, enumerations.STEM_COLUMN)
                pkg_status = model.get_value(itr, enumerations.STATUS_COLUMN)
                if self.info_cache.has_key(pkg_stem):
                        return
                self.set_busy_cursor()
                Thread(target = self.__show_package_info,
                    args = (pkg, pkg_stem, pkg_status, self.last_show_info_id)).start()

        def __show_package_info(self, pkg, pkg_stem, pkg_status, info_id):
                local_info = None
                remote_info = None
                if not self.showing_empty_details and (info_id ==
                    self.last_show_info_id) and (pkg_status ==
                    api.PackageInfo.INSTALLED or pkg_status ==
                    api.PackageInfo.UPGRADABLE):
                        local_info = gui_misc.get_pkg_info(self, self.api_o, pkg_stem,
                            True)
                if not self.showing_empty_details and (info_id ==
                    self.last_show_info_id) and (pkg_status ==
                    api.PackageInfo.KNOWN or pkg_status ==
                    api.PackageInfo.UPGRADABLE):
                        remote_info = gui_misc.get_pkg_info(self, self.api_o, pkg_stem,
                            False)
                if not self.showing_empty_details and (info_id ==
                    self.last_show_info_id):
                        if local_info:
                                info = local_info
                        else:
                                info = remote_info
                        dep_info = None
                        installed_dep_info = None
                        if info and info.dependencies:
                                gobject.idle_add(self.set_busy_cursor)
                                try:
                                        try:
                                                dep_info = self.api_o.info(
                                                    info.dependencies,
                                                    False,
                                                    frozenset([api.PackageInfo.STATE,
                                                    api.PackageInfo.IDENTITY]))
                                                temp_info = []
                                                for depend in info.dependencies:
                                                        name = fmri.extract_pkg_name(
                                                            depend)
                                                        temp_info.append(name)
                                                installed_dep_info = self.api_o.info(
                                                    temp_info,
                                                    True,
                                                    frozenset([api.PackageInfo.STATE,
                                                    api.PackageInfo.IDENTITY]))
                                        except api_errors.TransportError, tpex:
                                                err = str(tpex)
                                                logger.error(err)
                                                gui_misc.notify_log_error(self)
                                        except api_errors.InvalidDepotResponseException, \
                                                idex:
                                                err = str(idex)
                                                logger.error(err)
                                                gui_misc.notify_log_error(self)
                                        except api_errors.ImageLockedError, ex:
                                                err = str(ex)
                                                logger.error(err)
                                                gui_misc.notify_log_error(self)
                                        except Exception, ex:
                                                err = str(ex)
                                                gobject.idle_add(self.error_occurred, err)
                                finally:
                                        gobject.idle_add(self.unset_busy_cursor)
                        gobject.idle_add(self.__update_package_info, pkg,
                            local_info, remote_info, dep_info, installed_dep_info,
                            info_id)
                return

        # This function is ported from pkg.actions.generic.distinguished_name()
        @staticmethod
        def __locale_distinguished_name(action):
                if action.key_attr == None:
                        return str(action)
                return "%s: %s" % \
                    (_(action.name), action.attrs.get(action.key_attr, "???"))

        def __get_active_section_and_category(self):
                selection = self.w_categories_treeview.get_selection()
                selected_section = 0
                selected_category = 0
                
                if not selection:
                        return 0, 0
                category_model, category_itr = selection.get_selected()
                if not category_model or not category_itr:
                        return 0, 0

                selected_category = category_model.get_value(category_itr,
                    enumerations.CATEGORY_ID)
                cat_path = list(category_model.get_path(category_itr))
                        
                # Top level Section has been selected
                if len(cat_path) == 1 and selected_category > RECENT_SEARCH_ID_OFFSET:
                        selected_section = selected_category
                        return selected_section, 0
                elif len(cat_path) == 1 and selected_category > SECTION_ID_OFFSET:
                        selected_section = selected_category - SECTION_ID_OFFSET
                        return selected_section, 0
                else:
                        # Subcategory selected need to get categories parent Section
                        parent_iter = category_model.iter_parent(category_itr)
                        if not parent_iter:
                                return selected_section, selected_category
                        selected_section = category_model.get_value(
                            parent_iter, enumerations.CATEGORY_ID) - SECTION_ID_OFFSET
                        return selected_section, selected_category

        def __application_filter(self, model, itr):
                '''This function is used to filter content in the main
                application view'''
                selected_category = 0
                selected_section = 0
                category = False

                if self.in_setup or self.cancelled:
                        return category
                filter_id = self.w_filter_combobox.get_active()
                if filter_id == enumerations.FILTER_SELECTED:
                        return model.get_value(itr, enumerations.MARK_COLUMN)

                category_list = model.get_value(itr, enumerations.CATEGORY_LIST_COLUMN)
                selected_section, selected_category = \
                        self.__get_active_section_and_category()
                        
                in_recent_search = False
                if selected_section == 0 and selected_category == 0:
                        #Clicked on All Categories
                        category = True
                elif selected_category != 0:
                        #Clicked on subcategory
                        if category_list and selected_category in category_list:
                                category = True
                elif category_list:
                        #Clicked on Top Level section                        
                        if selected_section < RECENT_SEARCH_ID_OFFSET:
                                categories_in_section = \
                                        self.section_categories_list[selected_section]
                                for cat_id in category_list:
                                        if cat_id in categories_in_section:
                                                category = True
                                                break
                        else:
                                in_recent_search = True
                if (model.get_value(itr, enumerations.IS_VISIBLE_COLUMN) == False):
                        return False
                if self.in_search_mode or in_recent_search:
                        return self.__is_package_filtered(model, itr, filter_id)
                return (category &
                    self.__is_package_filtered(model, itr, filter_id))

        @staticmethod
        def __is_package_filtered(model, itr, filter_id):
                '''Function for filtercombobox'''
                if filter_id == enumerations.FILTER_ALL:
                        return True
                status = model.get_value(itr, enumerations.STATUS_COLUMN)
                if filter_id == enumerations.FILTER_INSTALLED:
                        return (status == api.PackageInfo.INSTALLED or status == \
                            api.PackageInfo.UPGRADABLE)
                elif filter_id == enumerations.FILTER_UPDATES:
                        return status == api.PackageInfo.UPGRADABLE
                elif filter_id == enumerations.FILTER_NOT_INSTALLED:
                        return status == api.PackageInfo.KNOWN

        def __is_pkg_repository_visible(self, model, itr):
                if len(self.repositories_list) <= 1:
                        return True
                else:
                        visible_publisher = self.__get_selected_publisher()
                        pkg = model.get_value(itr, enumerations.FMRI_COLUMN)
                        if not pkg:
                                return False
                        if cmp(pkg.get_publisher(), visible_publisher) == 0:
                                return True
                        else:
                                return False

        def __enable_disable_selection_menus(self):
                if self.in_setup:
                        return
                self.__enable_disable_select_updates()
                if not self.__doing_search():
                        self.unset_busy_cursor()

        def __enable_disable_select_all(self):
                if self.in_setup:
                        return
                model =  self.w_application_treeview.get_model()
                if model != None and len(model) > 0:
                        for row in model:
                                if not row[enumerations.MARK_COLUMN]:
                                        self.w_selectall_menuitem.set_sensitive(True)
                                        return
                        self.w_selectall_menuitem.set_sensitive(False)
                else:
                        self.w_selectall_menuitem.set_sensitive(False)

        def __enable_disable_install_remove(self):
                if not self.user_rights:
                        self.w_installupdate_button.set_sensitive(False)
                        self.w_installupdate_menuitem.set_sensitive(False)
                        self.w_remove_button.set_sensitive(False)
                        self.w_remove_menuitem.set_sensitive(False)
                        return
                self.__enable_if_selected_for_removal()
                self.__enable_if_selected_for_install_update()
                self.__enable_disable_export_selections()

        def __enable_if_selected_for_removal(self):
                sensitive = False
                selected = 0
                for pub in self.to_remove:
                        selected = self.to_remove.get(pub)
                        if selected > 0:
                                break
                if selected > 0:
                        sensitive = True
                self.w_remove_button.set_sensitive(sensitive)
                self.w_remove_menuitem.set_sensitive(sensitive)
                return sensitive

        def __enable_if_selected_for_install_update(self):
                sensitive = False
                selected = 0
                for pub in self.to_install_update:
                        selected = self.to_install_update.get(pub)
                        if selected > 0:
                                break
                if selected > 0:
                        sensitive = True
                self.w_installupdate_button.set_sensitive(sensitive)
                self.w_installupdate_menuitem.set_sensitive(sensitive)
                return sensitive

        def __enable_disable_select_updates(self):
                model = self.w_application_treeview.get_model()
                if model == None:
                        return
                for row in model:
                        if row[enumerations.STATUS_COLUMN] == api.PackageInfo.UPGRADABLE:
                                if not row[enumerations.MARK_COLUMN]:
                                        self.w_selectupdates_menuitem. \
                                            set_sensitive(True)
                                        return
                self.w_selectupdates_menuitem.set_sensitive(False)
                return

        def __enable_disable_export_selections(self):
                if self.selected_pkgs == None or len(self.selected_pkgs) == 0:
                        self.w_export_selections_menuitem.set_sensitive(False)
                else:
                        self.w_export_selections_menuitem.set_sensitive(True)
                return

        def __enable_disable_deselect(self):
                if self.w_application_treeview.get_model():
                        for row in self.w_application_treeview.get_model():
                                if row[enumerations.MARK_COLUMN]:
                                        self.w_deselect_menuitem.set_sensitive(True)
                                        return
                self.w_deselect_menuitem.set_sensitive(False)
                return

        def __add_pkgs_to_lists_from_api(self, pub, application_list,
            category_list, section_list):
                pubs = []
                pkgs_from_api = []

                status_str = _("Loading package list")
                gobject.idle_add(self.__update_statusbar_message, status_str)
                try:                
                        if self.is_all_publishers_installed:
                                pkgs_from_api = self.api_o.get_pkg_list(pubs = pubs,
                                    pkg_list = api.ImageInterface.LIST_INSTALLED)
                        else:
                                pubs.append(pub)
                                pkgs_from_api = self.api_o.get_pkg_list(pubs = pubs,
                                    pkg_list = api.ImageInterface.LIST_INSTALLED_NEWEST)
                except api_errors.InventoryException:
                        # This can happen if the repository does not
                        # contain any packages
                        err = _("Selected publisher does not contain any packages.")
                        gobject.idle_add(self.error_occurred, err, None,
                            gtk.MESSAGE_INFO)
                        gobject.idle_add(self.unset_busy_cursor)
                except api_errors.ApiException, apiex:
                        err = str(apiex)
                        gobject.idle_add(self.error_occurred, err, _('Unexpected Error'))
                        gobject.idle_add(self.unset_busy_cursor)
                try:    
                        self.__add_pkgs_to_lists(pkgs_from_api, pubs, application_list,
                            category_list, section_list)
                except api_errors.TransportError, tpex:
                        err = str(tpex)
                        logger.error(err)
                        gui_misc.notify_log_error(self)
                except api_errors.ApiException, apiex:
                        err = str(apiex)
                        gobject.idle_add(self.error_occurred, err, _('Unexpected Error'))
                        gobject.idle_add(self.unset_busy_cursor)
                        
        def __get_categories_for_pubs(self, pubs):
                sections = {}
                #ImageInfo for categories
                sectioninfo = imageinfo.ImageInfo()
                share_path = os.path.join(self.application_dir, 
                        "usr/share/package-manager/data")
                if len(pubs) == 0:
                        section = sectioninfo.read(os.path.join(share_path,
                                    "opensolaris.org.sections"))
                        sections["opensolaris.org"] = section
                        return sections
                        
                for pub in pubs:
                        if debug_perf:
                                a = time.time()
                        section = sectioninfo.read(os.path.join(share_path,
                            pub + ".sections"))
                        if len(section) == 0:
                                section = sectioninfo.read(os.path.join(share_path,
                                    "opensolaris.org.sections"))
                        sections[pub] = section
                        if debug_perf:
                                print "Time for get_pkg_categories", time.time() - a

                return sections

        def __add_pkgs_to_lists_from_info(self, local_results, remote_results, 
            application_list):
                status_str = _("Loading package list")
                gobject.idle_add(self.__update_statusbar_message, status_str)

                pkg_add = self.__add_pkgs_to_lists_from_results(local_results,
                    0, application_list)
                self.__add_pkgs_to_lists_from_results(remote_results,
                    pkg_add, application_list)

        def __add_pkgs_to_lists_from_results(self, results, pkg_add,
            application_list):
                for result in results:
                        pkg_pub = result.publisher
                        pkg_name = result.pkg_stem
                        pkg_fmri = fmri.PkgFmri(result.fmri)
                        pkg_stem = pkg_fmri.get_pkg_stem()
                        summ = result.summary

                        if api.PackageInfo.INSTALLED in result.states:
                                if api.PackageInfo.UPGRADABLE in result.states:
                                        status_icon = self.update_available_icon
                                        pkg_state = api.PackageInfo.UPGRADABLE
                                else:
                                        status_icon = self.installed_icon
                                        pkg_state = api.PackageInfo.INSTALLED
                        else:
                                status_icon = self.not_installed_icon
                                pkg_state = api.PackageInfo.KNOWN
                        if not self.is_all_publishers and \
                            not self.is_all_publishers_installed:
                                pkg_name = gui_misc.get_minimal_unique_name(
                                    self.package_names, pkg_name,
                                    self.special_package_names)
                                if len(pkg_name) == 0:
                                        pkg_name = result.pkg_stem
                        marked = False
                        pkgs = self.selected_pkgs.get(pkg_pub)
                        if pkgs != None:
                                if pkg_stem in pkgs:
                                        marked = True
                        pub_name = self.__get_publisher_name_from_prefix(pkg_pub)
                        next_app = \
                            [
                                marked, status_icon, pkg_name, summ, pkg_state,
                                pkg_fmri, pkg_stem, None, True, None, pub_name,
                                pkg_pub
                            ]
                        application_list.insert(pkg_add, next_app)
                        pkg_add += 1
                return pkg_add

        def __add_pkgs_to_lists(self, pkgs_from_api, pubs, application_list,
            category_list, section_list):
                if section_list != None:
                        self.__init_sections(section_list)
                sections = self.__get_categories_for_pubs(pubs)
                pkg_add = 0
                if debug_perf:
                        a = time.time()
                self.package_names = {}
                self.special_package_names = []

                for entry in pkgs_from_api:
                        (pkg_pub, pkg_name, ver), summ, cats, states = entry
                        if debug:
                                print entry
                        pkg_fmri = fmri.PkgFmri("%s@%s" % (pkg_name,
                            ver), publisher=pkg_pub)
                        pkg_stem = pkg_fmri.get_pkg_stem()
                        gui_misc.add_pkgname_to_dic(self.package_names, pkg_name, 
                            self.special_package_names)
                        if api.PackageInfo.INSTALLED in states:
                                pkg_state = api.PackageInfo.INSTALLED
                                if api.PackageInfo.UPGRADABLE in states:
                                        status_icon = self.update_available_icon
                                        pkg_state = api.PackageInfo.UPGRADABLE
                                else:
                                        status_icon = self.installed_icon
                        else:
                                pkg_state = api.PackageInfo.KNOWN
                                status_icon = self.not_installed_icon
                        marked = False
                        pkgs = self.selected_pkgs.get(pkg_pub)
                        if pkgs != None:
                                if pkg_stem in pkgs:
                                        marked = True
                        pub_name = self.__get_publisher_name_from_prefix(pkg_pub)
                        next_app = \
                            [
                                marked, status_icon, pkg_name, summ, pkg_state,
                                pkg_fmri, pkg_stem, None, True, None, pub_name,
                                pkg_pub
                            ]
                        self.__add_package_to_list(next_app,
                            application_list,
                            pkg_add, pkg_name,
                            cats, category_list, pkg_pub)
                        pkg_add += 1
                for pkg in application_list:
                        pkg_name = pkg[enumerations.NAME_COLUMN]
                        name = gui_misc.get_minimal_unique_name(self.package_names,
                            pkg_name, self.special_package_names)
                        if pkg_name != name:
                                pkg[enumerations.NAME_COLUMN] = name
                        
                if debug_perf:
                        print "Time to add packages:", time.time() - a
                if category_list != None:
                        self.__add_categories_to_sections(sections,
                            category_list, section_list)
                return

        def __add_categories_to_sections(self, sections, category_list, section_list):
                for pub in sections:
                        for section in sections[pub]:
                                self.__add_category_to_section(sections[pub][section],
                                    _(section), category_list, section_list)
                return

        def __add_package_to_list(self, app, application_list, pkg_add,
            pkg_name, cats, category_list, pub):
                row_iter = application_list.insert(pkg_add, app)
                if category_list == None:
                        return
                for cat in cats:
                        if len(cat[1]) > 1:
                                self.__add_package_to_category(cat[1],
                                    row_iter, application_list,
                                    category_list)

        @staticmethod
        def __add_package_to_category(category_name, package, 
            application_list, category_list):
                category_names = category_name.split('/', 2)
                if len(category_names) < 2:
                        return
                category_visible_name = category_names[1]
                if not package or category_visible_name == 'All':
                        return
                if not category_visible_name:
                        return
                category_id = None
                for category in category_list:
                        if category[enumerations.CATEGORY_NAME] == category_name:
                                category_id = category[enumerations.CATEGORY_ID]
                                break
                if not category_id:                       # Category not exists
                        category_id = len(category_list) + 1
                        category_list.append(None, [category_id, category_name,
                            category_visible_name, None, None, True])
                if application_list.get_value(package,
                    enumerations.CATEGORY_LIST_COLUMN):
                        a = application_list.get_value(package,
                            enumerations.CATEGORY_LIST_COLUMN)
                        a.append(category_id)
                else:
                        category_list = []
                        category_list.append(category_id)
                        application_list.set(package,
                            enumerations.CATEGORY_LIST_COLUMN, category_list)

        def __add_categories_to_tree(self, category_list, section_list):
                category_tree = self.__get_new_category_liststore()
                cat_iter = category_tree.append(None, [ 0, _("All Categories"),
                    _("All Categories"), None, None, True])

                self.section_categories_list = {}
                #Build dic of section ids and categories they contain
                #section_category_list[<sec_id>] -> cat_ids[cat_id] -> category
                #Each category row contains a list of sections it belongs to stored in
                #category[enumerations.SECTION_LIST_OBJECT]
                for category in category_list:
                        category_section_ids = \
                                category[enumerations.SECTION_LIST_OBJECT]
                        if category_section_ids == None:
                                continue
                        for sec_id in category_section_ids:
                                if sec_id in self.section_categories_list:
                                        category_ids = \
                                                self.section_categories_list[sec_id]
                                        category_ids[category[enumerations.CATEGORY_ID]] \
                                                = category
                                else:
                                        self.section_categories_list[sec_id] = \
                                                {category[enumerations.CATEGORY_ID]:\
                                                    category}

                #Build up the Category Tree
                count = 1
                visible_default_section_path = None
                for section in section_list:
                        sec_id = section[enumerations.SECTION_ID]
                        #Map self.set_section section_list index to visible section index
                        if sec_id <= 0 or not section[enumerations.SECTION_ENABLED]:
                                continue
                        if self.set_section == sec_id:
                                visible_default_section_path = (count,)
                        count += count
                        section_name = "<b>" + section[enumerations.SECTION_NAME] + "</b>"
                        cat_iter = category_tree.append(None,
                            [ SECTION_ID_OFFSET + section[enumerations.SECTION_ID], 
                            section_name, section_name, None, None, True])

                        if not sec_id in self.section_categories_list:
                                continue
                        
                        category_ids = self.section_categories_list[sec_id]
                        category_list = self.__get_new_category_liststore()
                        for cat_id in category_ids.keys():
                                if category_ids[cat_id][
                                    enumerations.CATEGORY_IS_VISIBLE]:
                                        category_list.append(None, category_ids[cat_id])
                        # Sort the Categories into alphabetical order
                        if len(category_list) > 0:
                                rows = [tuple(r) + (i,) for i, 
                                    r in enumerate(category_list)]
                                rows.sort(self.__sort)
                                r = []
                                category_list.reorder(None, [r[-1] for r in rows])
                        for category in category_list:
                                category_tree.append(cat_iter, category)

                recent_search_name = "<span foreground='#757575'><b>" + \
                    _("Recent Searches") + "</b></span>"
                self.recent_searches_cat_iter = category_tree.append(None,
                    [RECENT_SEARCH_ID, recent_search_name, recent_search_name,
                    None, None, True])
                if self.recent_searches and len(self.recent_searches) > 0:
                        for recent_search in self.recent_searches_list:
                                category_tree.append(self.recent_searches_cat_iter, 
                                    self.recent_searches[recent_search])
                
                self.w_categories_treeview.set_model(category_tree)
                
                #Initial startup expand default Section if available
                if visible_default_section_path and self.first_run and \
                        len(self.category_active_paths) == 0 and \
                        len(self.category_expanded_paths) == 0:
                        self.w_categories_treeview.expand_row(
                            visible_default_section_path, False)
                        return
                self.__restore_category_state()

        def __add_recent_search(self, text, pub_prefix, application_list):
                self.adding_recent_search = True
                category_tree = self.w_categories_treeview.get_model()
                if category_tree == None:
                        return
                if self.is_all_publishers:
                        pub_name = _("All Publishers")
                else:
                        pub_name = self.__get_publisher_display_name_from_prefix(
                            pub_prefix)
                recent_search = "(%d) <b>%s</b> %s" % \
	        	(len(application_list), text, pub_name)
                if not (recent_search in self.recent_searches):
                        cat_iter = category_tree.append(self.recent_searches_cat_iter,
                            [RECENT_SEARCH_ID + 1, recent_search, recent_search, 
                            text, application_list, True])
                        self.recent_searches[recent_search] = \
                                [RECENT_SEARCH_ID + 1, recent_search, recent_search,
                                 text, application_list, True]
                        self.recent_searches_list.append(recent_search)
                else:
                        rs_iter = category_tree.iter_children(
                            self.recent_searches_cat_iter)
                        while rs_iter:
                                rs_value = category_tree.get_value(rs_iter,
                                    enumerations.CATEGORY_VISIBLE_NAME)
                                if rs_value == recent_search:
                                        category_tree.remove(rs_iter)
                                        break
                                rs_iter = category_tree.iter_next(rs_iter)
                        cat_iter = category_tree.append(self.recent_searches_cat_iter,
                            [RECENT_SEARCH_ID + 1, recent_search, recent_search, 
                            text, application_list, True])
                        self.recent_searches_list.remove(recent_search)
                        self.recent_searches_list.append(recent_search)
                path = category_tree.get_path(cat_iter)
                self.w_categories_treeview.expand_to_path(path)
                self.__unselect_category()
                self.w_categories_treeview.scroll_to_cell(path)
                self.adding_recent_search = False
                
        def __clear_recent_searches(self):
                self.after_install_remove = False
                category_tree = self.w_categories_treeview.get_model()
                if category_tree == None:
                        return                        
                if self.recent_searches == None or len(self.recent_searches) == 0:
                        return                        
                self.__set_searchentry_to_prompt()
                selection, sel_path = self.__get_selection_and_category_path()
                rs_iter = category_tree.iter_children(self.recent_searches_cat_iter)
                while rs_iter:
                        category_tree.remove(rs_iter)
                        if category_tree.iter_is_valid(rs_iter):
                                rs_iter = category_tree.iter_next(rs_iter)
                        else:
                                break
                del(self.recent_searches_list[:])
                self.recent_searches.clear()
                
                rs_path = category_tree.get_path(self.recent_searches_cat_iter)
                if selection and sel_path and rs_path and len(sel_path) > 0 and \
                        len(rs_path) > 0 and sel_path[0] == rs_path[0]:
                        self.__restore_setup_for_browse()

        def __update_recent_search_states(self, application_list):
                pkg_stems = []
                pkg_stem_states = {}
                for row in application_list:
                        pkg_stems.append(row[enumerations.STEM_COLUMN])
                #Check for changes in package installation status
                try:
                        info = self.api_o.info(pkg_stems, True, frozenset(
                                    [api.PackageInfo.STATE, api.PackageInfo.IDENTITY]))
                        for info_s in info.get(0):
                                pkg_stem = fmri.PkgFmri(info_s.fmri).get_pkg_stem(
                                    include_scheme = True)
                                if api.PackageInfo.INSTALLED in info_s.states:
                                        pkg_stem_states[pkg_stem] = \
                                                api.PackageInfo.INSTALLED
                                else:
                                        pkg_stem_states[pkg_stem] = \
                                                api.PackageInfo.KNOWN
                except api_errors.TransportError, tpex:
                        err = str(tpex)
                        logger.error(err)
                        gui_misc.notify_log_error(self)
                except api_errors.InvalidDepotResponseException, idex:
                        err = str(idex)
                        logger.error(err)
                        gui_misc.notify_log_error(self)
                except api_errors.ImageLockedError, ex:
                        err = str(ex)
                        logger.error(err)
                        gui_misc.notify_log_error(self)
                except Exception, ex:
                        err = str(ex)
                        gobject.idle_add(self.error_occurred, err)

                #Create a new result list updated with current installation status
                tmp_app_list = self.__get_new_application_liststore()
                
                for row in application_list:
                        pkg_stem = row[enumerations.STEM_COLUMN]
                        pub = row[enumerations.PUBLISHER_COLUMN]
                        marked = False
                        pkgs = None
                        if self.selected_pkgs != None:
                                pkgs = self.selected_pkgs.get(pub)
                        if pkgs != None:
                                if pkg_stem in pkgs:
                                        marked = True
                        if row[enumerations.MARK_COLUMN] != marked:
                                row[enumerations.MARK_COLUMN] = marked
                        
                        if pkg_stem_states.has_key(pkg_stem):
                                row[enumerations.STATUS_COLUMN] = \
                                        pkg_stem_states[pkg_stem]
                                if pkg_stem_states[pkg_stem] == \
                                        api.PackageInfo.KNOWN:
                                        row[enumerations.STATUS_ICON_COLUMN] = \
                                                self.not_installed_icon
                                else:
                                        row[enumerations.STATUS_ICON_COLUMN] = \
                                                self.installed_icon
                        else:
                                row[enumerations.STATUS_COLUMN] = \
                                        api.PackageInfo.KNOWN
                                row[enumerations.STATUS_ICON_COLUMN] = \
                                        self.not_installed_icon
                        tmp_app_list.append(row)
                return tmp_app_list

        def __restore_recent_search(self, sel_category):
                if not sel_category:
                        return
                if not self.is_all_publishers:
                        self.__save_setup_before_search(single_search=True)

                application_list = sel_category[enumerations.SECTION_LIST_OBJECT]
                text = sel_category[enumerations.CATEGORY_DESCRIPTION]
                if self.after_install_remove:
                        application_list = self.__update_recent_search_states(
                            application_list)
                self.__clear_before_search(show_list=True, in_setup=False,
                    unselect_cat=False)
                self.in_search_mode = True
                self.in_recent_search = True
                self.__set_search_text_mode(enumerations.SEARCH_STYLE_NORMAL)
                self.w_searchentry.set_text(text)
                self.__set_main_view_package_list()
                self.__init_tree_views(application_list, None, None, None, None,
                    enumerations.NAME_COLUMN)

        def __setup_category_state(self):
                if self.cache_o == None:
                        return
                self.cache_o.load_categories_active_dict(self.category_active_paths)
                self.cache_o.load_categories_expanded_dict(self.category_expanded_paths)

        def __restore_category_state(self):
                #Restore expanded Category state
                if self.w_categories_treeview == None:
                        return
                model = self.w_categories_treeview.get_model()
                if model == None:
                        return
                if len(self.category_expanded_paths) > 0:
                        paths = self.category_expanded_paths.items()
                        for key, val in paths:
                                source, path = key
                                if self.last_visible_publisher == source and val:
                                        self.w_categories_treeview.expand_row(path, False)
                #Restore selected category path
                if self.last_visible_publisher in self.category_active_paths and \
                        self.category_active_paths[self.last_visible_publisher]:
                        self.w_categories_treeview.set_cursor(
                            self.category_active_paths[self.last_visible_publisher])
                else:
                        self.w_categories_treeview.set_cursor(0)
                return

        @staticmethod
        def __add_category_to_section(categories_list, section_name, category_list,
            section_list):
                '''Adds the section to section list in category. If there is no such
                section, than it is not added. If there was already section than it
                is skipped. Sections must be case sensitive'''
                if not categories_list:
                        return
                for section in section_list:
                        if section[enumerations.SECTION_NAME] == section_name:
                                section_id = section[enumerations.SECTION_ID]
                                for category in category_list:
                                        localized_top_cat = _(category[
                                            enumerations.CATEGORY_NAME].split("/")[0])
                                        if localized_top_cat == \
                                                section[enumerations.SECTION_NAME]:
                                                
                                                vis = \
                                                    enumerations.CATEGORY_VISIBLE_NAME
                                                category[vis] = _(category[
                                                    enumerations.CATEGORY_VISIBLE_NAME])
                                                section_lst = category[ \
                                                    enumerations.SECTION_LIST_OBJECT]
                                                section[enumerations.SECTION_ENABLED] = \
                                                    True
                                                if not section_lst:
                                                        category[ \
                                                    enumerations.SECTION_LIST_OBJECT] = \
                                                            [section_id, ]
                                                else:
                                                        if not section_name in \
                                                            section_lst:
                                                                section_lst.append(
                                                                    section_id)
                                break


        def __progress_set_fraction(self, count, total):
                self.__progress_pulse_stop()
                if count == total:
                        self.w_progress_frame.hide()
                        return False
                if self.api_o and self.api_o.can_be_canceled():
                        self.progress_cancel.set_sensitive(True)
                else:
                        self.progress_cancel.set_sensitive(False)
                self.w_progress_frame.show()
                result = (count + 0.0)/total
                if result > 1.0:
                        result = 1.0
                elif result < 0.0:
                        result = 0.0
                self.w_status_progressbar.set_fraction(result)


        def __progress_pulse_start(self):
                if self.progress_stop_thread == True:
                        self.progress_stop_thread = False
                        Thread(target = self.__progress_pulse).start()

        def __progress_pulse_stop(self):
                self.progress_stop_thread = True

        def __progress_pulse(self):
                gobject.idle_add(self.w_progress_frame.show)
                while not self.progress_stop_thread:
                        if self.api_o and self.api_o.can_be_canceled():
                                gobject.idle_add(self.progress_cancel.set_sensitive, True)
                        else:
                                gobject.idle_add(self.progress_cancel.set_sensitive,
                                    False)
                        gobject.idle_add(self.w_status_progressbar.pulse)
                        time.sleep(0.1)
                gobject.idle_add(self.w_progress_frame.hide)
                self.progress_stop_thread = True

        def error_occurred(self, error_msg, msg_title=None, msg_type=gtk.MESSAGE_ERROR):
                if msg_title:
                        title = msg_title
                else:
                        title = _("Package Manager")
                gui_misc.error_occurred(self.w_main_window, error_msg,
                    title, msg_type, use_markup=True)

#-----------------------------------------------------------------------------#
# Static Methods
#-----------------------------------------------------------------------------#

        @staticmethod
        def __sort(a, b):
                return cmp(a[2], b[2])

        @staticmethod
        def filter_cell_data_function(column, renderer, model, itr, data):
                '''Function which sets icon size'''
                if data == enumerations.FILTER_NAME:
                        renderer.set_property("xalign", 0)
                        renderer.set_property("width", max_filter_length + 10)
                elif data == enumerations.FILTER_ICON:
                        renderer.set_property("xalign", 0)
                        renderer.set_property("width", 24)
                return

        @staticmethod
        def cell_data_function(column, renderer, model, itr, data):
                '''Function which sets the background colour to black if package is
                selected'''
                if itr:
                        if model.get_value(itr, enumerations.MARK_COLUMN):
                                renderer.set_property("cell-background", "#ffe5cc")
                                renderer.set_property("cell-background-set", True)
                        else:
                                renderer.set_property("cell-background-set", False)

        @staticmethod
        def combobox_separator(model, itr):
                return model.get_value(itr, enumerations.FILTER_NAME) == ""

        @staticmethod
        def combobox_id_separator(model, itr):
                return model.get_value(itr, 0) == -1 and \
                    model.get_value(itr, 1) == ""

        @staticmethod
        def combobox_filter_id_separator(model, itr):
                return model.get_value(itr, 0) == -1 and \
                    model.get_value(itr, 2) == ""

        @staticmethod
        def get_datetime(version):
                dt = None
                try:
                        dt = version.get_datetime()
                except AttributeError:
                        dt = version.get_timestamp()
                return dt

        def __get_version(self, api_o, local, pkg):
                version = None
                try:
                        info = api_o.info([pkg], local, frozenset(
                            [api.PackageInfo.STATE, api.PackageInfo.IDENTITY]))
                        found = info[api.ImageInterface.INFO_FOUND]
                        version = found[0]
                except IndexError:
                        pass
                except api_errors.ApiException, ex:
                        err = str(ex)
                        logger.error(err)
                        gobject.idle_add(gui_misc.notify_log_error, self)
                except Exception, ex:
                        pass
                return version

#-----------------------------------------------------------------------------#
# Public Methods
#-----------------------------------------------------------------------------#
        def init_show_filter(self):
                """ Sets up the Filter Combobox and returns the maximum length of text
                    labels it is displaying."""
                return self.__init_show_filter()                #Initiates filter

        def reload_packages(self):
                self.api_o = gui_misc.get_api_object(self.image_directory, 
                    self.pr, self.w_main_window)
                self.cache_o = self.__get_cache_obj(self.api_o)
                self.force_reload_packages = False
                self.__do_reload(None)

        def is_busy_cursor_set(self):
                return self.gdk_window.is_visible()

        def set_busy_cursor(self):
                if self.gdk_window.get_state() & gtk.gdk.WINDOW_STATE_WITHDRAWN:
                        self.gdk_window.show()
                        self.w_main_window.get_accessible().emit('state-change',
                            'busy', True)
                if not self.exiting:
                        self.__progress_pulse_start()

        def unset_busy_cursor(self):
                self.__progress_pulse_stop()
                if not (self.gdk_window.get_state() & gtk.gdk.WINDOW_STATE_WITHDRAWN):
                        self.gdk_window.hide()
                        self.w_main_window.get_accessible().emit('state-change',
                            'busy', False)

        def process_package_list_start(self):
                if self.first_run:
                        self.__setup_filter_combobox()
                self.__setup_repositories_combobox(self.api_o)
                if self.first_run:
                        self.__update_reload_button()
                        self.w_repository_combobox.grab_focus()

        @staticmethod
        def __get_cache_obj(api_o):
                cache_o = cache.CacheListStores(api_o)
                return cache_o

        def __setup_search_completion(self):
                completion = gtk.EntryCompletion()
                if self.cache_o != None:
                        self.cache_o.load_search_completion_info(self.search_completion)
                completion.set_model(self.search_completion)
                self.w_searchentry.set_completion(completion)
                completion.set_text_column(0)
                self.w_searchentry.connect('activate', self.__search_completion_cb)


        def process_package_list_end(self):
                self.in_startpage_startup = False
                if self.update_all_proceed:
                        self.__on_update_all(None)
                        self.update_all_proceed = False
                self.__enable_disable_install_remove()
                self.update_statusbar()
                self.in_setup = False
                self.cancelled = False
                active_filter = self.w_filter_combobox.get_active()
                if self.set_section != 0 or \
                    active_filter != enumerations.FILTER_ALL:
                        self.__application_refilter()
                else:
                        if not self.__doing_search():
                                self.unset_busy_cursor()
                if debug_perf:
                        print "End process_package_list_end", time.time()
                if self.first_run:
                        if self.start_insearch:
                                self.w_repository_combobox.set_active(
                                    self.repo_combobox_all_pubs_index)
                        self.first_run = False

        def get_icon_pixbuf_from_glade_dir(self, icon_name):
                return gui_misc.get_pixbuf_from_path(
                    os.path.join(self.application_dir, 
                    "usr/share/package-manager/"),
                    icon_name)

        def __count_selected_packages(self):
                self.all_selected = 0
                for pub_name in self.selected_pkgs:
                        pkgs = self.selected_pkgs.get(pub_name)
                        if not pkgs:
                                break
                        self.all_selected += len(pkgs)
 
        def update_statusbar(self):
                '''Function which updates statusbar'''
                self.__remove_statusbar_message()
                search_text = self.w_searchentry.get_text()

                self.__count_selected_packages()
                if not self.in_search_mode:
                        if self.application_list == None:
                                return
                        self.length_visible_list = len(self.application_list_filter)
                        selected_in_list = 0
                        for pkg_row in self.application_list_filter:
                                if pkg_row[enumerations.MARK_COLUMN]:
                                        selected_in_list = selected_in_list + 1
                        status_str = _("Total: %(total)s  Selected: %(selected)s") % \
                                {"total": self.length_visible_list, 
                                "selected": selected_in_list}
                        self.__update_statusbar_message(status_str)
                        return

                # In Search Mode
                if self.w_main_statusbar_label:
                        search_text = saxutils.escape(search_text)
                if self.w_main_statusbar_label:
                        s1 = "<b>"
                        e1 = "</b>"
                else:
                        s1 = e1 = '"'

                if self.__doing_search():
                        active_pub = self.search_all_pub_being_searched
                        status_str  = ""
                        if active_pub != None and active_pub != "":
                                status_str = \
                                        _("Searching %(s1)s%(active_pub)s%(e1)s"
                                        " for %(s1)s%(search_text)s%(e1)s ...") % \
                                        {"s1": s1, "active_pub": active_pub, "e1": e1,
                                        "search_text": search_text}
                        else:
                                status_str = \
                                        _("Searching for %(s1)s%(search_text)s%(e1)s "
                                        "...") % \
                                        {"s1": s1, "search_text": search_text, "e1": e1}
                else:
                        status_str = \
                                _("%(number)d packages found matching %(s1)s"
                                "%(search_text)s%(e1)s") % \
                                {"number": len(self.application_list),
                                    "s1": s1, "search_text": search_text, "e1": e1, }
                self.__update_statusbar_message(status_str)

        def __reset_row_status(self, row):
                pkg_stem = row[enumerations.STEM_COLUMN]
                self.__remove_pkg_stem_from_list(pkg_stem)
                if self.info_cache.has_key(pkg_stem):
                        del self.info_cache[pkg_stem]
                package_info = self.__get_version(self.api_o,
                    local = True, pkg = pkg_stem)
                package_installed =  False
                if package_info:
                        package_installed =  \
                            (api.PackageInfo.INSTALLED in package_info.states)
                if package_installed:
                        package_info = self.__get_version(self.api_o,
                            local = False, pkg = pkg_stem)
                        if (package_info and
                            api.PackageInfo.INSTALLED in package_info.states):
                                row[enumerations.STATUS_COLUMN] = \
                                    api.PackageInfo.INSTALLED
                                row[enumerations.STATUS_ICON_COLUMN] = \
                                    self.installed_icon
                        else:
                                row[enumerations.STATUS_COLUMN] = \
                                    api.PackageInfo.UPGRADABLE
                                row[enumerations.STATUS_ICON_COLUMN] = \
                                    self.update_available_icon
                else:
                        row[enumerations.STATUS_COLUMN] = \
                            api.PackageInfo.KNOWN
                        row[enumerations.STATUS_ICON_COLUMN] = \
                            self.not_installed_icon
                row[enumerations.MARK_COLUMN] = False

        def __update_publisher_list(self, pub, full_list, package_list):
                for row in full_list:
                        if row[enumerations.FMRI_COLUMN] and \
                            row[enumerations.FMRI_COLUMN].pkg_name in package_list:
                                self.__reset_row_status(row)

        def update_package_list(self, update_list):
                if update_list == None and self.img_timestamp:
                        return
                self.after_install_remove = True
                visible_publisher = self.__get_selected_publisher()
                default_publisher = self.default_publisher
                self.__do_refresh()
                if update_list == None and not self.img_timestamp:
                        self.img_timestamp = self.cache_o.get_index_timestamp()
                        self.__on_reload(None)
                        return
                visible_list = update_list.get(visible_publisher)
                if self.is_all_publishers or self.is_all_publishers_installed \
                    or self.in_recent_search:
                        try:
                                pubs = self.api_o.get_publishers()
                        except api_errors.ApiException, ex:
                                err = str(ex)
                                gobject.idle_add(self.error_occurred, err,
                                    None, gtk.MESSAGE_INFO)
                                return
                        for pub in pubs:
                                if pub.disabled:
                                        continue
                                prefix = pub.prefix
                                package_list = update_list.get(prefix)
                                if package_list != None:
                                        self.__update_publisher_list(prefix,
                                            self.application_list,
                                            package_list)
                                        if self.last_visible_publisher == prefix:
                                                self.__update_publisher_list(prefix,
                                                        self.saved_application_list,
                                                        package_list)
                        if self.is_all_publishers_installed:
                                self.__do_set_publisher()
                elif visible_list:
                        self.__update_publisher_list(visible_publisher, 
                                self.application_list, visible_list)
                        if self.in_search_mode:
                                self.__update_publisher_list(visible_publisher,
                                        self.saved_application_list,
                                        visible_list)

                for pub in update_list:
                        if pub != visible_publisher:
                                pkg_list = update_list.get(pub)
                                for pkg in pkg_list:
                                        pkg_stem = None
                                        if pub != default_publisher:
                                                pkg_stem = self.__get_pkg_stem(
                                                    pkg, pub)
                                        else:
                                                pkg_stem = self.__get_pkg_stem(
                                                    pkg)
                                        if pkg_stem:
                                                if self.info_cache.has_key(pkg_stem):
                                                        del self.info_cache[pkg_stem]
                                                self.__remove_pkg_stem_from_list(pkg_stem)
                if not self.img_timestamp:
                        self.img_timestamp = self.cache_o.get_index_timestamp()
                        self.__on_reload(None)
                        return
                self.img_timestamp = self.cache_o.get_index_timestamp()
                if self.is_all_publishers_installed:
                        return
                # We need to reset status descriptions if a11y is enabled
                self.__set_visible_status(False)
                self.__process_package_selection()
                self.__enable_disable_selection_menus()
                self.__enable_disable_install_remove()
                self.update_statusbar()

        def __reset_home_dir(self):
                # We reset the HOME directory in case the user called us
                # with gksu and had NFS mounted home directory in which
                # case dbus called from gconf cannot write to the directory.
                if self.user_rights:
                        root_home_dir = self.__find_root_home_dir()
                        os.putenv('HOME', root_home_dir)

        @staticmethod
        def __find_root_home_dir():
                return_str = '/var/tmp'
                 
                try:
                        lines = pwd.getpwnam('root')
                except KeyError:
                        if debug:
                                print "Error getting passwd database entry for root"
                        return return_str
                try:
                        return_str = lines[5]
                except IndexError:
                        if debug:
                                print "Error getting home directory for root"
                return return_str

        @staticmethod
        def __get_pkg_stem(pkg_name, pkg_pub=None):
                pkg_str = "pkg:/"
                if pkg_pub == None:
                        return_str = "%s%s" % (pkg_str, pkg_name)
                else:
                        return_str = "%s/%s/%s" % (pkg_str, pkg_pub, pkg_name)
                return return_str

        def restart_after_ips_update(self):
                self.__main_application_quit(restart = True)

        def shutdown_after_image_update(self, exit_pm = False):
                if exit_pm == True:
                        self.__on_mainwindow_delete_event(None, None)

        def __get_api_object(self):
                self.api_o = gui_misc.get_api_object(self.image_directory, 
                    self.pr, self.w_main_window)
                self.cache_o = self.__get_cache_obj(self.api_o)
                self.img_timestamp = self.cache_o.get_index_timestamp()
                self.__setup_search_completion()
                self.__setup_category_state()
                gobject.idle_add(self.__got_api_object)

        def __got_api_object(self):
                self.process_package_list_start()
                
        def start(self):
                self.before_start = False
                self.set_busy_cursor()
                Thread(target = self.__get_api_object).start() 
        
        def unhandled_exception_shutdown(self):
                self.__shutdown_part1()
                self.__shutdown_part2()

###############################################################################
#-----------------------------------------------------------------------------#
# Main
#-----------------------------------------------------------------------------#

def installThreadExcepthook():
        """
        Workaround for sys.excepthook python thread bug from:
        Bug: sys.excepthook doesn't work in threads
        http://bugs.python.org/issue1230540#msg91244
        """
        init_old = threading.Thread.__init__
        def init(self, *ite_args, **ite_kwargs):
                init_old(self, *ite_args, **ite_kwargs)
                run_old = self.run
                def run_with_except_hook(*rweh_args, **rweh_kwargs):
                        try:
                                run_old(*rweh_args, **rweh_kwargs)
                        except (KeyboardInterrupt, SystemExit):
                                raise
                        except:
                                sys.excepthook(*sys.exc_info())
                self.run = run_with_except_hook
        threading.Thread.__init__ = init
    
def __display_unknown_err(trace):
        dmsg = _("An unknown error occurred")
        md = gtk.MessageDialog(type=gtk.MESSAGE_ERROR, message_format=dmsg)
        close_btn = md.add_button(gtk.STOCK_CLOSE, 100)
        md.set_default_response(100)

        dmsg = _("Please let the developers know about this problem by\n"
                    "filing a bug together with the error details listed below at:")
        md.format_secondary_text(dmsg)
        md.set_title(_('Unexpected Error'))

        uri_btn = gtk.LinkButton(
            "http://defect.opensolaris.org/bz/enter_bug.cgi?product=pkg",
            "defect.opensolaris.org")
        uri_btn.set_relief(gtk.RELIEF_NONE)
        uri_btn.set_size_request(160, -1)
        align = gtk.Alignment(0, 0, 0, 0)
        align.set_padding(0, 0, 56, 0)
        align.add(uri_btn)
        textview = gtk.TextView()
        textview.show()
        textview.set_editable(False)
        sw = gtk.ScrolledWindow()
        sw.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
        sw.add(textview)
        fr = gtk.Frame()
        fr.set_shadow_type(gtk.SHADOW_IN)
        fr.add(sw)
        ca = md.get_content_area()
        ca.pack_start(align, False, False, 0)
        ca.pack_start(fr)

        textbuffer = textview.get_buffer()
        textbuffer.create_tag("bold", weight=pango.WEIGHT_BOLD)
        textbuffer.create_tag("level1", left_margin=30, right_margin=10)
        textiter = textbuffer.get_end_iter()
        textbuffer.insert_with_tags_by_name(textiter, _("Error details:\n"), "bold")
        textbuffer.insert_with_tags_by_name(textiter, trace.getvalue(), "level1")

        publisher_str = ""
        if packagemanager:
                publisher_str = \
                        gui_misc.get_publishers_for_output(packagemanager.api_o)
                if publisher_str != "":
                        textbuffer.insert_with_tags_by_name(textiter, 
                            _("\nList of configured publishers:"), "bold")
                        textbuffer.insert_with_tags_by_name(
                            textiter, publisher_str + "\n", "level1")
        
        if publisher_str == "":
                textbuffer.insert_with_tags_by_name(textiter, 
                    _("\nPlease include output from:\n"), "bold")
                textbuffer.insert(textiter, "$ pkg publisher\n")  
                
        ver = gui_misc.get_version()
        textbuffer.insert_with_tags_by_name(textiter,
            _("\npkg version:\n"), "bold")
        textbuffer.insert_with_tags_by_name(textiter, ver + "\n", "level1")

        md.set_size_request(550, 400)
        md.set_resizable(True)
        close_btn.grab_focus()
        md.show_all()
        md.run()        
        md.destroy()

def __display_unknown_err_ex(trace):
        try:
                __display_unknown_err(trace)
        except MemoryError:
                print trace
        except Exception:
                pass
        if packagemanager:
                packagemanager.unhandled_exception_shutdown()
        else:
                sys.exit()

def __display_memory_err():
        try:
                dmsg = misc.out_of_memory()
                msg_stripped = dmsg.replace("\n", " ")
                gui_misc.error_occurred(None, msg_stripped, _("Package Manager"),
                    gtk.MESSAGE_ERROR)
        except MemoryError:
                print dmsg
        except Exception:
                pass
        if packagemanager:
                packagemanager.unhandled_exception_shutdown()
        else:
                sys.exit()

def global_exception_handler(exctyp, value, tb):
        trace = StringIO()
        traceback.print_exception (exctyp, value, tb, None, trace)
        if exctyp is MemoryError:
                gobject.idle_add(__display_memory_err)
        else:
                gobject.idle_add(__display_unknown_err_ex, trace)

def main():
        gtk.main()
        return 0

sys.excepthook = global_exception_handler
if __name__ == '__main__':
        installThreadExcepthook()
        debug = False
        debug_perf = False
        max_filter_length = 0
        update_all_proceed = False
        app_path = None
        image_dir = None
        info_install_arg = None
        original_user = None
        save_selected = _("Save selected...")
        save_selected_pkgs = _("Save selected packages...")
        reboot_needed = _("The installed package(s) require a reboot before "
            "installation can be completed.")

        try:
                opts, args = getopt.getopt(sys.argv[1:], "hR:Ui:", \
                    ["help", "image-dir=", "update-all", "info-install="])
        except getopt.error, msg:
                print "%s, for help use --help" % msg
                sys.exit(2)

        if os.path.isabs(sys.argv[0]):
                app_path = sys.argv[0]
        else:
                cmd = os.path.join(os.getcwd(), sys.argv[0])
                app_path = os.path.realpath(cmd)

        for option, argument in opts:
                if option in ("-h", "--help"):
                        print """\
Use -R (--image-dir) to specify image directory.
Use -U (--update-all) to proceed with Updates"""
                        sys.exit(0)
                if option in ("-R", "--image-dir"):
                        image_dir = argument
                if option in ("-U", "--update-all"):
                        update_all_proceed = True
                if option in ("-i", "--info-install"):
                        info_install_arg = argument

        if image_dir == None:
                try:
                        image_dir = os.environ["PKG_IMAGE"]
                except KeyError:
                        image_dir = os.getcwd()
        try:
                gtk.init_check()
        except RuntimeError, e:
                print _("Unable to initialize gtk")
                print str(e)
                sys.exit(1)

        # Setup webinstall
        if info_install_arg or len(sys.argv) == 2 and not update_all_proceed:
                webinstall = webinstall.Webinstall(image_dir)
                if len(sys.argv) == 2:
                        info_install_arg = sys.argv[1]
                webinstall.process_param(info_install_arg)
                main()
                sys.exit(0)

        # Get original user name if running as root
        if portable.is_admin():
                original_id = portable.get_userid()
                if original_id:
                        try:
                                original_user = portable.get_username()
                        except EnvironmentError:
                                pass

        # Setup packagemanager
        packagemanager = PackageManager()
        packagemanager.application_path = app_path
        packagemanager.image_directory = image_dir
        packagemanager.update_all_proceed = update_all_proceed
        packagemanager.original_user = original_user

        while gtk.events_pending():
                gtk.main_iteration(False)

        max_filter_length = packagemanager.init_show_filter()

        gobject.idle_add(packagemanager.start)

        main()