diff options
Diffstat (limited to 'portato/gui/gtk/windows.py')
-rw-r--r-- | portato/gui/gtk/windows.py | 2057 |
1 files changed, 0 insertions, 2057 deletions
diff --git a/portato/gui/gtk/windows.py b/portato/gui/gtk/windows.py deleted file mode 100644 index c6aaab6..0000000 --- a/portato/gui/gtk/windows.py +++ /dev/null @@ -1,2057 +0,0 @@ -# -*- coding: utf-8 -*- -# -# File: portato/gui/gtk/windows.py -# This file is part of the Portato-Project, a graphical portage-frontend. -# -# Copyright (C) 2006-2008 René 'Necoro' Neumann -# This is free software. You may redistribute copies of it under the terms of -# the GNU General Public License version 2. -# There is NO WARRANTY, to the extent permitted by law. -# -# Written by René 'Necoro' Neumann <necoro@necoro.net> - -from __future__ import absolute_import, with_statement - -# gtk stuff -import gtk -import gobject - -# other -import os.path -from subprocess import Popen -import itertools -from gettext import lgettext as _ - -# our backend stuff -from ... import get_listener, plugin -from ...helper import debug, warning, error, info, unique_array, N_ -from ...session import Session -from ...constants import CONFIG_LOCATION, VERSION, APP_ICON -from ...backend import flags, system -from ...backend.exceptions import PackageNotFoundException, BlockedException -from ... import dependency - -# more GUI stuff -from ..gui_helper import Database, Config, EmergeQueue -from .basic import Window, AbstractDialog, Popup -from .wrapper import GtkTree, GtkConsole -from .exception_handling import GtkThread -from .views import LogView, HighlightView, InstalledOnlyView -from .dialogs import (blocked_dialog, changed_flags_dialog, io_ex_dialog, - nothing_found_dialog, queue_not_empty_dialog, remove_deps_dialog, - remove_queue_dialog, remove_updates_dialog, unmask_dialog) - -# the current version for saved sessions -# change this, whenever the change is incompatible with previous versions -SESSION_VERSION = 1 - -class SessionException (Exception): - - error = _("Version mismatch.") - def __init__ (self, got, expected): - self.got = got - self.expected = expected - - def __str__ (self): - return "%s %s" % (self.error, (_("Got '%d' - expected '%d'.") % (self.got, self.expected))) - -class OldSessionException (SessionException): - error = _("Current session format is too old.") - -class NewSessionException (SessionException): - error = _("Current session format is newer than this version supports.") - -class AboutWindow (AbstractDialog): - """A window showing the "about"-informations.""" - - def __init__ (self, parent): - - AbstractDialog.__init__(self, parent) - - img = gtk.Image() - img.set_from_file(APP_ICON) - - self.window.set_version(VERSION) - self.window.set_logo(img.get_pixbuf()) - - self.window.show_all() - -class PluginWindow (AbstractDialog): - - statsStore = gtk.ListStore(str) - - for s in (_("Disabled"), _("Temporarily enabled"), _("Enabled"), _("Temporarily disabled")): - statsStore.append([s]) - - def __init__ (self, parent, plugins): - """Constructor. - - @param parent: the parent window - @type parent: gtk.Window""" - - AbstractDialog.__init__(self, parent) - self.plugins = plugins - self.changedPlugins = {} - - view = self.tree.get_widget("pluginList") - self.store = gtk.ListStore(str,str,str) - - view.set_model(self.store) - - cell = gtk.CellRendererText() - col = gtk.TreeViewColumn(_("Plugin"), cell, markup = 0) - view.append_column(col) - - col = gtk.TreeViewColumn(_("Authors"), cell, text = 1) - view.append_column(col) - - ccell = gtk.CellRendererCombo() - ccell.set_property("model", self.statsStore) - ccell.set_property("text-column", 0) - ccell.set_property("has-entry", False) - ccell.set_property("editable", True) - ccell.connect("edited", self.cb_status_changed) - col = gtk.TreeViewColumn(_("Status"), ccell, markup = 2) - view.append_column(col) - - for p in (("<b>"+p.name+"</b>", p.author, _(self.statsStore[p.status][0])) for p in plugins): - self.store.append(p) - - self.window.show_all() - - def cb_status_changed (self, cell, path, new_text): - path = int(path) - - self.store[path][2] = "<b>%s</b>" % new_text - - # convert string to constant - const = None - for num, val in enumerate(self.statsStore): - if val[0] == new_text: - const = num - break - - assert (const is not None) - - self.changedPlugins.update({self.plugins[path] : const}) - debug("new changed plugins: %s => %d", self.plugins[path].name, const) - - def cb_ok_clicked (self, btn): - for plugin, val in self.changedPlugins.iteritems(): - plugin.status = val - - self.close() - return True - -class UpdateWindow (AbstractDialog): - - def __init__ (self, parent, packages, queue, jump_to): - AbstractDialog.__init__(self, parent) - - self.queue = queue - self.jump = jump_to - - self.packages = system.sort_package_list(packages) - - self.build_list() - - self.window.show_all() - - def build_list (self): - - store = gtk.ListStore(bool, str) - self.view = self.tree.get_widget("packageList") - self.view.set_model(store) - - cell = gtk.CellRendererText() - tCell = gtk.CellRendererToggle() - tCell.set_property("activatable", True) - tCell.connect("toggled", self.cb_check_toggled) # emulate the normal toggle behavior ... - - self.view.append_column(gtk.TreeViewColumn(_("Enabled"), tCell, active = 0)) - self.view.append_column(gtk.TreeViewColumn(_("Package"), cell, text = 1)) - - for p in self.packages: - store.append([False, p.get_cpv()]) - - def cb_set_size (self, *args): - """ - This callback is called shortly before drawing. - It calculates the optimal size of the window. - The optimum is defined as: as large as possible w/o scrollbars - """ - - bb = self.tree.get_widget("updateBB") - vals = (self.view.get_vadjustment().upper+bb.size_request()[1]+10, # max size of list + size of BB + constant - self.parent.get_size()[1]) # size of the parent -> maximum size - debug("Size values for the list and for the parent: %d / %d", *vals) - val = int(min(vals)) - debug("Minimum value: %d", val) - self.window.set_geometry_hints(self.window, min_height = val) - - def cb_select_all_clicked (self, btn): - model = self.view.get_model() - iter = model.get_iter_first() - - while iter: - model.set_value(iter, 0, True) - iter = model.iter_next(iter) - - return True - - def cb_install_clicked (self, btn): - model = self.view.get_model() - iter = model.get_iter_first() - if iter is None: return - - items = [] - while iter: - if model.get_value(iter, 0): - items.append(model.get_value(iter, 1)) - iter = model.iter_next(iter) - - for item in items: - try: - try: - self.queue.append(item, type = "install", oneshot = True) - except PackageNotFoundException, e: - if unmask_dialog(e[0]) == gtk.RESPONSE_YES : - self.queue.append(item, type = "install", unmask = True, oneshot = True) - - except BlockedException, e: - blocked_dialog(e[0], e[1]) - - self.close() - return True - - def cb_package_selected (self, view): - sel = view.get_selection() - store, it = sel.get_selected() - if it: - package = system.new_package(store.get_value(it, 1)) - - self.jump(package.get_cp(), package.get_version()) - - return True - - def cb_check_toggled (self, cell, path): - # for whatever reason we have to define normal toggle behavior explicitly - store = self.view.get_model() - store[path][0] = not store[path][0] - return True - - -class SearchWindow (AbstractDialog): - """A window showing the results of a search process.""" - - def __init__ (self, parent, list, jump_to): - """Constructor. - - @param parent: parent-window - @type parent: gtk.Window - @param list: list of results to show - @type list: string[] - @param jump_to: function to call if "OK"-Button is hit - @type jump_to: function(string)""" - - AbstractDialog.__init__(self, parent) - - self.jump_to = jump_to # function to call for jumping - self.list = list - self.list.sort() - - # combo box - self.searchList = self.tree.get_widget("searchList") - self.build_sort_list() - self.searchList.get_selection().select_path(0) - - # finished --> show - self.window.show_all() - - def build_sort_list (self): - """Builds the sort list.""" - - store = gtk.ListStore(str) - self.searchList.set_model(store) - - # build categories - for p in self.list: - store.append(["%s/<b>%s</b>" % tuple(p.split("/"))]) - - cell = gtk.CellRendererText() - col = gtk.TreeViewColumn(_("Results"), cell, markup = 0) - self.searchList.append_column(col) - - def ok (self, *args): - self.jump() - self.close() - - def jump (self, *args): - model, iter = self.searchList.get_selection().get_selected() - self.jump_to(self.list[model.get_path(iter)[0]]) - - def cb_key_pressed_combo (self, widget, event): - """Emulates a ok-button-click.""" - keyname = gtk.gdk.keyval_name(event.keyval) - if keyname == "Return": # take it as an "OK" if Enter is pressed - self.jump() - return True - else: - return False - -class PreferenceWindow (AbstractDialog): - """Window displaying some preferences.""" - - # all checkboxes in the window - # widget name -> option name - checkboxes = { - "debugCheck" : "debug", - "deepCheck" : "deep", - "newUseCheck" : "newuse", - "maskPerVersionCheck" : "maskPerVersion", - "minimizeCheck" : ("hideOnMinimize", "GUI"), - "searchOnTypeCheck" : ("searchOnType", "GUI"), - "systrayCheck" : ("showSystray", "GUI"), - "testPerVersionCheck" : "keywordPerVersion", - "titleUpdateCheck" : ("updateTitle", "GUI"), - "usePerVersionCheck" : "usePerVersion" - } - - # all edits in the window - # widget name -> option name - edits = { - "maskFileEdit" : "maskFile", - "testFileEdit" : "keywordFile", - "useFileEdit" : "useFile", - "syncCommandEdit" : "syncCommand", - "browserEdit" : ("browserCmd", "GUI") - } - - # the mappings for the tabpos combos - tabpos = { - 1 : gtk.POS_TOP, - 2 : gtk.POS_BOTTOM, - 3 : gtk.POS_LEFT, - 4 : gtk.POS_RIGHT - } - - def __init__ (self, parent, cfg, console_fn, linkbtn_fn, tabpos_fn): - """Constructor. - - @param parent: parent window - @type parent: gtk.Window - @param cfg: configuration object - @type cfg: gui_helper.Config - @param console_fn: function to call to set the console font - @type console_fn: function(string) - @param linkbtn_fn: function to call to set the linkbutton behavior - @type linkbtn_fn: function(string) - @param tabpos_fn: function to call to set the tabposition of the notebooks - @type tabpos_fn: function(gtk.ComboBox,int)""" - - AbstractDialog.__init__(self, parent) - - # our config - self.cfg = cfg - - # the setter functions - self.console_fn = console_fn - self.linkbtn_fn = linkbtn_fn - self.tabpos_fn = tabpos_fn - - # set the bg-color of the hint - hintEB = self.tree.get_widget("hintEB") - hintEB.modify_bg(gtk.STATE_NORMAL, gtk.gdk.color_parse("#f3f785")) - - # the checkboxes - for box, val in self.checkboxes.iteritems(): - if isinstance(val, tuple): - self.tree.get_widget(box).\ - set_active(self.cfg.get_boolean(val[0], section = val[1])) - else: - self.tree.get_widget(box).\ - set_active(self.cfg.get_boolean(val)) - - # the edits - for edit, val in self.edits.iteritems(): - if isinstance(val,tuple): - self.tree.get_widget(edit).\ - set_text(self.cfg.get(val[0], section = val[1])) - else: - self.tree.get_widget(edit).\ - set_text(self.cfg.get(val)) - - # the console font button - self.consoleFontBtn = self.tree.get_widget("consoleFontBtn") - self.consoleFontBtn.set_font_name(self.cfg.get("consolefont", section = "GTK")) - - # the comboboxes - self.systemTabCombo = self.tree.get_widget("systemTabCombo") - self.pkgTabCombo = self.tree.get_widget("packageTabCombo") - - for c in (self.systemTabCombo, self.pkgTabCombo): - m = c.get_model() - m.clear() - for i in (_("Top"), _("Bottom"), _("Left"), _("Right")): - m.append((i,)) - - self.systemTabCombo.set_active(int(self.cfg.get("systemTabPos", section = "GTK"))-1) - self.pkgTabCombo.set_active(int(self.cfg.get("packageTabPos", section = "GTK"))-1) - - self.window.show_all() - - def _save(self): - """Sets all options in the Config-instance.""" - - for box, val in self.checkboxes.iteritems(): - if isinstance(val, tuple): - self.cfg.set_boolean(val[0], self.tree.get_widget(box).get_active(), section = val[1]) - else: - self.cfg.set_boolean(val, self.tree.get_widget(box).get_active()) - - for edit, val in self.edits.iteritems(): - if isinstance(val,tuple): - self.cfg.set(val[0], self.tree.get_widget(edit).get_text(), section = val[1]) - else: - self.cfg.set(val,self.tree.get_widget(edit).get_text()) - - font = self.consoleFontBtn.get_font_name() - self.cfg.set("consolefont", font, section = "GTK") - self.console_fn(font) - - pkgPos = self.pkgTabCombo.get_active()+1 - sysPos = self.systemTabCombo.get_active()+1 - - self.cfg.set("packageTabPos", str(pkgPos), section = "GTK") - self.cfg.set("systemTabPos", str(sysPos), section = "GTK") - - self.tabpos_fn(map(self.tabpos.get, (pkgPos, sysPos))) - - self.linkbtn_fn(self.cfg.get("browserCmd", section="GUI")) - - def cb_ok_clicked(self, button): - """Saves, writes to config-file and closes the window.""" - self._save() - try: - self.cfg.write() - except IOError, e: - io_ex_dialog(e) - - self.window.destroy() - - def cb_cancel_clicked (self, button): - """Just closes - w/o saving.""" - self.window.destroy() - -class PackageTable: - """A window with data about a specfic package.""" - - def __init__ (self, main): - """Build up window contents. - - @param main: the main window - @type main: MainWindow""" - - self.main = main - self.tree = main.tree - self.window = main.window - self.tree.signal_autoconnect(self) - - # all the package data is in this one VB - self.vb = self.tree.get_widget("packageVB") - - # the notebook - self.notebook = self.tree.get_widget("packageNotebook") - - # the version combo - self.versionCombo = self.tree.get_widget("versionCombo") - self.build_version_combo() - - # chechboxes - self.installedCheck = self.tree.get_widget("installedCheck") - self.maskedCheck = self.tree.get_widget("maskedCheck") - self.testingCheck = self.tree.get_widget("testingCheck") - self.maskedLabel = self.tree.get_widget("maskedLabel") - - # labels - generalVB = self.tree.get_widget("generalVB") - generalVB.modify_bg(gtk.STATE_NORMAL, gtk.gdk.color_parse("#FFFFFF")) - - self.nameLabel = self.tree.get_widget("nameLabel") - self.descLabel = self.tree.get_widget("descLabel") - self.overlayLabel = self.tree.get_widget("overlayLabel") - self.overlayLL = self.tree.get_widget("overlayLabelLabel") - self.licenseLabel = self.tree.get_widget("licenseLabel") - self.linkBox = self.tree.get_widget("linkBox") - self.notInSysLabel = self.tree.get_widget("notInSysLabel") - self.missingLabel = self.tree.get_widget("missingLabel") - self.useFlagsLabel = self.tree.get_widget("useFlagsLabel") - self.useFlagsLL = self.tree.get_widget("useFlagsLabelLabel") - - # buttons - self.emergeBtn = self.tree.get_widget("pkgEmergeBtn") - self.unmergeBtn = self.tree.get_widget("pkgUnmergeBtn") - self.revertBtn = self.tree.get_widget("pkgRevertBtn") - - # useList - self.useList = self.tree.get_widget("useList") - self.build_use_list() - - # depList - self.depList = self.tree.get_widget("dependencyList") - self.build_dep_list() - - # views - self.ebuildView = self.tree.get_widget("ebuildScroll").get_child() - self.changelogView = self.tree.get_widget("changelogScroll").get_child() - self.filesView = self.tree.get_widget("filesScroll").get_child() - - # icons - self.icons = {} - self.icons["use"] = self.window.render_icon(gtk.STOCK_REMOVE, gtk.ICON_SIZE_MENU) - self.icons["installed"] = self.window.render_icon(gtk.STOCK_YES, gtk.ICON_SIZE_MENU) - self.icons["or"] = self.window.render_icon(gtk.STOCK_MEDIA_PAUSE, gtk.ICON_SIZE_MENU) - self.icons["block"] = self.window.render_icon(gtk.STOCK_NO, gtk.ICON_SIZE_MENU) - - def update (self, cp, queue = None, version = None, doEmerge = True, instantChange = False, type = None): - """Updates the table to show the contents for the package. - - @param cp: the selected package - @type cp: string (cp) - @param queue: emerge-queue (if None the emerge-buttons are disabled) - @type queue: EmergeQueue - @param version: if not None, specifies the version to select - @type version: string - @param doEmerge: if False, the emerge buttons are disabled - @type doEmerge: boolean - @param instantChange: if True the changed keywords are updated instantly - @type instantChange: boolean - @param type: the type of the queue this package is in; if None there is no queue :) - @type type: string""" - - self.cp = cp # category/package - self.version = version # version - if not None this is used - self.queue = queue - self.doEmerge = doEmerge - self.instantChange = instantChange - self.type = type - - # packages and installed packages - if not self.doEmerge: - self.instPackages = self.packages = system.find_packages("=%s-%s" % (cp, version), masked = True) - else: - self.packages = system.sort_package_list(system.find_packages(cp, masked = True)) - self.instPackages = system.sort_package_list(system.find_installed_packages(cp, masked = True)) - - # version-combo-box - self.versionCombo.handler_block(self.versionCombo.changeHandler) # block change handler, because it would be called several times - self.versionCombo.get_model().clear() - self.fill_version_combo() - self.versionCombo.handler_unblock(self.versionCombo.changeHandler) # unblock handler again - - if not self.queue or not self.doEmerge: - self.emergeBtn.set_sensitive(False) - self.unmergeBtn.set_sensitive(False) - - # current status - self.cb_version_combo_changed() - self.vb.show_all() - - def hide (self): - self.vb.hide_all() - - def set_labels (self): - pkg = self.actual_package() - - # name - self.nameLabel.set_markup("<b>%s</b>" % pkg.get_cp()) - - # description - desc = pkg.get_package_settings("DESCRIPTION") or _("<no description>") - self.descLabel.set_label(desc) - - # overlay - if pkg.is_overlay(): - self.overlayLabel.set_label(pkg.get_overlay_path()) - self.overlayLabel.show() - self.overlayLL.show() - else: - self.overlayLabel.hide() - self.overlayLL.hide() - - # license - self.licenseLabel.set_label(pkg.get_package_settings("LICENSE")) - - # link - for c in self.linkBox.get_children(): - self.linkBox.remove(c) - - text = pkg.get_package_settings("HOMEPAGE") - texts = text.split(" ") - ftexts = [] - - for count, t in enumerate(texts): - if not t.startswith(("http:", "ftp:")): - if count == 0: - error(_("The first homepage part does not start with 'http' or 'ftp'.")) - ftexts.append(t) - continue - else: - info(_("Blank inside homepage.")) - ftexts[-1] += " %s" % t - else: - ftexts.append(t) - - for t in ftexts: - link = gtk.LinkButton(t) - link.set_alignment(0.0, 0.5) - link.set_border_width(0) - self.linkBox.add(link) - - # useflags - flaglist = list(itertools.ifilterfalse(pkg.use_expanded, pkg.get_iuse_flags())) - flaglist.sort() - flags = ", ".join(flaglist) - - if flags: - self.useFlagsLL.show() - self.useFlagsLabel.show() - self.useFlagsLabel.set_label(flags) - else: - self.useFlagsLL.hide() - self.useFlagsLabel.hide() - - def fill_dep_list(self): - - deptree = self.actual_package().get_dependencies() - store = self.depList.get_model() - - def add (tree, it): - - def get_icon (dep): - if dep.satisfied: - return self.icons["installed"] - elif dep.dep[0] == "!": - return self.icons["block"] - else: - return None - - # useflags - for use, usetree in tree.flags.iteritems(): - if use[0] == "!": - usestring = _("If '%s' is disabled") % use[1:] - else: - usestring = _("If '%s' is enabled") % use - useit = store.append(it, [self.icons["use"], usestring]) - add(usetree, useit) - - # ORs - ordeps = (dep for dep in tree.deps if isinstance(dep, dependency.OrDependency)) - - for ordep in ordeps: - orit = store.append(it, [self.icons["or"], _("One of the following")]) - - for dep in ordep.dep: - store.append(orit, [get_icon(dep), dep.dep]) - - # normal - def sort_key (x): - split = system.split_cpv(x.dep) - - if split is None: # split_cpv returns None if this is only a CP; we assume there are only valid deps - return x.dep - else: - return "/".join(split[0:2]) - - ndeps = [dep for dep in tree.deps if not isinstance(dep, dependency.OrDependency)] - ndeps.sort(key = sort_key) - for dep in ndeps: - store.append(it, [get_icon(dep), dep.dep]) - - add (deptree, None) - - def fill_use_list(self): - - pkg = self.actual_package() - pkg_flags = pkg.get_iuse_flags() - pkg_flags.sort() - - actual_exp = None - actual_exp_it = None - - euse = pkg.get_actual_use_flags() - instuse = pkg.get_installed_use_flags() - - store = self.useList.get_model() - - for use in pkg_flags: - exp = pkg.use_expanded(use, suggest = actual_exp) - if exp is not None: - if exp != actual_exp: - actual_exp_it = store.append(None, [None, None, exp, "<i>%s</i>" % _("This is an expanded use flag and cannot be selected")]) - actual_exp = exp - else: - actual_exp_it = None - actual_exp = None - - enabled = use in euse - installed = use in instuse - store.append(actual_exp_it, [enabled, installed, use, system.get_use_desc(use, self.cp)]) - - def build_dep_list (self): - store = gtk.TreeStore(gtk.gdk.Pixbuf, str) - - self.depList.set_model(store) - - col = gtk.TreeViewColumn() - - cell = gtk.CellRendererPixbuf() - col.pack_start(cell, False) - col.add_attribute(cell, "pixbuf", 0) - - cell = gtk.CellRendererText() - col.pack_start(cell, True) - col.add_attribute(cell, "text", 1) - - self.depList.append_column(col) - - def build_use_list (self): - """Builds the useList.""" - store = gtk.TreeStore(bool, bool, str, str) - self.useList.set_model(store) - - # build view - cell = gtk.CellRendererText() - iCell = gtk.CellRendererToggle() - iCell.set_property("activatable", False) - tCell = gtk.CellRendererToggle() - tCell.set_property("activatable", True) - tCell.connect("toggled", self.cb_use_flag_toggled, store) - self.useList.append_column(gtk.TreeViewColumn(_("Enabled"), tCell, active = 0)) - self.useList.append_column(gtk.TreeViewColumn(_("Installed"), iCell, active = 1)) - self.useList.append_column(gtk.TreeViewColumn(_("Flag"), cell, text = 2)) - self.useList.append_column(gtk.TreeViewColumn(_("Description"), cell, markup = 3)) - - self.useList.set_search_column(2) - self.useList.set_enable_tree_lines(True) - - def build_version_combo (self): - store = gtk.ListStore(gtk.gdk.Pixbuf, str) - - # build view - self.versionCombo.set_model(store) - col = gtk.TreeViewColumn("Versions") - - # adding the pixbuf - cell = gtk.CellRendererPixbuf() - self.versionCombo.pack_start(cell, False) - self.versionCombo.add_attribute(cell, "pixbuf", 0) - - # adding the package name - cell = gtk.CellRendererText() - self.versionCombo.pack_start(cell, True) - self.versionCombo.add_attribute(cell, "text", 1) - - # connect - self.versionCombo.changeHandler = self.versionCombo.connect("changed", self.cb_version_combo_changed) - - def fill_version_combo (self): - - store = self.versionCombo.get_model() - - # append versions - for vers, inst in ((x.get_version(), x.is_installed()) for x in self.packages): - if inst: - icon = self.main.instPixbuf - else: - icon = None - store.append([icon, vers]) - - # activate the first one - try: - best_version = "" - if self.version: - best_version = self.version - else: - best_version = system.find_best_match(self.packages[0].get_cp(), only_installed = (self.instPackages != [])).get_version() - for i in range(len(self.packages)): - if self.packages[i].get_version() == best_version: - self.versionCombo.set_active(i) - break - except AttributeError: # no package found - self.versionCombo.set_active(0) - - def actual_package (self): - """Returns the actual selected package. - - @returns: the actual selected package - @rtype: backend.Package""" - - return self.packages[self.versionCombo.get_active()] - - def _update_keywords (self, emerge, update = False): - if emerge: - type = "install" if not self.type else self.type - try: - try: - self.queue.append(self.actual_package().get_cpv(), type = type, update = update) - except PackageNotFoundException, e: - if unmask_dialog(e[0]) == gtk.RESPONSE_YES: - self.queue.append(self.actual_package().get_cpv(), type = type, unmask = True, update = update) - except BlockedException, e: - blocked_dialog(e[0], e[1]) - else: - try: - self.queue.append(self.actual_package().get_cpv(), type = "uninstall") - except PackageNotFoundException, e: - error(_("Package could not be found: %s"), e[0]) - #masked_dialog(e[0]) - - def cb_version_combo_changed (self, *args): - - pkg = self.actual_package() - - # set the views - for v in (self.ebuildView, self.changelogView, self.filesView): - v.update(pkg, force = self.notebook.get_nth_page(self.notebook.get_current_page()) == v.get_parent()) - - # set the labels - self.set_labels() - - # set use list - self.useList.get_model().clear() - self.useList.columns_autosize() - self.fill_use_list() - - # set dep list - self.depList.get_model().clear() - self.useList.columns_autosize() - self.fill_dep_list() - - # - # rebuild the buttons and checkboxes in all the different manners which are possible - # - if (not pkg.is_in_system()) or pkg.is_missing_keyword(): - if not pkg.is_in_system(): - self.missingLabel.hide() - self.notInSysLabel.show() - else: # missing keyword - self.missingLabel.show() - self.notInSysLabel.hide() -# - self.installedCheck.hide() - self.maskedCheck.hide() - self.maskedLabel.hide() - self.testingCheck.hide() - self.emergeBtn.set_sensitive(False) - else: # normal package - self.missingLabel.hide() - self.notInSysLabel.hide() - self.installedCheck.show() - self.maskedCheck.show() - self.maskedLabel.show() - self.testingCheck.show() - if self.doEmerge: - self.emergeBtn.set_sensitive(True) - self.installedCheck.set_active(pkg.is_installed()) - - reason = pkg.get_masking_reason() or " " - if pkg.is_masked(use_changed = False) and not pkg.is_masked(use_changed = True): - self.maskedCheck.set_label("<i>(%s)</i>" % _("Masked")) - self.maskedCheck.get_child().set_use_markup(True) - else: - self.maskedCheck.set_label(_("Masked")) - - if pkg.is_locally_masked(): - self.maskedCheck.set_label("<b>%s</b>" % _("Masked")) - self.maskedCheck.get_child().set_use_markup(True) - self.maskedCheck.set_active(True) - reason = _("Masked by user") - else: - self.maskedCheck.set_active(pkg.is_masked(use_changed = False)) - - if reason: - self.maskedLabel.set_label(reason) - - if pkg.is_testing(use_keywords = False) and not pkg.is_testing(use_keywords = True): - self.testingCheck.set_label("<i>(%s)</i>" % _("Testing")) - self.testingCheck.get_child().set_use_markup(True) - else: - self.testingCheck.set_label(_("Testing")) - - self.testingCheck.set_active(pkg.is_testing(use_keywords = False)) - - if self.doEmerge: - # set emerge-button-label - if not self.actual_package().is_installed(): - self.unmergeBtn.set_sensitive(False) - else: - self.unmergeBtn.set_sensitive(True) - - self.vb.show_all() - return True - - def cb_button_pressed (self, b, event): - """Callback for pressed checkboxes. Just quits the event-loop - no redrawing.""" - if not isinstance(b, gtk.CellRendererToggle): - b.emit_stop_by_name("button-press-event") - return True - - def cb_package_revert_clicked (self, button): - """Callback for pressed revert-button.""" - self.actual_package().remove_new_use_flags() - self.actual_package().remove_new_masked() - self.actual_package().remove_new_testing() - self.versionCombo.get_model().clear() - self.fill_version_combo() - self.cb_version_combo_changed() - if self.instantChange: - self._update_keywords(True, update = True) - return True - - def cb_package_emerge_clicked (self, button): - """Callback for pressed emerge-button. Adds the package to the EmergeQueue.""" - self._update_keywords(True) - self.main.sysNotebook.set_current_page(self.main.QUEUE_PAGE) - return True - - def cb_package_unmerge_clicked (self, button): - """Callback for pressed unmerge-button clicked. Adds the package to the UnmergeQueue.""" - self._update_keywords(False) - self.main.sysNotebook.set_current_page(self.main.QUEUE_PAGE) - return True - - def cb_testing_toggled (self, button): - """Callback for toggled testing-checkbox.""" - status = button.get_active() - - # end of recursion :) - if self.actual_package().is_testing(use_keywords = False) == status: - return False - - # if the package is not testing - don't allow to set it as such - if not self.actual_package().is_testing(use_keywords = False): - button.set_active(False) - return True - - # re-set to testing status - if not self.actual_package().is_testing(use_keywords = True): - self.actual_package().set_testing(False) - button.set_label(_("Testing")) - button.set_active(True) - else: # disable testing - self.actual_package().set_testing(True) - button.set_label("<i>(%s)</i>" % _("Testing")) - button.get_child().set_use_markup(True) - button.set_active(True) - - if self.instantChange: - self._update_keywords(True, update = True) - - return True - - def cb_masked_toggled (self, button): - """Callback for toggled masking-checkbox.""" - status = button.get_active() - pkg = self.actual_package() - - if pkg.is_masked(use_changed = False) == status and not pkg.is_locally_masked(): - return False - - if pkg.is_locally_masked() and status: - return False - - if not pkg.is_masked(use_changed = True): - pkg.set_masked(True) - if pkg.is_locally_masked(): - button.set_label("<b>%s</b>" % _("Masked")) - button.get_child().set_use_markup(True) - self.maskedLabel.set_label(_("Masked by user")) - else: - button.set_label(_("Masked")) - - button.set_active(True) - else: - locally = pkg.is_locally_masked() - pkg.set_masked(False) - if pkg.is_masked(use_changed=False) and not locally: - button.set_label("<i>(%s)</i>" % _("Masked")) - button.get_child().set_use_markup(True) - button.set_active(True) - else: - button.set_label(_("Masked")) - self.maskedLabel.set_label("") - - if self.instantChange: - self._update_keywords(True, update = True) - - return True - - def cb_use_flag_toggled (self, cell, path, store): - """Callback for a toggled use-flag button.""" - flag = store[path][2] - pkg = self.actual_package() - - if pkg.use_expanded(flag): # ignore expanded flags - return False - - store[path][0] = not store[path][0] - prefix = "" - if not store[path][0]: - prefix = "-" - - pkg.set_use_flag(prefix+flag) - if self.instantChange: - self._update_keywords(True, update = True) - - return True - -class MainWindow (Window): - """ - Application main window. - """ - - # NOTEBOOK PAGE CONSTANTS - ( - QUEUE_PAGE, - CONSOLE_PAGE, - LOG_PAGE - ) = range(3) - - def __init__ (self, splash = None): - """ - Build up window. - - @param splash: the splash screen =) - @type splash: SplashScreen - """ - - if splash is None: - splash = lambda x: True - - # the title - self.main_title = "Portato (%s)" % VERSION - - # main window stuff - Window.__init__(self) - self.window.set_title(self.main_title) - self.window.set_geometry_hints (self.window, max_height = gtk.gdk.screen_height(), max_width = gtk.gdk.screen_width()) - - # booleans - self.doUpdate = False - self.showAll = True # show only installed or all packages? - self.__searchChanged = False - - # installed pixbuf - self.instPixbuf = self.window.render_icon(gtk.STOCK_YES, gtk.ICON_SIZE_MENU) - - # get the logging window as soon as possible - self.logView = LogView(self.tree.get_widget("logView")) - - # config - splash(_("Loading Config")) - try: - self.cfg = Config(CONFIG_LOCATION) - except IOError, e: - io_ex_dialog(e) - raise - - self.cfg.modify_external_configs() - self.set_uri_hook(self.cfg.get("browserCmd", section = "GUI")) - gtk.about_dialog_set_url_hook(lambda *args: True) # dummy - if not set link is not set as link; if link is clicked the normal uuri_hook is called too - thus do not call browser here - - # package db - splash(_("Creating Database")) - self.db = Database() - self.db.populate() - - # set plugins and plugin-menu - splash(_("Loading Plugins")) - - plugin.load_plugins("gtk") - menus = plugin.get_plugin_queue().get_plugin_menus() - if menus: - self.tree.get_widget("pluginMenuItem").set_no_show_all(False) - pluginMenu = self.tree.get_widget("pluginMenu") - - for m in menus: - item = gtk.MenuItem(m.label) - item.connect("activate", m.call) - pluginMenu.append(item) - - splash(_("Building frontend")) - # set paned position - self.vpaned = self.tree.get_widget("vpaned") - self.vpaned.set_position(int(self.window.get_size()[1]/2)) - self.hpaned = self.tree.get_widget("hpaned") - self.hpaned.set_position(int(self.window.get_size()[0]/1.5)) - - # cat and pkg list - self.sortPkgListByName = True - self.catList = self.tree.get_widget("catList") - self.pkgList = self.tree.get_widget("pkgList") - self.build_cat_list() - self.build_pkg_list() - - # search entry - self.searchEntry = self.tree.get_widget("searchEntry") - - # queue list - self.queueList = self.tree.get_widget("queueList") - self.build_queue_list() - - # the terminal - self.console = GtkConsole() - self.termHB = self.tree.get_widget("termHB") - self.build_terminal() - - # notebooks - self.sysNotebook = self.tree.get_widget("systemNotebook") - self.pkgNotebook = self.tree.get_widget("packageNotebook") - self.set_notebook_tabpos(map(PreferenceWindow.tabpos.get, map(int, (self.cfg.get("packageTabPos", "GTK"), self.cfg.get("systemTabPos", "GTK"))))) - - # the different scrolls - ebuildScroll = self.tree.get_widget("ebuildScroll") - ebuildScroll.add(HighlightView(lambda p: p.get_ebuild_path(), ["gentoo", "sh"])) - - changelogScroll = self.tree.get_widget("changelogScroll") - changelogScroll.add(HighlightView(lambda p: os.path.join(p.get_package_path(), "ChangeLog"), ["changelog"])) - - def show_files (p): - try: - for f in p.get_files(): - yield " %s\n" % f - except IOError, e: - yield _("Error: %s") % e.strerror - - filesScroll = self.tree.get_widget("filesScroll") - filesScroll.add(InstalledOnlyView(show_files)) - - # table - self.packageTable = PackageTable(self) - - # popups - self.queuePopup = Popup("queuePopup", self, self.__file__) - self.consolePopup = Popup("consolePopup", self, self.__file__) - self.trayPopup = Popup("systrayPopup", self) - - # pause menu items - self.emergePaused = False - self.pauseItems = {} - self.pauseItems["tray"] = self.trayPopup.tree.get_widget("pauseItemTray") - self.pauseItems["popup"] = self.consolePopup.tree.get_widget("pauseItemPopup") - self.pauseItems["menu"] = self.tree.get_widget("pauseItemMenu") - - for k,v in self.pauseItems.iteritems(): - self.pauseItems[k] = (v, v.connect_after("activate", self.cb_pause_emerge(k))) - - # systray - if self.cfg.get_boolean("showSystray", "GUI"): - self.tray = gtk.status_icon_new_from_file(APP_ICON) - self.tray.connect("activate", self.cb_systray_activated) - self.tray.connect("popup-menu", lambda icon, btn, time: self.trayPopup.popup(None, None, None, btn, time)) - else: - self.tray = None - - # set emerge queue - self.queueTree = GtkTree(self.queueList.get_model()) - self.queue = EmergeQueue(console = self.console, tree = self.queueTree, db = self.db, title_update = self.title_update, threadClass = GtkThread) - - self.catList.get_selection().select_path(1) - self.pkgList.get_selection().select_path(0) - - # session - splash(_("Restoring Session")) - try: - try: - self.load_session() - except OldSessionException, e: - self.load_session(e) - except SessionException, e: - warning(str(e)) - - splash(_("Finishing startup")) - - self.window.show_all() - - def show_package (self, *args, **kwargs): - self.packageTable.update(*args, **kwargs) - - def build_terminal (self): - """ - Builds the terminal. - """ - - self.console.set_scrollback_lines(1024) - self.console.set_scroll_on_output(True) - self.console.set_font_from_string(self.cfg.get("consolefont", "GTK")) - self.console.connect("button-press-event", self.cb_right_click) - self.termHB.pack_start(self.console, True, True) - - # add scrollbar - termScroll = gtk.VScrollbar(self.console.get_adjustment()) - self.termHB.pack_start(termScroll, False) - - def build_queue_list (self): - """ - Builds the queue list. - """ - - store = gtk.TreeStore(str,str,bool) - - self.queueList.set_model(store) - - cell = gtk.CellRendererText() - col = gtk.TreeViewColumn(_("Queue"), cell, markup = 0) - self.queueList.append_column(col) - - col = gtk.TreeViewColumn(_("Options"), cell, markup = 1) - self.queueList.append_column(col) - - def build_cat_list (self): - """ - Builds the category list. - """ - - store = gtk.ListStore(str) - - self.catList.set_model(store) - cell = gtk.CellRendererText() - col = gtk.TreeViewColumn(_("Categories"), cell, text = 0) - self.catList.append_column(col) - - self.fill_cat_store(store) - self.catList.get_selection().connect("changed", self.cb_cat_list_selection) - - def fill_cat_store (self, store): - """ - Fills the category store with data. - - @param store: the store to fill - @type store: gtk.ListStore - """ - - cats = self.db.get_categories(installed = not self.showAll) - - for p in cats: - store.append([p]) - - # sort them alphabetically - store.set_sort_column_id(0, gtk.SORT_ASCENDING) - - def build_pkg_list (self, name = None): - """ - Builds the package list. - - @param name: name of the selected catetegory - @type name: string - """ - - store = gtk.ListStore(gtk.gdk.Pixbuf, str, str) - self.fill_pkg_store(store,name) - - # build view - self.pkgList.set_model(store) - - col = gtk.TreeViewColumn(_("Packages")) - col.set_clickable(True) - col.connect("clicked", self.cb_pkg_list_header_clicked) - - # adding the pixbuf - cell = gtk.CellRendererPixbuf() - col.pack_start(cell, False) - col.add_attribute(cell, "pixbuf", 0) - - # adding the package name - cell = gtk.CellRendererText() - col.pack_start(cell, True) - col.add_attribute(cell, "text", 1) - - self.pkgList.append_column(col) - - self.pkgList.get_selection().connect("changed", self.cb_pkg_list_selection) - - def fill_pkg_store (self, store, name = None): - """ - Fills a given ListStore with the packages in a category. - - @param store: the store to fill - @type store: gtk.ListStore - @param name: the name of the category - @type name: string - """ - - if name: - for cat, pkg, is_inst in self.db.get_cat(name, self.sortPkgListByName): - if is_inst: - icon = self.instPixbuf - elif not self.showAll: - continue # ignore not installed packages - else: - icon = None - store.append([icon, pkg, cat]) - - def refresh_stores (self): - """ - Refreshes the category and package stores. - """ - store = self.catList.get_model() - store.clear() - self.fill_cat_store(store) - - store = self.pkgList.get_model() - store.clear() - try: - self.fill_pkg_store(store, self.selCatName) - except AttributeError: # no selCatName -> so no category selected --> ignore - debug("No category selected --> should be no harm.") - - def load_session(self, sessionEx = None): - """ - Loads the session data. - """ - try: - self.session = Session("gtk_session.cfg") - except (OSError, IOError), e: - io_ex_dialog(e) - return - - oldVersion = SESSION_VERSION - allowedVersions = (0,) - - if sessionEx and isinstance(sessionEx, SessionException): - if sessionEx.got in allowedVersions: - info(_("Translating session from version %d to %d.") % (sessionEx.got, sessionEx.expected)) - oldVersion = sessionEx.got - else: - warning(_("Cannot translate session from version %d to %d.") % (session.got, session.expected)) - raise session_ex - - # - # the callbacks for the different session variables - # - - # QUEUE - def load_queue (merge, unmerge, oneshot): - def _load(q, **kwargs): - if q: - for i in q.split(","): - self.queue.append(i, **kwargs) - - _load(merge) - _load(unmerge, unmerge = True) - _load(oneshot, oneshot = True) - - def save_queue (): - if self.__save_queue: - return (",".join(self.queue.mergequeue), ",".join(self.queue.unmergequeue), ",".join(self.queue.oneshotmerge)) - else: - return ("", "", "") - - # PANED - def load_paned (*pos): - pos = map(int, pos) - [x.set_position(p) for x,p in zip((self.vpaned, self.hpaned), pos)] - - def save_paned (): - return [x.get_position() for x in (self.vpaned, self.hpaned)] - - # SELECTION - def load_selection (list, col): - def _load (name): - pos = "0" # default - - if name: - for cname, path in ((x[col], x.path) for x in list.get_model()): - if cname == name: - pos = path - - list.get_selection().select_path(pos) - list.scroll_to_cell(pos) - - return _load - - def save_pkg_selection (): - store, iter = self.pkgList.get_selection().get_selected() - if iter: - return store.get_value(iter, 1) - else: - return "" - - def save_cat_selection (): - # try to find the correct category using the pkgList selection - # so we do not select ALL =) - # if no package has been selected - return selCatName - store, iter = self.pkgList.get_selection().get_selected() - if iter: - return store.get_value(iter, 2) - else: - return self.selCatName - - # PLUGIN - def load_plugin (p): - def _load(val): - if val: - p.status = int(val)*2 - - return _load - - def save_plugin (p): - def _save (): - stat_on = p.status >= p.STAT_ENABLED - hard_on = not p.get_option("disabled") - - if stat_on != hard_on: - return int(stat_on) - else: - return "" - return _save - - # SESSION VERSION - def load_session_version (version): - if oldVersion != SESSION_VERSION: # we are trying to convert - return - - version = int(version) - - if version < SESSION_VERSION: - raise OldSessionException(version, SESSION_VERSION) - elif version > SESSION_VERSION: - raise NewSessionException(version, SESSION_VERSION) - - # set the simple ones :) - map(self.session.add_handler,[ - ([("gtksessionversion", "session")], load_session_version, lambda: SESSION_VERSION), - ([("width", "window"), ("height", "window")], lambda w,h: self.window.resize(int(w), int(h)), self.window.get_size), - ([("vpanedpos", "window"), ("hpanedpos", "window")], load_paned, save_paned), - ([("catsel", "window")], load_selection(self.catList, 0), save_cat_selection), - ([("pkgsel", "window")], load_selection(self.pkgList, 1), save_pkg_selection) - #([("merge", "queue"), ("unmerge", "queue"), ("oneshot", "queue")], load_queue, save_queue), - ]) - - # set the plugins - queue = plugin.get_plugin_queue() - if queue: - for p in queue.get_plugins(): - self.session.add_handler(([(p.name.replace(" ","_"), "plugins")], load_plugin(p), save_plugin(p))) - - # now we have the handlers -> load - self.session.load() - - def jump_to (self, cp, version = None): - """ - Is called when we want to jump to a specific package. - - @param cp: the CP to jump to - @type cp: string - @param version: if not None jump to a specific version - @type version: string - """ - - cat, pkg = cp.split("/") - - for list, idx, what, expr in ((self.catList, 0, "categories", cat), (self.pkgList, 1, "packages", pkg)): - pathes = [row.path for row in list.get_model() if row[idx] == expr] - - if len(pathes) == 1: - list.get_selection().select_path(pathes[0]) - list.scroll_to_cell(pathes[0]) - else: - debug("Unexpected number of %s returned after search: %d", what, len(pathes)) - break - - self.show_package(cp, self.queue, version = version) - - def set_uri_hook (self, browser): - """ - Sets the browser command which is called when a URL is going to be opened. - - @param browser: the browser command - @type browser: string - """ - - browser = browser.split() - gtk.link_button_set_uri_hook(lambda btn, x: get_listener().send_cmd(browser+[btn.get_uri()])) - - def set_notebook_tabpos (self, tabposlist): - """ - Sets the positions of the tabs of the notebooks. - - @param tabposlist: the list of positions: first comes the one for package tabs; sndly for sys tabs - @type tabposlist: int[] - """ - self.pkgNotebook.set_tab_pos(tabposlist[0]) - self.sysNotebook.set_tab_pos(tabposlist[1]) - - def title_update (self, title): - """ - Updates the titles of the window and the systray. - Mainly used with emerge term titles. - - @param title: the title - @type title: string - """ - - def window_title_update (title): - """ - Updates the title of the main window. - """ - if title is None or not self.cfg.get_boolean("updateTitle", "GUI"): - self.window.set_title(self.main_title) - else: - title = title.strip() - if title[0] == '*': - self.window.set_title(self.main_title) - else: - space_idx = title.rfind(" ") - if space_idx != -1: - title = title[:space_idx] - - self.window.set_title(("Portato >>> %s" % title)) - - def __update(title): - if self.tray: - self.tray.set_tooltip(title) - - window_title_update(title) - if title is None: - title = _("Console") - else: - title = ("%s (%s)") % (_("Console"), title) - - self.sysNotebook.set_tab_label_text(self.termHB, title) - - return False - - # as this might get called from other threads use gobject.idle_add - gobject.idle_add(__update, title) - - def cb_cat_list_selection (self, selection): - """ - Callback for a category-list selection. - Updates the package list with the packages in the category. - """ - # get the selected category - store, it = selection.get_selected() - if it: - self.selCatName = store.get_value(it, 0) - self.pkgList.get_model().clear() - self.fill_pkg_store(self.pkgList.get_model(), self.selCatName) - return True - - def cb_pkg_list_selection (self, selection): - """ - Callback for a package-list selection. - Updates the package info. - """ - store, it = selection.get_selected() - if it: - cp = "%s/%s" % (store.get_value(it, 2), store.get_value(it, 1)) - self.show_package(cp, self.queue) - return True - - def cb_pkg_list_header_clicked(self, col): - self.sortPkgListByName = not self.sortPkgListByName - self.pkgList.get_model().clear() - self.fill_pkg_store(self.pkgList.get_model(), self.selCatName) - return True - - def cb_queue_row_activated (self, view, path, *args): - """Callback for an activated row in the emergeQueue. Opens a package window.""" - store = self.queueTree - if len(path) > 1: - iterator = store.get_original().get_iter(path) - if store.iter_has_parent(iterator): - package = store.get_value(iterator, store.get_cpv_column()) - cat, name, vers, rev = system.split_cpv(package) - if rev != "r0": vers = vers+"-"+rev - - if store.is_in_emerge(iterator): - type = "install" - elif store.is_in_unmerge(iterator): - type = "uninstall" - elif store.is_in_update(iterator): - type = "update" - - self.show_package(cat+"/"+name, queue = self.queue, version = vers, instantChange = True, doEmerge = False, type = type) - return True - - def cb_queue_tooltip_queried (self, view, x, y, is_keyboard, tooltip): - store = self.queueList.get_model() - path = self.queueList.get_path_at_pos(x,y) - - if path is None: - return False - - it = store.get_iter(path[0]) - - if store.iter_parent(it) is None: - return False # do not show tooltips for the root entries - - pkg = system.new_package(store.get_value(it, 0)) - - enabled = [] - disabled = [] - expanded = set() - - pkg_flags = pkg.get_iuse_flags() - pkg_flags.sort() - if not pkg_flags: # no flags - stop here - return None - - actual = set(pkg.get_actual_use_flags()) - - if pkg.is_installed(): - installed = set(pkg.get_iuse_flags()).intersection(pkg.get_installed_use_flags()) - else: - inst = system.find_installed_packages(pkg.get_slot_cp()) - if inst: - installed = set(inst[0].get_iuse_flags()).intersection(inst[0].get_installed_use_flags()) - else: - installed = set() - - diff = actual.symmetric_difference(installed) - - for use in pkg_flags: - exp = pkg.use_expanded(use) - if exp: - expanded.add(exp) - - else: - useStr = use - if installed and use in diff: - useStr += " %" - if use in actual: - enabled.append(useStr) - else: - disabled.append(useStr) - - string = "" - - if enabled: - string = "<b>+%s</b>" % ("\n+".join(enabled),) - if len(disabled) > 0: - string = string + "\n" - - if disabled: - string = string+"<i>- %s</i>" % ("\n- ".join(disabled),) - - if expanded: - string = string+"\n\n"+"\n".join(expanded) - - tooltip.set_markup(string) - return string != "" - - def cb_execute_clicked (self, action): - """Execute the current queue.""" - - if len(flags.newUseFlags) > 0: - changed_flags_dialog(_("use flags")) - try: - flags.write_use_flags() - except IOError, e: - io_ex_dialog(e) - return True - - if len(flags.new_masked)>0 or len(flags.new_unmasked)>0 or len(flags.newTesting)>0: - debug("new masked: %s",flags.new_masked) - debug("new unmasked: %s", flags.new_unmasked) - debug("new testing: %s", flags.newTesting) - changed_flags_dialog(_("masking keywords")) - try: - flags.write_masked() - flags.write_testing() - except IOError, e: - io_ex_dialog(e) - return True - else: - system.reload_settings() - - model, iter = self.queueList.get_selection().get_selected() - - if iter is None: - if model.iter_n_children(None) == 1: # only one queue there - take this as being selected - iter = model.get_iter_root() - else: - return False - - self.sysNotebook.set_current_page(self.CONSOLE_PAGE) - - # test which type of queue we have here - if self.queueTree.is_in_emerge(iter): - self.queue.emerge(force = True) - elif self.queueTree.is_in_unmerge(iter): - self.queue.unmerge(force = True) - else: - self.queue.update_world(force=True, newuse = self.cfg.get_boolean("newuse"), deep = self.cfg.get_boolean("deep")) - - return True - - def cb_update_clicked (self, action): - def __update(): - - def cb_idle_append (updating): - try: - try: - for pkg, old_pkg in updating: - self.queue.append(pkg.get_cpv(), type = "update", unmask = False) - except PackageNotFoundException, e: - if unmask_dialog(e[0]) == gtk.RESPONSE_YES: - for pkg, old_pkg in updating: - self.queue.append(pkg.get_cpv(), type = "update", unmask = True) - - except BlockedException, e: - blocked_dialog(e[0], e[1]) - self.queue.remove_children(self.queueTree.get_update_it()) - - return False - - watch = gtk.gdk.Cursor(gtk.gdk.WATCH) - self.window.window.set_cursor(watch) - try: - updating = system.update_world(newuse = self.cfg.get_boolean("newuse"), deep = self.cfg.get_boolean("deep")) - debug("updating list: %s --> length: %s", [(x.get_cpv(), y.get_cpv()) for x,y in updating], len(updating)) - gobject.idle_add(cb_idle_append, updating) - finally: - self.window.window.set_cursor(None) - - GtkThread(name="Update-Thread", target=__update).start() - - return True - - def cb_remove_clicked (self, button): - """Removes a selected item in the (un)emerge-queue if possible.""" - model, iter = self.queueList.get_selection().get_selected() - - if iter: - parent = model.iter_parent(iter) - - if self.queueTree.is_in_update(iter) and parent: - if remove_updates_dialog() == gtk.RESPONSE_YES: - self.queue.remove_with_children(self.queueTree.get_update_it()) - - elif not parent: # top-level - if model.iter_n_children(iter) > 0: # and has children which can be removed :) - if remove_queue_dialog() == gtk.RESPONSE_YES : - self.queue.remove_with_children(iter) - else: - self.queue.remove(iter) - - elif model.iter_parent(parent): # this is in the 3rd level => dependency - remove_deps_dialog() - else: - self.queue.remove_with_children(iter) - - if model.iter_n_children(parent) == 0: # no more children left - remove queue too - self.queue.remove(parent) - - return True - return False - - def cb_sync_clicked (self, action): - self.sysNotebook.set_current_page(self.CONSOLE_PAGE) - cmd = self.cfg.get("syncCommand") - - if cmd != "emerge --sync": - cmd = cmd.split() - self.queue.sync(cmd) - else: - self.queue.sync() - - def cb_save_flags_clicked (self, action): - try: - flags.write_use_flags() - flags.write_testing() - flags.write_masked() - except IOError, e: - io_ex_dialog(e) - - @Window.watch_cursor - def cb_reload_clicked (self, action): - """Reloads the portage settings and the database.""" - system.reload_settings() - self.db.reload() - - @Window.watch_cursor - def cb_search_clicked (self, entry): - """Do a search.""" - text = entry.get_text() - if text != "": - if "/" not in text: - text = "/.*"+text # only look for package names - - packages = system.find_all_packages(text, withVersion = False) - - if packages == []: - nothing_found_dialog() - else: - if len(packages) == 1: - self.jump_to(packages[0]) - else: - SearchWindow(self.window, packages, self.jump_to) - - return True - - def cb_search_changed (self, *args): - """ - Called when the user enters something in the search field. - Updates the packages according to the search expression. - """ - if not self.__searchChanged and self.cfg.get_boolean("searchOnType", section="GUI"): - self.__searchChanged = True - - def __update(): - self.__searchChanged = False - txt = self.searchEntry.get_text() - - if txt or self.db.restrict: - self.db.restrict = txt - - self.refresh_stores() - self.catList.get_selection().select_path("0") # XXX make this smarter - - return False # not again ;) - - gobject.timeout_add(100, __update) - - def cb_delete_search_clicked (self, *args): - self.searchEntry.set_text("") - return True - - def cb_preferences_clicked (self, *args): - """ - User wants to open preferences. - """ - PreferenceWindow(self.window, self.cfg, self.console.set_font_from_string, self.set_uri_hook, self.set_notebook_tabpos) - return True - - def cb_about_clicked (self, *args): - """ - User wants to open about dialog. - """ - AboutWindow(self.window) - return True - - def cb_plugins_clicked (self, *args): - """ - User wants to open plugin dialog. - """ - queue = plugin.get_plugin_queue() - if queue is None: - plugins = [] - else: - plugins = queue.get_plugins() - - PluginWindow(self.window, plugins) - return True - - def cb_show_updates_clicked (self, *args): - """ - Show the list of updateble packages. - """ - - def __update(): - def cb_idle_show(packages): - """ - Callback opening the menu when the calculation is finished. - - @returns: False to signal that it is finished - """ - UpdateWindow(self.window, packages, self.queue, self.jump_to) - return False - - watch = gtk.gdk.Cursor(gtk.gdk.WATCH) - self.window.window.set_cursor(watch) - - packages = [] - try: - packages.extend(system.get_updated_packages()) - finally: - self.window.window.set_cursor(None) - - gobject.idle_add(cb_idle_show, packages) - - GtkThread(name="Show Updates Thread", target = __update).start() - return True - - def cb_show_installed_toggled (self, *args): - """ - Toggle the "show only installed" option. - """ - self.showAll = not self.showAll - self.refresh_stores() - - def cb_right_click (self, object, event): - """ - Called when the user right clicks somewhere. - Used to display a menu. - - This method should handle ALL such menus. - - @param object: the object/widget where the click is done - @type object: gtk.Widget - @param event: the event triggered - @type event: gtk.gdk.Event - """ - - if event.type == gtk.gdk.BUTTON_PRESS and event.button == 3: # 3 == right click - x = int(event.x) - y = int(event.y) - time = event.time - - if object == self.queueList: - pthinfo = object.get_path_at_pos(x, y) - if pthinfo is not None: - path, col, cellx, celly = pthinfo - it = self.queueList.get_model().get_iter(path) - if self.queueTree.is_in_emerge(it) and self.queueTree.iter_has_parent(it): - object.grab_focus() - object.set_cursor(path, col, 0) - self.queuePopup.popup(None, None, None, event.button, time) - return True - elif object == self.console: - self.consolePopup.popup(None, None, None, event.button, time) - else: - return False - else: - return False - - def cb_oneshot_clicked (self, *args): - """ - Mark a package as oneshot. - """ - sel = self.queueList.get_selection() - store, it = sel.get_selected() - if it: - package = store.get_value(it, 0) - set = (package not in self.queue.oneshotmerge) - - self.queue.append(package, update = True, oneshot = set, forceUpdate = True) - - def cb_pause_emerge (self, curr): - """ - This method returns a callback for a "pause emerge" toggle button. - It is needed as there are different toggle buttons of this type and if one is clicked, - the others should be marked too. - - @param curr: The button to return the callback for. - @type curr: gtk.ToggleButton - """ - def pause (cb): - """ - The actual callback. - - Mark all other buttons too. - - @param cb: The button which got toggled. - @type cb: gtk.ToggleButton - """ - - # pause or continue - self.emergePaused = cb.get_active() - if not self.emergePaused: - self.queue.continue_emerge() - else: - self.queue.stop_emerge() - - # block the handlers of the other buttons - # so that calling "set_active" does not call this callback recursivly - for v in self.pauseItems.itervalues(): - v[0].handler_block(v[1]) - - # mark the others - for k, v in self.pauseItems.iteritems(): - if k != curr: - v[0].set_active(self.emergePaused) - - # unblock - for v in self.pauseItems.itervalues(): - v[0].handler_unblock(v[1]) - - return False - return pause - - def cb_kill_clicked (self, *args): - """ - Kill emerge. - """ - self.queue.kill_emerge() - if self.emergePaused: # unmark the "pause emerge" buttons - self.pauseItems["menu"][0].set_active(False) # calling one button is enough (see: cb_pause_emerge) - - def cb_copy_clicked (self, *args): - """ - Copy marked text in the terminal to clipboard. - """ - self.console.copy_clipboard() - - def cb_delete (self, *args): - """ - Called when the user wants to quit the application. - - Asks the user for confirmation if there is something in the queue. - Also saves session data. - """ - - self.__save_queue = False - - if not self.queue.is_empty(): - ret = queue_not_empty_dialog() - if ret == gtk.RESPONSE_CANCEL: - return True - else: # there is sth in queue AND the user still wants to close -> kill emerge - self.__save_queue = (ret == gtk.RESPONSE_YES) - self.queue.kill_emerge() - - # write session - self.session.save() - - return False - - def cb_minimized (self, window, event): - """ - User wants to minimize the window. - If it is possible to minimize to tray, it is done. - """ - - if self.tray and self.cfg.get_boolean("hideOnMinimize", "GUI"): - if event.changed_mask & gtk.gdk.WINDOW_STATE_ICONIFIED: - if event.new_window_state & gtk.gdk.WINDOW_STATE_ICONIFIED: - self.window.hide() - return True - - return False - - def cb_systray_activated (self, *args): - """ - Systray was activated. Show or hide the window. - """ - if self.window.iconify_initially: - self.window.deiconify() - self.window.show() - self.window.window.show() - else: - self.window.iconify() - - def cb_close (self, *args): - """ - "Close" menu entry called. - Emulate normal quitting. - """ - if not self.cb_delete(): # do the checks - self.window.destroy() - - def cb_destroy (self, *args): - """ - Calls main_quit(). - """ - gtk.main_quit() - - def main (self): - """ - Main. - """ - gobject.threads_init() - # now subthreads can run normally, but are not allowed to touch the GUI. If threads should change sth there - use gobject.idle_add(). - # for more informations on threading and gtk: http://www.async.com.br/faq/pygtk/index.py?req=show&file=faq20.006.htp - gtk.main() |