def __init__(self, cache, db, distro, icons, datadir, show_ratings=False):
        gtk.VBox.__init__(self)
        # other classes we need
        self.cache = cache
        self.db = db
        self.distro = distro
        self.db.connect("reopen", self.on_db_reopen)
        self.icons = icons
        self.datadir = datadir
        # refreshes can happen out-of-bound so we need to be sure
        # that we only set the new model (when its available) if
        # the refresh_seq_nr of the ready model matches that of the
        # request (e.g. people click on ubuntu channel, get impatient, click
        # on partner channel)
        self.refresh_seq_nr = 0
        # common UI elements (applist and appdetails) 
        # its the job of the Child class to put it into a good location
        # list
        self.app_view = AppView(show_ratings)
        self.app_view.connect("application-selected", 
                              self.on_application_selected)
        self.scroll_app_list = gtk.ScrolledWindow()
        self.scroll_app_list.set_policy(gtk.POLICY_AUTOMATIC, 
                                        gtk.POLICY_AUTOMATIC)
        self.scroll_app_list.add(self.app_view)
        self.app_view.connect("application-activated", 
                              self.on_application_activated)
        self.app_view.connect("application-request-action", 
                              self.on_application_request_action)
        # details
        self.app_details = AppDetailsView(self.db, 
                                          self.distro,
                                          self.icons, 
                                          self.cache, 
                                          self.datadir)
        self.scroll_details = gtk.ScrolledWindow()
        self.scroll_details.set_policy(gtk.POLICY_AUTOMATIC, 
                                       gtk.POLICY_AUTOMATIC)
        self.scroll_details.add(self.app_details)

        # cursor
        self.busy_cursor = gtk.gdk.Cursor(gtk.gdk.WATCH)
        # when the cache changes, refresh the app list
        self.cache.connect("cache-ready", self.on_cache_ready)
        # COMMON UI elements
        # navigation bar and search on top in a hbox
        self.navigation_bar = NavigationBar()
        self.searchentry = SearchEntry()
        self.searchentry.connect("terms-changed", self.on_search_terms_changed)
        self.top_hbox = gtk.HBox()
        self.top_hbox.pack_start(self.navigation_bar, padding=self.PADDING)
        self.top_hbox.pack_start(self.searchentry, expand=False, padding=self.PADDING)
        self.pack_start(self.top_hbox, expand=False, padding=self.PADDING)
        # a notebook below
        self.notebook = gtk.Notebook()
        self.notebook.set_show_tabs(False)
        self.notebook.set_show_border(False)
        self.pack_start(self.notebook)
	def __init__(self):
		self.add_categories()
		self.build_matched_packages()
		self.add_packages()

		# Build the GUI
		gladefile = "/usr/lib/tuquito/tuquito-software-manager/tuquito-software-manager.glade"
		wTree = gtk.glade.XML(gladefile, "main_window")
		wTree.get_widget("main_window").set_title(_("Software Manager"))
		wTree.get_widget("main_window").set_icon_from_file("/usr/lib/tuquito/tuquito-software-manager/logo.svg")
		wTree.get_widget("main_window").connect("delete_event", self.close_application)

		self.transaction_loop = TransactionLoop(self, self.packages, wTree)
		self.transaction_loop.setDaemon(True)
		self.transaction_loop.start()

		self.prefs = self.read_configuration()

		# Build the menu
		fileMenu = gtk.MenuItem(_("_File"))
		fileSubmenu = gtk.Menu()
		fileMenu.set_submenu(fileSubmenu)
		closeMenuItem = gtk.ImageMenuItem(gtk.STOCK_CLOSE)
		closeMenuItem.get_child().set_text(_("Close"))
		closeMenuItem.connect("activate", self.close_application)
		fileSubmenu.append(closeMenuItem)

		editMenu = gtk.MenuItem(_("_Edit"))
		editSubmenu = gtk.Menu()
		editMenu.set_submenu(editSubmenu)
		prefsMenuItem = gtk.ImageMenuItem(gtk.STOCK_PREFERENCES)
		prefsMenuItem.get_child().set_text(_("Preferences"))
		prefsMenu = gtk.Menu()
		prefsMenuItem.set_submenu(prefsMenu)

		searchInSummaryMenuItem = gtk.CheckMenuItem(_("Search in packages summary (slower search)"))
		searchInSummaryMenuItem.set_active(self.prefs["search_in_summary"])
		searchInSummaryMenuItem.connect("toggled", self.set_search_filter, "search_in_summary")

		searchInDescriptionMenuItem = gtk.CheckMenuItem(_("Search in packages description (even slower search)"))
		searchInDescriptionMenuItem.set_active(self.prefs["search_in_description"])
		searchInDescriptionMenuItem.connect("toggled", self.set_search_filter, "search_in_description")

		openLinkExternalMenuItem = gtk.CheckMenuItem(_("Open links using the web browser"))
		openLinkExternalMenuItem.set_active(self.prefs["external_browser"])
		openLinkExternalMenuItem.connect("toggled", self.set_external_browser)

		prefsMenu.append(searchInSummaryMenuItem)
		prefsMenu.append(searchInDescriptionMenuItem)
		prefsMenu.append(openLinkExternalMenuItem)

		editSubmenu.append(prefsMenuItem)

		accountMenuItem = gtk.ImageMenuItem(gtk.STOCK_PREFERENCES)
		accountMenuItem.get_child().set_text(_("Account information"))
		accountMenuItem.connect("activate", self.open_account_info)
		editSubmenu.append(accountMenuItem)

		if os.path.exists("/usr/bin/software-properties-gtk") or os.path.exists("/usr/bin/software-properties-kde"):
			sourcesMenuItem = gtk.ImageMenuItem(gtk.STOCK_PREFERENCES)
			sourcesMenuItem.set_image(gtk.image_new_from_file("/usr/lib/tuquito/tuquito-software-manager/data/software-properties.png"))
			sourcesMenuItem.get_child().set_text(_("Software sources"))
			sourcesMenuItem.connect("activate", self.open_repositories)
			editSubmenu.append(sourcesMenuItem)

		viewMenu = gtk.MenuItem(_("_View"))
		viewSubmenu = gtk.Menu()
		viewMenu.set_submenu(viewSubmenu)

		availablePackagesMenuItem = gtk.CheckMenuItem(_("Available packages"))
		availablePackagesMenuItem.set_active(self.prefs["available_packages_visible"])
		availablePackagesMenuItem.connect("toggled", self.set_filter, "available_packages_visible")

		installedPackagesMenuItem = gtk.CheckMenuItem(_("Installed packages"))
		installedPackagesMenuItem.set_active(self.prefs["installed_packages_visible"])
		installedPackagesMenuItem.connect("toggled", self.set_filter, "installed_packages_visible")

		viewSubmenu.append(availablePackagesMenuItem)
		viewSubmenu.append(installedPackagesMenuItem)

		helpMenu = gtk.MenuItem(_("_Help"))
		helpSubmenu = gtk.Menu()
		helpMenu.set_submenu(helpSubmenu)
		aboutMenuItem = gtk.ImageMenuItem(gtk.STOCK_ABOUT)
		aboutMenuItem.get_child().set_text(_("About"))
		aboutMenuItem.connect("activate", self.open_about)
		helpSubmenu.append(aboutMenuItem)

		wTree.get_widget("menubar1").append(fileMenu)
		wTree.get_widget("menubar1").append(editMenu)
		wTree.get_widget("menubar1").append(viewMenu)
		wTree.get_widget("menubar1").append(helpMenu)

		# Build the applications tables
		self.tree_applications = wTree.get_widget("tree_applications")
		self.tree_search = wTree.get_widget("tree_search")
		self.tree_transactions = wTree.get_widget("tree_transactions")

		self.build_application_tree(self.tree_applications)
		self.build_application_tree(self.tree_search)
		self.build_transactions_tree(self.tree_transactions)

		self.navigation_bar = NavigationBar()
		self.searchentry = SearchEntry()
		self.searchentry.connect("terms-changed", self.on_search_terms_changed)
		top_hbox = gtk.HBox()
		top_hbox.pack_start(self.navigation_bar, padding=6)
		top_hbox.pack_start(self.searchentry, expand=False, padding=6)
		wTree.get_widget("toolbar").pack_start(top_hbox, expand=False, padding=6)

		self.notebook = wTree.get_widget("notebook1")

		# Build the category browsers
		self.browser = webkit.WebView()
		template = open("/usr/lib/tuquito/tuquito-software-manager/data/templates/CategoriesView.html").read()
		subs = {'header': _("Categories")}
		subs['select'] = _("Select a category...")
		html = string.Template(template).safe_substitute(subs)
		self.browser.load_html_string(html, "file:/")
		self.browser.connect("load-finished", self._on_load_finished)
	 	self.browser.connect('title-changed', self._on_title_changed)
		wTree.get_widget("scrolled_categories").add(self.browser)

		self.browser2 = webkit.WebView()
		template = open("/usr/lib/tuquito/tuquito-software-manager/data/templates/CategoriesView.html").read()
		subs = {'header': _("Categories")}
		subs['select'] = _("Select a category...")
		html = string.Template(template).safe_substitute(subs)
		self.browser2.load_html_string(html, "file:/")
	 	self.browser2.connect('title-changed', self._on_title_changed)
		wTree.get_widget("scrolled_mixed_categories").add(self.browser2)

		self.packageBrowser = webkit.WebView()
		wTree.get_widget("scrolled_details").add(self.packageBrowser)

		self.packageBrowser.connect('title-changed', self._on_title_changed)

		#self.screenshotBrowser = webkit.WebView()
		#wTree.get_widget("scrolled_screenshot").add(self.screenshotBrowser)

		self.websiteBrowser = webkit.WebView()
		wTree.get_widget("scrolled_website").add(self.websiteBrowser)

		# kill right click menus in webkit views
	        self.browser.connect("button-press-event", lambda w, e: e.button == 3)
		self.browser2.connect("button-press-event", lambda w, e: e.button == 3)
		self.packageBrowser.connect("button-press-event", lambda w, e: e.button == 3)

		wTree.get_widget("label_transactions_header").set_text(_("Active tasks:"))

		wTree.get_widget("button_transactions").connect("clicked", self.show_transactions)

		wTree.get_widget("main_window").show_all()
		wTree.get_widget("button_transactions").hide()
		splash.window.hide()
class Application():
	PAGE_CATEGORIES = 0
	PAGE_MIXED = 1
	PAGE_PACKAGES = 2
	PAGE_DETAILS = 3
	PAGE_SCREENSHOT = 4
	PAGE_WEBSITE = 5
	PAGE_SEARCH = 6
	PAGE_TRANSACTIONS = 7

	NAVIGATION_HOME = 1
	NAVIGATION_SEARCH = 2
	NAVIGATION_CATEGORY = 3
	NAVIGATION_SUB_CATEGORY = 4
	NAVIGATION_ITEM = 5
	NAVIGATION_SCREENSHOT = 6
	NAVIGATION_WEBSITE = 6

	def __init__(self):
		self.add_categories()
		self.build_matched_packages()
		self.add_packages()

		# Build the GUI
		gladefile = "/usr/lib/tuquito/tuquito-software-manager/tuquito-software-manager.glade"
		wTree = gtk.glade.XML(gladefile, "main_window")
		wTree.get_widget("main_window").set_title(_("Software Manager"))
		wTree.get_widget("main_window").set_icon_from_file("/usr/lib/tuquito/tuquito-software-manager/logo.svg")
		wTree.get_widget("main_window").connect("delete_event", self.close_application)

		self.transaction_loop = TransactionLoop(self, self.packages, wTree)
		self.transaction_loop.setDaemon(True)
		self.transaction_loop.start()

		self.prefs = self.read_configuration()

		# Build the menu
		fileMenu = gtk.MenuItem(_("_File"))
		fileSubmenu = gtk.Menu()
		fileMenu.set_submenu(fileSubmenu)
		closeMenuItem = gtk.ImageMenuItem(gtk.STOCK_CLOSE)
		closeMenuItem.get_child().set_text(_("Close"))
		closeMenuItem.connect("activate", self.close_application)
		fileSubmenu.append(closeMenuItem)

		editMenu = gtk.MenuItem(_("_Edit"))
		editSubmenu = gtk.Menu()
		editMenu.set_submenu(editSubmenu)
		prefsMenuItem = gtk.ImageMenuItem(gtk.STOCK_PREFERENCES)
		prefsMenuItem.get_child().set_text(_("Preferences"))
		prefsMenu = gtk.Menu()
		prefsMenuItem.set_submenu(prefsMenu)

		searchInSummaryMenuItem = gtk.CheckMenuItem(_("Search in packages summary (slower search)"))
		searchInSummaryMenuItem.set_active(self.prefs["search_in_summary"])
		searchInSummaryMenuItem.connect("toggled", self.set_search_filter, "search_in_summary")

		searchInDescriptionMenuItem = gtk.CheckMenuItem(_("Search in packages description (even slower search)"))
		searchInDescriptionMenuItem.set_active(self.prefs["search_in_description"])
		searchInDescriptionMenuItem.connect("toggled", self.set_search_filter, "search_in_description")

		openLinkExternalMenuItem = gtk.CheckMenuItem(_("Open links using the web browser"))
		openLinkExternalMenuItem.set_active(self.prefs["external_browser"])
		openLinkExternalMenuItem.connect("toggled", self.set_external_browser)

		prefsMenu.append(searchInSummaryMenuItem)
		prefsMenu.append(searchInDescriptionMenuItem)
		prefsMenu.append(openLinkExternalMenuItem)

		editSubmenu.append(prefsMenuItem)

		accountMenuItem = gtk.ImageMenuItem(gtk.STOCK_PREFERENCES)
		accountMenuItem.get_child().set_text(_("Account information"))
		accountMenuItem.connect("activate", self.open_account_info)
		editSubmenu.append(accountMenuItem)

		if os.path.exists("/usr/bin/software-properties-gtk") or os.path.exists("/usr/bin/software-properties-kde"):
			sourcesMenuItem = gtk.ImageMenuItem(gtk.STOCK_PREFERENCES)
			sourcesMenuItem.set_image(gtk.image_new_from_file("/usr/lib/tuquito/tuquito-software-manager/data/software-properties.png"))
			sourcesMenuItem.get_child().set_text(_("Software sources"))
			sourcesMenuItem.connect("activate", self.open_repositories)
			editSubmenu.append(sourcesMenuItem)

		viewMenu = gtk.MenuItem(_("_View"))
		viewSubmenu = gtk.Menu()
		viewMenu.set_submenu(viewSubmenu)

		availablePackagesMenuItem = gtk.CheckMenuItem(_("Available packages"))
		availablePackagesMenuItem.set_active(self.prefs["available_packages_visible"])
		availablePackagesMenuItem.connect("toggled", self.set_filter, "available_packages_visible")

		installedPackagesMenuItem = gtk.CheckMenuItem(_("Installed packages"))
		installedPackagesMenuItem.set_active(self.prefs["installed_packages_visible"])
		installedPackagesMenuItem.connect("toggled", self.set_filter, "installed_packages_visible")

		viewSubmenu.append(availablePackagesMenuItem)
		viewSubmenu.append(installedPackagesMenuItem)

		helpMenu = gtk.MenuItem(_("_Help"))
		helpSubmenu = gtk.Menu()
		helpMenu.set_submenu(helpSubmenu)
		aboutMenuItem = gtk.ImageMenuItem(gtk.STOCK_ABOUT)
		aboutMenuItem.get_child().set_text(_("About"))
		aboutMenuItem.connect("activate", self.open_about)
		helpSubmenu.append(aboutMenuItem)

		wTree.get_widget("menubar1").append(fileMenu)
		wTree.get_widget("menubar1").append(editMenu)
		wTree.get_widget("menubar1").append(viewMenu)
		wTree.get_widget("menubar1").append(helpMenu)

		# Build the applications tables
		self.tree_applications = wTree.get_widget("tree_applications")
		self.tree_search = wTree.get_widget("tree_search")
		self.tree_transactions = wTree.get_widget("tree_transactions")

		self.build_application_tree(self.tree_applications)
		self.build_application_tree(self.tree_search)
		self.build_transactions_tree(self.tree_transactions)

		self.navigation_bar = NavigationBar()
		self.searchentry = SearchEntry()
		self.searchentry.connect("terms-changed", self.on_search_terms_changed)
		top_hbox = gtk.HBox()
		top_hbox.pack_start(self.navigation_bar, padding=6)
		top_hbox.pack_start(self.searchentry, expand=False, padding=6)
		wTree.get_widget("toolbar").pack_start(top_hbox, expand=False, padding=6)

		self.notebook = wTree.get_widget("notebook1")

		# Build the category browsers
		self.browser = webkit.WebView()
		template = open("/usr/lib/tuquito/tuquito-software-manager/data/templates/CategoriesView.html").read()
		subs = {'header': _("Categories")}
		subs['select'] = _("Select a category...")
		html = string.Template(template).safe_substitute(subs)
		self.browser.load_html_string(html, "file:/")
		self.browser.connect("load-finished", self._on_load_finished)
	 	self.browser.connect('title-changed', self._on_title_changed)
		wTree.get_widget("scrolled_categories").add(self.browser)

		self.browser2 = webkit.WebView()
		template = open("/usr/lib/tuquito/tuquito-software-manager/data/templates/CategoriesView.html").read()
		subs = {'header': _("Categories")}
		subs['select'] = _("Select a category...")
		html = string.Template(template).safe_substitute(subs)
		self.browser2.load_html_string(html, "file:/")
	 	self.browser2.connect('title-changed', self._on_title_changed)
		wTree.get_widget("scrolled_mixed_categories").add(self.browser2)

		self.packageBrowser = webkit.WebView()
		wTree.get_widget("scrolled_details").add(self.packageBrowser)

		self.packageBrowser.connect('title-changed', self._on_title_changed)

		#self.screenshotBrowser = webkit.WebView()
		#wTree.get_widget("scrolled_screenshot").add(self.screenshotBrowser)

		self.websiteBrowser = webkit.WebView()
		wTree.get_widget("scrolled_website").add(self.websiteBrowser)

		# kill right click menus in webkit views
	        self.browser.connect("button-press-event", lambda w, e: e.button == 3)
		self.browser2.connect("button-press-event", lambda w, e: e.button == 3)
		self.packageBrowser.connect("button-press-event", lambda w, e: e.button == 3)

		wTree.get_widget("label_transactions_header").set_text(_("Active tasks:"))

		wTree.get_widget("button_transactions").connect("clicked", self.show_transactions)

		wTree.get_widget("main_window").show_all()
		wTree.get_widget("button_transactions").hide()
		splash.window.hide()

	def on_search_terms_changed(self, searchentry, terms):
		if terms != "":
			self.show_search_results(terms)

	def set_filter(self, checkmenuitem, configName):
		config = ConfigParser.ConfigParser()
		config.add_section("filter")
		if configName == "available_packages_visible":
			config.set("filter", "installed_packages_visible", self.prefs["installed_packages_visible"])
		else:
			config.set("filter", "available_packages_visible", self.prefs["available_packages_visible"])
		config.set("filter", configName, checkmenuitem.get_active())
		config.add_section("search")
		config.set("search", "search_in_summary", self.prefs["search_in_summary"])
		config.set("search", "search_in_description", self.prefs["search_in_description"])
		config.add_section("general")
		config.set("general", "external_browser", self.prefs["external_browser"])
		config.write(open(home + "/.tuquito/tuquito-software-manager/tuquito-software-manager.conf", 'w'))
		self.prefs = self.read_configuration()
		if self.model_filter is not None:
			self.model_filter.refilter()

	def set_search_filter(self, checkmenuitem, configName):
		config = ConfigParser.ConfigParser()
		config.add_section("search")
		if configName == "search_in_description":
			config.set("search", "search_in_summary", self.prefs["search_in_summary"])
		else:
			config.set("search", "search_in_description", self.prefs["search_in_description"])
		config.set("search", configName, checkmenuitem.get_active())
		config.add_section("filter")
		config.set("filter", "available_packages_visible", self.prefs["available_packages_visible"])
		config.set("filter", "installed_packages_visible", self.prefs["installed_packages_visible"])
		config.add_section("general")
		config.set("general", "external_browser", self.prefs["external_browser"])
		config.write(open(home + "/.tuquito/tuquito-software-manager/tuquito-software-manager.conf", 'w'))
		self.prefs = self.read_configuration()
		if self.searchentry.get_text() != "":
			self.show_search_results(self.searchentry.get_text())

	def set_external_browser(self, checkmenuitem):
		config = ConfigParser.ConfigParser()
		config.add_section("general")
		config.set("general", "external_browser", checkmenuitem.get_active())
		config.add_section("filter")
		config.set("filter", "available_packages_visible", self.prefs["available_packages_visible"])
		config.set("filter", "installed_packages_visible", self.prefs["installed_packages_visible"])
		config.add_section("search")
		config.set("search", "search_in_summary", self.prefs["search_in_summary"])
		config.set("search", "search_in_description", self.prefs["search_in_description"])
		config.write(open(home + "/.tuquito/tuquito-software-manager/tuquito-software-manager.conf", 'w'))
		self.prefs = self.read_configuration()

	def read_configuration(self, conf=None):
		# Lee la configuración
		config = ConfigParser.ConfigParser()
		config.read(home + "/.tuquito/tuquito-software-manager/account.conf")
		prefs = {}
		#Read account info
		try:
			prefs["username"] = config.get('account', 'username')
			prefs["password"] = config.get('account', 'password')
		except:
			prefs["username"] = ""
			prefs["password"] = ""

		config = ConfigParser.ConfigParser()
		config.read(home + "/.tuquito/tuquito-software-manager/tuquito-software-manager.conf")
		#Read filter info
		try:
			prefs["available_packages_visible"] = config.getboolean("filter", "available_packages_visible")
		except:
			prefs["available_packages_visible"] = True
		try:
			prefs["installed_packages_visible"] = config.getboolean("filter", "installed_packages_visible")
		except:
			prefs["installed_packages_visible"] = True

		#Read search info
		try:
			prefs["search_in_summary"] = config.getboolean("search", "search_in_summary")
		except:
			prefs["search_in_summary"] = False
		try:
			prefs["search_in_description"] = config.getboolean("search", "search_in_description")
		except:
			prefs["search_in_description"] = False

		#External browser
		try:
			prefs["external_browser"] = config.getboolean("general", "external_browser")
		except:
			prefs["external_browser"] = False
		return prefs

	def open_repositories(self, widget):
		if os.path.exists("/usr/bin/software-properties-gtk"):
			os.system("gksu /usr/bin/software-properties-gtk -D '%s'" % _("Software sources"))
		else:
			os.system("gksu /usr/bin/software-properties-kde -D '%s'" % _("Software sources"))
		self.close_application(None, None, 9) # Status code 9 means we want to restart ourselves

	def close_window(self, widget, window):
		window.hide()

	def open_account_info(self, widget):
		gladefile = "/usr/lib/tuquito/tuquito-software-manager/tuquito-software-manager.glade"
		wTree = gtk.glade.XML(gladefile, "window_account")
		wTree.get_widget("window_account").set_title(_("Account information"))
		wTree.get_widget("label1").set_label("<b>%s</b>" % _("Your community account"))
		wTree.get_widget("label1").set_use_markup(True)
		wTree.get_widget("label2").set_label("<i><small>%s</small></i>" % _("Enter your account info to post comments"))
		wTree.get_widget("label2").set_use_markup(True)
		wTree.get_widget("label3").set_label(_("Username:"******"label4").set_label(_("Password:"******"entry_username").set_text(self.prefs["username"])
		wTree.get_widget("entry_password").set_text(base64.b64decode(self.prefs["password"]))
		wTree.get_widget("close_button").connect("clicked", self.close_window, wTree.get_widget("window_account"))
		wTree.get_widget("save_button").connect("clicked", self.update_account_info, wTree)
		wTree.get_widget("window_account").show_all()

	def show_account_message(self):
		gladefile = "/usr/lib/tuquito/tuquito-software-manager/tuquito-software-manager.glade"
		wTree = gtk.glade.XML(gladefile, "account_message")
		wTree.get_widget("account_message").set_title(_("Message"))
		wTree.get_widget("label1").set_markup(_("<big><b>You need a user account</b></big>"))
		wTree.get_widget("label2").set_markup(_("To comment you need to be registered.\nIf you already have an account just enter your data in: <b>Edit > Account information</b>.\nWhat want you do?"))
		wTree.get_widget("label3").set_label(_("I'm not registered but want do it"))
		wTree.get_widget("label4").set_label(_("I have an account, I will add my data"))
		wTree.get_widget("linkbutton1").connect("clicked", self.close_window, wTree.get_widget("account_message"))
		wTree.get_widget("button2").connect("clicked", self.add_data_account, wTree.get_widget("account_message"))
		wTree.get_widget("account_message").show_all()

	def add_data_account(self, widget, window):
		self.close_window(widget, window)
		self.open_account_info(widget)

	def close_window(self, widget, window):
		window.hide()

	def update_account_info(self, widteg, data=None):
		config = ConfigParser.ConfigParser()
		config.add_section("account")
		username = data.get_widget("entry_username").get_text()
		password = base64.b64encode(data.get_widget("entry_password").get_text())
		config.set("account", "username", username)
		config.set("account", "password", password)
		config.write(open(home + "/.tuquito/tuquito-software-manager/account.conf", 'w'))
		self.prefs = self.read_configuration()
		data.get_widget("window_account").hide()

	def open_about(self, widget):
		os.system('/usr/lib/tuquito/tuquito-software-manager/about.py &')

	def show_transactions(self, widget):
		self.notebook.set_current_page(self.PAGE_TRANSACTIONS)

	def close_window(self, widget, window, extra=None):
		try:
			window.hide_all()
		except:
			pass

	def build_application_tree(self, treeview):
		column0 = gtk.TreeViewColumn(_("Icon"), gtk.CellRendererPixbuf(), pixbuf=0)
		column0.set_sort_column_id(0)
		column0.set_resizable(True)
		column0.set_alignment(1)
		column0.set_min_width(70)
		column0.set_max_width(70)

		column1 = gtk.TreeViewColumn(_("Application"), gtk.CellRendererText(), markup=1)
		column1.set_sort_column_id(2)
		column1.set_resizable(True)
		column1.set_sizing(gtk.TREE_VIEW_COLUMN_FIXED)
		column1.set_min_width(350)
		column1.set_max_width(350)

		treeview.append_column(column0)
		treeview.append_column(column1)
		treeview.show()

		selection = treeview.get_selection()
		selection.set_mode(gtk.SELECTION_SINGLE)
		selection.connect("changed", self.show_selected)

	def build_transactions_tree(self, treeview):
		column0 = gtk.TreeViewColumn(_("Task"), gtk.CellRendererText(), text=0)
		column0.set_resizable(True)

		column1 = gtk.TreeViewColumn(_("Status"), gtk.CellRendererText(), text=1)
		column1.set_resizable(True)

		column2 = gtk.TreeViewColumn(_("Progress"), gtk.CellRendererProgress(), text=2, value=3)
		column2.set_resizable(True)

		treeview.append_column(column0)
		treeview.append_column(column1)
		treeview.append_column(column2)
		treeview.show()

	def show_selected(self, selection):
		(model, iter) = selection.get_selected()
		if iter != None:
			self.selected_package = model.get_value(iter, 3)
			self.show_package(self.selected_package)
			selection.unselect_all()

	def navigate(self, button, destination):
		if destination == "search":
			self.notebook.set_current_page(self.PAGE_SEARCH)
		else:
			self.searchentry.set_text("")
			if isinstance(destination, Category):
				if len(destination.subcategories) > 0:
					if len(destination.packages) > 0:
						self.notebook.set_current_page(self.PAGE_MIXED)
					else:
						self.notebook.set_current_page(self.PAGE_CATEGORIES)
				else:
					self.notebook.set_current_page(self.PAGE_PACKAGES)
			elif isinstance(destination, Package):
				self.notebook.set_current_page(self.PAGE_DETAILS)
			elif destination == "screenshot":
				self.notebook.set_current_page(self.PAGE_SCREENSHOT)
			else:
				self.notebook.set_current_page(self.PAGE_WEBSITE)

	def close_application(self, window, event=None, exit_code=0):
		if exit_code == 0:
			pid = os.getpid()
			os.system("kill -9 %d &" % pid)
		else:
			global shutdown_flag
			shutdown_flag = True
			gtk.main_quit()
			sys.exit(exit_code)

	def _on_load_finished(self, view, frame):
		# Get the categories
		self.show_category(self.root_category)

	def on_category_clicked(self, name):
		for category in self.categories:
		    if category.name == name:
			self.show_category(category)

	def on_button_clicked(self):
		package = self.current_package
		if package != None:
			if package.pkg.is_installed:
				os.system("/usr/lib/tuquito/tuquito-software-manager/aptd_client.py remove %s &" % package.pkg.name)
			else:
				os.system("/usr/lib/tuquito/tuquito-software-manager/aptd_client.py install %s &" % package.pkg.name)

	def on_screenshot_clicked(self):
		package = self.current_package
		if package is not None:
			url = "http://community.linuxmint.com/img/screenshots/" + package.pkg.name + ".png"
			self.websiteBrowser.open(url)
			self.navigation_bar.add_with_id(_("Screenshot"), self.navigate, self.NAVIGATION_WEBSITE, "website")

	def on_website_clicked(self):
		package = self.current_package
		if package != None:
			url = self.current_package.pkg.candidate.homepage
			if self.prefs['external_browser']:
				os.system("xdg-open " + url + " &")
			else:
				self.websiteBrowser.open(url)
				self.navigation_bar.add_with_id(_("Website"), self.navigate, self.NAVIGATION_WEBSITE, "website")

	def on_comment_clicked(self):
		package = self.current_package
		if package != None:
			url = "http://apps.tuquito.org.ar/comment.php?name=" + package.pkg.name + "&limit=false"
			self.websiteBrowser.open(url)
			self.navigation_bar.add_with_id(_("Comments"), self.navigate, self.NAVIGATION_WEBSITE, "website")

	def _on_title_changed(self, view, frame, title):
		# no op - needed to reset the title after a action so that
		#         the action can be triggered again
		if title.startswith("nop"):
		    return
		# call directive looks like:
		#  "call:func:arg1,arg2"
		#  "call:func"
		if title.startswith("call:"):
			args_str = ""
			args_list = []
			# try long form (with arguments) first
			try:
				(t,funcname,args_str) = title.split(":")
			except ValueError:
				# now try short (without arguments)
				(t,funcname) = title.split(":")
			if args_str:
				args_list = args_str.split(",")
			# see if we have it and if it can be called
			f = getattr(self, funcname)
			if f and callable(f):
				f(*args_list)
			# now we need to reset the title
			self.browser.execute_script('document.title = "nop"')

	def add_categories(self):
		self.categories = []
		self.root_category = Category(_("Categories"), "applications-other", None, None, self.categories)
		featured = Category(_("Featured"), "gtk-about", None, self.root_category, self.categories)
		featured.matchingPackages = self.file_to_array("/usr/lib/tuquito/tuquito-software-manager/categories/featured.list")

		Category(_("Accessories"), "applications-utilities", ("accessories", "utils"), self.root_category, self.categories)

		subcat = Category(_("Access"), "access", None, self.root_category, self.categories)
		subcat.matchingPackages = self.file_to_array("/usr/lib/tuquito/tuquito-software-manager/categories/access.list")

		subcat = Category(_("Education"), "applications-accessories", ("education", "math"), self.root_category, self.categories)
		subcat.matchingPackages = self.file_to_array("/usr/lib/tuquito/tuquito-software-manager/categories/education.list")

		subcat = Category(_("Fonts"), "applications-fonts", None, self.root_category, self.categories)
		subcat.matchingPackages = self.file_to_array("/usr/lib/tuquito/tuquito-software-manager/categories/fonts.list")

		games = Category(_("Games"), "applications-games", ("games"), self.root_category, self.categories)
		subcat = Category(_("Board games"), "applications-games", None, games, self.categories)
		subcat.matchingPackages = self.file_to_array("/usr/lib/tuquito/tuquito-software-manager/categories/games-board.list")
		subcat = Category(_("First-person shooters"), "applications-games", None, games, self.categories)
		subcat.matchingPackages = self.file_to_array("/usr/lib/tuquito/tuquito-software-manager/categories/games-fps.list")
		subcat = Category(_("Real-time strategy"), "applications-games", None, games, self.categories)
		subcat.matchingPackages = self.file_to_array("/usr/lib/tuquito/tuquito-software-manager/categories/games-rts.list")
		subcat = Category(_("Turn-based strategy"), "applications-games", None, games, self.categories)
		subcat.matchingPackages = self.file_to_array("/usr/lib/tuquito/tuquito-software-manager/categories/games-tbs.list")
		subcat = Category(_("Emulators"), "applications-games", None, games, self.categories)
		subcat.matchingPackages = self.file_to_array("/usr/lib/tuquito/tuquito-software-manager/categories/games-emulators.list")
		subcat = Category(_("Simulation and racing"), "applications-games", None, games, self.categories)
		subcat.matchingPackages = self.file_to_array("/usr/lib/tuquito/tuquito-software-manager/categories/games-simulations.list")

		graphics = Category(_("Graphics"), "applications-graphics", ("graphics"), self.root_category, self.categories)
		graphics.matchingPackages = self.file_to_array("/usr/lib/tuquito/tuquito-software-manager/categories/graphics.list")
		subcat = Category(_("3D"), "applications-graphics", None, graphics, self.categories)
		subcat.matchingPackages = self.file_to_array("/usr/lib/tuquito/tuquito-software-manager/categories/graphics-3d.list")
		subcat = Category(_("Drawing"), "applications-graphics", None, graphics, self.categories)
		subcat.matchingPackages = self.file_to_array("/usr/lib/tuquito/tuquito-software-manager/categories/graphics-drawing.list")
		subcat = Category(_("Photography"), "applications-graphics", None, graphics, self.categories)
		subcat.matchingPackages = self.file_to_array("/usr/lib/tuquito/tuquito-software-manager/categories/graphics-photography.list")
		subcat = Category(_("Publishing"), "applications-graphics", None, graphics, self.categories)
		subcat.matchingPackages = self.file_to_array("/usr/lib/tuquito/tuquito-software-manager/categories/graphics-publishing.list")
		subcat = Category(_("Scanning"), "applications-graphics", None, graphics, self.categories)
		subcat.matchingPackages = self.file_to_array("/usr/lib/tuquito/tuquito-software-manager/categories/graphics-scanning.list")
		subcat = Category(_("Viewers"), "applications-graphics", None, graphics, self.categories)
		subcat.matchingPackages = self.file_to_array("/usr/lib/tuquito/tuquito-software-manager/categories/graphics-viewers.list")

		internet = Category(_("Internet"), "applications-internet", ("mail", "web", "net"), self.root_category, self.categories)
		subcat = Category(_("Web"), "applications-internet", None, internet, self.categories)
		subcat.matchingPackages = self.file_to_array("/usr/lib/tuquito/tuquito-software-manager/categories/internet-web.list")
		subcat = Category(_("Email"), "applications-internet", None, internet, self.categories)
		subcat.matchingPackages = self.file_to_array("/usr/lib/tuquito/tuquito-software-manager/categories/internet-email.list")
		subcat = Category(_("Chat"), "applications-internet", None, internet, self.categories)
		subcat.matchingPackages = self.file_to_array("/usr/lib/tuquito/tuquito-software-manager/categories/internet-chat.list")
		subcat = Category(_("File sharing"), "applications-internet", None, internet, self.categories)
		subcat.matchingPackages = self.file_to_array("/usr/lib/tuquito/tuquito-software-manager/categories/internet-filesharing.list")

		Category(_("Office"), "applications-office", ("office", "editors"), self.root_category, self.categories)
		Category(_("Science"), "applications-science", ("science", "math"), self.root_category, self.categories)

		soundvideo = Category(_("Sound and video"), "applications-multimedia", ("multimedia", "video"), self.root_category, self.categories)
		subcat = Category(_("Players"), "applications-multimedia", None, soundvideo, self.categories)
		subcat.matchingPackages = self.file_to_array("/usr/lib/tuquito/tuquito-software-manager/categories/sound-video-players.list")
		subcat = Category(_("Editors"), "applications-multimedia", None, soundvideo, self.categories)
		subcat.matchingPackages = self.file_to_array("/usr/lib/tuquito/tuquito-software-manager/categories/sound-video-editors.list")
		subcat = Category(_("Multimedia"), "applications-multimedia", None, soundvideo, self.categories)
		subcat.matchingPackages = self.file_to_array("/usr/lib/tuquito/tuquito-software-manager/categories/sound-video-other.list")

		subcat = Category(_("Themes and tweaks"), "preferences-other", None, self.root_category, self.categories)
		subcat.matchingPackages = self.file_to_array("/usr/lib/tuquito/tuquito-software-manager/categories/themes-tweaks.list")

		subcat = Category(_("System tools"), "applications-system", ("system", "admin"), self.root_category, self.categories)
		subcat.matchingPackages = self.file_to_array("/usr/lib/tuquito/tuquito-software-manager/categories/system-tools.list")

		Category(_("Programming"), "applications-development", ("devel"), self.root_category, self.categories)

		self.category_all = Category(_("Other"), "applications-other", None, self.root_category, self.categories)

	def file_to_array(self, filename):
		array = []
		f = open(filename)
		for line in f:
			line = line.replace("\n","").replace("\r","").strip();
			if line != "":
				array.append(line)
		return array

	def build_matched_packages(self):
		# Build a list of matched packages
		self.matchedPackages = []
		for category in self.categories:
			self.matchedPackages.extend(category.matchingPackages)
		self.matchedPackages.sort()

	def add_packages(self):
		self.packages = []
		self.packages_dict = {}
		cache = apt.Cache()
		for pkg in cache:
			package = Package(pkg.name, pkg)
			self.packages.append(package)
			self.packages_dict[pkg.name] = package
			self.category_all.packages.append(package)

			# If the package is not a "matching package", find categories with matching sections
			if pkg.name not in self.matchedPackages:
				section = pkg.section
				if "/" in section:
					section = section.split("/")[1]
				for category in self.categories:
					if category.sections is not None:
						if section in category.sections:
							self.add_package_to_category(package, category)

		# Process matching packages
		for category in self.categories:
			for package_name in category.matchingPackages:
				if package_name in self.packages_dict:
					package = self.packages_dict[package_name]
					self.add_package_to_category(package, category)

	def add_package_to_category(self, package, category):
		if category.parent is not None:
			if category not in package.categories:
				package.categories.append(category)
				category.packages.append(package)
			self.add_package_to_category(package, category.parent)

	def show_category(self, category):
		# Load subcategories
		if len(category.subcategories) > 0:
			if len(category.packages) == 0:
				# Show categories page
				browser = self.browser
			else:
				# Show mixed page
				browser = self.browser2

			theme = gtk.icon_theme_get_default()
			browser.execute_script('clearCategories()')
			for cat in category.subcategories:
				if theme.has_icon(cat.icon):
					iconInfo = theme.lookup_icon(cat.icon, 42, 0)
				else:
					iconInfo = theme.lookup_icon("applications-other", 42, 0)

				if iconInfo and os.path.exists(iconInfo.get_filename()):
					icon = iconInfo.get_filename()
				browser.execute_script('addCategory("%s", "%s", "%s")' % (cat.name, _("%d packages") % len(cat.packages), icon))
			browser.execute_script('animateItems()')

		# Load packages into self.tree_applications
		tree_applications = self.tree_applications
		model_applications = gtk.TreeStore(gtk.gdk.Pixbuf, str, gtk.gdk.Pixbuf, object)

		self.model_filter = model_applications.filter_new()
		self.model_filter.set_visible_func(self.visible_func)

		category.packages.sort()
		for package in category.packages[0:500]:
			if package.name in COMMERCIAL_APPS:
				continue

			if not (package.pkg.name.endswith(":i386") or package.pkg.name.endswith(":amd64")):
				iter = model_applications.insert_before(None, None)
				try:
					model_applications.set_value(iter, 0, gtk.gdk.pixbuf_new_from_file_at_size(self.find_app_icon(package), 32, 32))
				except:
					try:
						model_applications.set_value(iter, 0, gtk.gdk.pixbuf_new_from_file_at_size(self.find_app_icon_alternative(package), 32, 32))
					except:
						model_applications.set_value(iter, 0, gtk.gdk.pixbuf_new_from_file_at_size(self.find_fallback_icon(package), 32, 32))
				summary = ""
				if package.pkg.candidate is not None:
					summary = package.pkg.candidate.summary
					summary = unicode(summary, 'UTF-8', 'replace')
					summary = summary.replace("<", "&lt;")
					summary = summary.replace("&", "&amp;")

				model_applications.set_value(iter, 1, "%s\n<small><span foreground='#555555'>%s</span></small>" % (package.name, summary.capitalize()))

				model_applications.set_value(iter, 3, package)

		tree_applications.set_model(self.model_filter)
		first = model_applications.get_iter_first()
		del model_applications

		# Update the navigation bar
		if category == self.root_category:
			self.navigation_bar.add_with_id(category.name, self.navigate, self.NAVIGATION_HOME, category)
		elif category.parent == self.root_category:
			self.navigation_bar.add_with_id(category.name, self.navigate, self.NAVIGATION_CATEGORY, category)
		else:
			self.navigation_bar.add_with_id(category.name, self.navigate, self.NAVIGATION_SUB_CATEGORY, category)

	def find_fallback_icon(self, package):
		icon_path = None
		if package.pkg.is_installed:
			icon_path = "/usr/lib/tuquito/tuquito-software-manager/data/installed.png"
		else:
			icon_path = "/usr/lib/tuquito/tuquito-software-manager/data/available.png"
		return icon_path

	def find_app_icon_alternative(self, package):
		icon_path = None
		if package.pkg.is_installed:
			icon_path = "/usr/share/tuquito/tuquito-software-manager/installed/%s" % package.name
			if os.path.exists(icon_path + ".png"):
				icon_path = icon_path + ".png"
			elif os.path.exists(icon_path + ".xpm"):
				icon_path = icon_path + ".xpm"
			else:
				# Else, default to generic icons
				icon_path = "/usr/lib/tuquito/tuquito-software-manager/data/installed.png"
		else:
			# Try the Icon theme first
			theme = gtk.icon_theme_get_default()
			if theme.has_icon(package.name):
				iconInfo = theme.lookup_icon(package.name, 32, 0)
				if iconInfo and os.path.exists(iconInfo.get_filename()):
					icon_path = iconInfo.get_filename()
			else:
				# Try tuquito-icons then
				icon_path = "/usr/share/tuquito/tuquito-software-manager/icons/%s" % package.name
				if os.path.exists(icon_path + ".png"):
					icon_path = icon_path + ".png"
				elif os.path.exists(icon_path + ".xpm"):
					icon_path = icon_path + ".xpm"
				else:
					# Else, default to generic icons
					icon_path = "/usr/lib/tuquito/tuquito-software-manager/data/available.png"
		return icon_path

	def find_app_icon(self, package):
		icon_path = None
		if package.pkg.is_installed:
			icon_path = "/usr/share/tuquito/tuquito-software-manager/installed/%s" % package.name
		else:
			icon_path = "/usr/share/tuquito/tuquito-software-manager/icons/%s" % package.name
		if os.path.exists(icon_path + ".png"):
			icon_path = icon_path + ".png"
		elif os.path.exists(icon_path + ".xpm"):
			icon_path = icon_path + ".xpm"
		else:
			if package.pkg.is_installed:
				icon_path = "/usr/lib/tuquito/tuquito-software-manager/data/installed.png"
			else:
				icon_path = "/usr/lib/tuquito/tuquito-software-manager/data/available.png"
		return icon_path

	def show_search_results(self, terms):
		# Load packages into self.tree_search
		model_applications = gtk.TreeStore(gtk.gdk.Pixbuf, str, gtk.gdk.Pixbuf, object)

		self.model_filter = model_applications.filter_new()
		self.model_filter.set_visible_func(self.visible_func)

		self.packages.sort()
		for package in self.packages:
			termss = terms.split(' ')
			if len(termss) > 1:
				found = False
			else:
				found = True
			for term in termss:
				aux = found
				if term.strip() != '':
					if term in package.pkg.name and not (package.pkg.name.endswith(":i386") or package.pkg.name.endswith(":amd64")):
						found = True
					else:
						if package.pkg.candidate is not None:
							if self.prefs["search_in_summary"] and ((term in package.pkg.candidate.summary) or (term.capitalize() in package.pkg.candidate.summary)):
								found = True
							elif self.prefs["search_in_description"] and ((term in package.pkg.candidate.description) or (term.capitalize() in package.pkg.candidate.description)):
								found = True
							else:
								found = False
						else:
							found = False
			if aux and found:
				iter = model_applications.insert_before(None, None)
				try:
					model_applications.set_value(iter, 0, gtk.gdk.pixbuf_new_from_file_at_size(self.find_app_icon(package), 32, 32))
				except:
					try:
						model_applications.set_value(iter, 0, gtk.gdk.pixbuf_new_from_file_at_size(self.find_app_icon_alternative(package), 32, 32))
					except:
						model_applications.set_value(iter, 0, gtk.gdk.pixbuf_new_from_file_at_size(self.find_fallback_icon(package), 32, 32))
				summary = ""
				if package.pkg.candidate is not None:
					summary = package.pkg.candidate.summary
					summary = unicode(summary, 'UTF-8', 'replace')
					summary = summary.replace("<", "&lt;")
					summary = summary.replace("&", "&amp;")

				model_applications.set_value(iter, 1, "%s\n<small><span foreground='#555555'>%s</span></small>" % (package.name, summary.capitalize()))
				model_applications.set_value(iter, 3, package)

		self.tree_search.set_model(self.model_filter)
		cant = len(model_applications)
		del model_applications
		self.navigation_bar.add_with_id('%s (%s)' % (_("Search results"), cant), self.navigate, self.NAVIGATION_CATEGORY, "search")

	def visible_func(self, model, iter):
		package = model.get_value(iter, 3)
		if package is not None:
			if package.pkg is not None:
				if package.pkg.is_installed and self.prefs["installed_packages_visible"]:
					return True
				elif (not package.pkg.is_installed) and self.prefs["available_packages_visible"]:
					return True
		return False

	def show_package(self, package):
		account_file = os.path.join(home, '.tuquito/tuquito-software-manager/account.conf')
		if not os.path.exists(account_file):
			self.show_account_message()
		theme = gtk.icon_theme_get_default()
		self.current_package = package
		if theme.has_icon(package.pkg.name):
			iconInfo = theme.lookup_icon(package.pkg.name, 72, 0)
			fileName = iconInfo.get_filename()
			baseName = os.path.basename(fileName)
			if '.xpm' in fileName:
				svgFile = os.path.join(home, '.tuquito/tuquito-software-manager/apps/' + baseName.replace('.xpm', '.svg'))
				if not os.path.exists(svgFile):
					os.system('mkdir -p ' + os.path.join(home, ".tuquito/tuquito-software-manager/apps/"))
					os.system('cp ' + fileName + ' ' + svgFile)
				icon = svgFile
			elif iconInfo and os.path.exists(fileName):
				icon = fileName
		else:
			iconInfo = theme.lookup_icon("applications-other", 72, 0)
			if iconInfo and os.path.exists(iconInfo.get_filename()):
				icon = iconInfo.get_filename()

		impacted_packages  = []
		cache = apt.Cache()
		pkg = cache[package.name]
		if package.pkg.is_installed:
			pkg.mark_delete(True, True)
		else:
			pkg.mark_install()

		changes = cache.get_changes()
		for pkg in changes:
			if not (pkg.name.endswith(":i386") or pkg.name.endswith(":amd64")):
				if pkg.is_installed:
					impacted_packages.append(_("%s (removed)") % pkg.name)
				else:
					impacted_packages.append(_("%s (installed)") % pkg.name)

		# Load package info
		subs = {}
		subs['icon'] = icon
		subs['txtVersion'] = _("Version:")
		subs['txtSize'] = _("Size:")
		subs['txtImpact'] = _("Impact on packages:")
		subs['packagesinfo'] = (', '.join(name for name in impacted_packages))
		subs['loading_txt'] = _("Loading score...")
		subs['votes'] = _('votes')
		subs['vbad'] = _('Very bad')
		subs['ntbad'] = _('Not that bad')
		subs['average'] = _('Average')
		subs['good'] = _('Good')
		subs['excellent'] = _('Excellent')
		subs['timeout_error'] = _('Error loading data')
		subs['just_now'] = _('Just now')
		subs['more'] = _('More...')
		subs['nick'] = self.prefs["username"]
		subs['pass'] = base64.b64decode(self.prefs["password"])
		subs['comment'] = _('Comment')
		subs['comments'] = _('reviews')
		subs['send'] = _('Send')
		subs['loading_comments'] = _('Loading reviews...')
		subs['reviews'] = _('Reviews')
		a = package.name.split('-')
		c = []
		for b in a:
			c.append(b.capitalize())
		subs['appname'] = ' '.join(c)
		subs['pkgname'] = package.pkg.name
		subs['description'] = package.pkg.candidate.description.replace('\n','<br>\n')
		subs['summary'] = package.pkg.candidate.summary.capitalize()
		subs['why'] = _('This is due to possible problems with your Internet connection.')

		downloadSize = str(cache.required_download) + _("B")
		if cache.required_download >= 1000:
			downloadSize = str(cache.required_download / 1000) + _("KB")
		if cache.required_download >= 1000000:
			downloadSize = str(cache.required_download / 1000000) + _("MB")
		if cache.required_download >= 1000000000:
			downloadSize = str(cache.required_download / 1000000000) + _("GB")

		requiredSpace = cache.required_space
		if requiredSpace < 0:
			requiredSpace = (-1) * requiredSpace
		localSize = str(requiredSpace) + _("B")
		if requiredSpace >= 1000:
			localSize = str(requiredSpace / 1000) + _("KB")
		if requiredSpace >= 1000000:
			localSize = str(requiredSpace / 1000000) + _("MB")
		if requiredSpace >= 1000000000:
			localSize = str(requiredSpace / 1000000000) + _("GB")

		if package.pkg.is_installed:
			if cache.required_space < 0:
				subs['sizeinfo'] = _("%(localSize)s of disk space freed") % {'localSize': localSize}
			else:
				subs['sizeinfo'] = _("%(localSize)s of disk space required") % {'localSize': localSize}
		else:
			if cache.required_space < 0:
				subs['sizeinfo'] = _("%(downloadSize)s to download, %(localSize)s of disk space freed") % {'downloadSize': downloadSize, 'localSize': localSize}
			else:
				subs['sizeinfo'] = _("%(downloadSize)s to download, %(localSize)s of disk space required") % {'downloadSize': downloadSize, 'localSize': localSize}

		if len(package.pkg.candidate.homepage) > 0:
			subs['website'] = '<a href="javascript:action_website_clicked()">' + _("Website") + '</a> -'
		else:
			subs['website'] = ""

		subs['remove_button_label'] = _("Remove")
		subs['install_button_label'] = _("Install")

		if package.pkg.is_installed:
			subs['version'] = package.pkg.installed.version
			subs['action'] = 'remove'
		else:
			subs['version'] = package.pkg.candidate.version
			subs['action'] = 'install'

		template = open("/usr/lib/tuquito/tuquito-software-manager/data/templates/PackageView.html").read()
		html = string.Template(template).safe_substitute(subs)
		self.packageBrowser.load_html_string(html, "file:/")
		self.navigation_bar.add_with_id(subs['appname'], self.navigate, self.NAVIGATION_ITEM, package)
class SoftwarePane(gtk.VBox):
    """ Common base class for InstalledPane and AvailablePane """

    __gsignals__ = {
        "app-list-changed" : (gobject.SIGNAL_RUN_LAST,
                              gobject.TYPE_NONE, 
                              (int, ),
                             ),
    }
    PADDING = 6

    def __init__(self, cache, db, distro, icons, datadir, show_ratings=False):
        gtk.VBox.__init__(self)
        # other classes we need
        self.cache = cache
        self.db = db
        self.distro = distro
        self.db.connect("reopen", self.on_db_reopen)
        self.icons = icons
        self.datadir = datadir
        # refreshes can happen out-of-bound so we need to be sure
        # that we only set the new model (when its available) if
        # the refresh_seq_nr of the ready model matches that of the
        # request (e.g. people click on ubuntu channel, get impatient, click
        # on partner channel)
        self.refresh_seq_nr = 0
        # common UI elements (applist and appdetails) 
        # its the job of the Child class to put it into a good location
        # list
        self.app_view = AppView(show_ratings)
        self.app_view.connect("application-selected", 
                              self.on_application_selected)
        self.scroll_app_list = gtk.ScrolledWindow()
        self.scroll_app_list.set_policy(gtk.POLICY_AUTOMATIC, 
                                        gtk.POLICY_AUTOMATIC)
        self.scroll_app_list.add(self.app_view)
        self.app_view.connect("application-activated", 
                              self.on_application_activated)
        self.app_view.connect("application-request-action", 
                              self.on_application_request_action)
        # details
        self.app_details = AppDetailsView(self.db, 
                                          self.distro,
                                          self.icons, 
                                          self.cache, 
                                          self.datadir)
        self.scroll_details = gtk.ScrolledWindow()
        self.scroll_details.set_policy(gtk.POLICY_AUTOMATIC, 
                                       gtk.POLICY_AUTOMATIC)
        self.scroll_details.add(self.app_details)

        # cursor
        self.busy_cursor = gtk.gdk.Cursor(gtk.gdk.WATCH)
        # when the cache changes, refresh the app list
        self.cache.connect("cache-ready", self.on_cache_ready)
        # COMMON UI elements
        # navigation bar and search on top in a hbox
        self.navigation_bar = NavigationBar()
        self.searchentry = SearchEntry()
        self.searchentry.connect("terms-changed", self.on_search_terms_changed)
        self.top_hbox = gtk.HBox()
        self.top_hbox.pack_start(self.navigation_bar, padding=self.PADDING)
        self.top_hbox.pack_start(self.searchentry, expand=False, padding=self.PADDING)
        self.pack_start(self.top_hbox, expand=False, padding=self.PADDING)
        # a notebook below
        self.notebook = gtk.Notebook()
        self.notebook.set_show_tabs(False)
        self.notebook.set_show_border(False)
        self.pack_start(self.notebook)

    def on_cache_ready(self, cache):
        " refresh the application list when the cache is re-opened "
        logging.debug("on_cache_ready")
        # FIXME: preserve selection too
        # get previous vadjustment and reapply it
        vadj = self.scroll_app_list.get_vadjustment()
        self.refresh_apps()
        # needed otherwise we jump back to the beginning of the table
        if vadj:
            vadj.value_changed()

    def on_application_activated(self, appview, app):
        """callback when an app is clicked"""
        logging.debug("on_application_activated: '%s'" % app)
        self.navigation_bar.add_with_id(app.name,
                                       self.on_navigation_details,
                                       "details")
        self.notebook.set_current_page(self.PAGE_APP_DETAILS)
        self.app_details.show_app(app)

    def on_application_request_action(self, appview, app, action):
        """callback when an app action is requested from the appview"""
        logging.debug("on_application_action_requested: '%s' %s" % (app, action))
        # FIXME: move the action-code below out of the appdetails and
        #        into some controller class
        # init the app_details here with the given app because we
        # reuse it 
        self.app_details.init_app(app)
        # action_func is "install" or "remove" of self.app_details
        action_func = getattr(self.app_details, action)
        if callable(action_func):
            action_func()
        else:
            logging.error("can not find action '%s'" % action)

    def update_app_view(self):
        """
        Update the app_view.  If no row is selected, then the previously
        selected app is reselected if it is found in the model, else the
        first app in the list is selected.  If a row is already selected,
        nothing is done.
        """
        selected_iter = None
        selection = self.app_view.get_selection()
        model = self.app_view.get_model()
        if selection:
            selected_iter = selection.get_selected()[1]
        current_app = self.get_current_app()
        if (model is not None and 
            model.get_iter_root() is not None 
            and selected_iter is None):
            index=0
            vadj = self.scroll_app_list.get_vadjustment()
            if current_app:
                if current_app in model.app_index_map:
                    index = model.app_index_map.get(current_app)
            # re-select item
            if vadj:
                self.app_view.set_cursor(index)
                vadj.value_changed()

    def get_status_text(self):
        """return user readable status text suitable for a status bar"""
        raise Exception, "Not implemented"
        
    @wait_for_apt_cache_ready
    def refresh_apps(self):
        " stub implementation "
        pass
    
    def on_search_terms_changed(self, terms):
        " stub implementation "
        pass

    def on_db_reopen(self):
        " stub implementation "
        pass
        
    def is_category_view_showing(self):
        " stub implementation "
        pass
        
    def get_current_app(self):
        " stub implementation "
        pass

    def on_application_selected(self, widget, app):
        " stub implementation "
        pass
        
    def on_nav_back_clicked(self, widget, event):
        " stub implementation "
        pass

    def on_nav_forward_clicked(self, widget, event):
        " stub implementation "
        pass