summaryrefslogtreecommitdiff
path: root/geneticone
diff options
context:
space:
mode:
Diffstat (limited to 'geneticone')
-rw-r--r--geneticone/gui/gui_helper.py265
-rw-r--r--geneticone/gui/windows.py115
2 files changed, 298 insertions, 82 deletions
diff --git a/geneticone/gui/gui_helper.py b/geneticone/gui/gui_helper.py
index cb9e612..449fa9c 100644
--- a/geneticone/gui/gui_helper.py
+++ b/geneticone/gui/gui_helper.py
@@ -9,19 +9,22 @@
#
# Written by Necoro d.M. <necoro@necoro.net>
+# some backend things
from geneticone import backend
from geneticone.backend import flags
from geneticone.helper import *
+
+# our dialogs
import dialogs
+# some stuff needed
from subprocess import Popen, PIPE, STDOUT
from threading import Thread
from ConfigParser import SafeConfigParser
-
import pty
-import vte
class Config:
+ """Wrapper around a ConfigParser and for additional local configurations."""
const = {
"main_sec" : "Main",
"usePerVersion_opt" : "usePerVersion",
@@ -35,7 +38,16 @@ class Config:
}
def __init__ (self, cfgFile):
+ """Constructor.
+ @attention: If cfgFile is a file, it is closed afterwards!
+
+ @param cfgFile: path to config file or file-object of the config-file.
+ @type cfgFile: string or file"""
+
+ # init ConfigParser
self._cfg = SafeConfigParser()
+
+ # set correct file-obj
if not isinstance(cfgFile, file):
self._file = open(cfgFile) # assume string
elif cfgFile.closed:
@@ -43,18 +55,41 @@ class Config:
else:
self._file = cfgFile
+ # read config
self._cfg.readfp(self._file)
self._file.close()
+ # local configs
self.local = {}
def get(self, name, section=const["main_sec"]):
+ """Gets an option.
+
+ @param name: name of the option
+ @type name: string
+ @param section: section to look in; default is Main-Section
+ @type section: string
+ @return: the option's value
+ @rtype: string"""
+
return self._cfg.get(section, name)
def get_boolean(self, name, section=const["main_sec"]):
+ """Gets a boolean option.
+
+ @param name: name of the option
+ @type name: string
+ @param section: section to look in; default is Main-Section
+ @type section: string
+ @return: the option's value
+ @rtype: boolean"""
+
return self._cfg.getboolean(section, name)
def modify_flags_config (self):
+ """Sets the internal config of the L{flags}-module.
+ @see: L{flags.set_config()}"""
+
flagCfg = {
"usefile": self.get(self.const["useFile_opt"]),
"usePerVersion" : self.get_boolean(self.const["usePerVersion_opt"]),
@@ -65,15 +100,40 @@ class Config:
flags.set_config(flagCfg)
def modify_debug_config (self):
+ """Sets the external debug-config.
+ @see: L{helper.set_debug()}"""
set_debug(self.get_boolean(self.const["debug_opt"]))
+ def modify_external_configs (self):
+ """Convenience function setting all external configs."""
+ self.modify_debug_config()
+ self.modify_flags_config()
+
def set_local(self, cpv, name, val):
+ """Sets some local config.
+
+ @param cpv: the cpv describing the package for which to set this option
+ @type cpv: string (cpv)
+ @param name: the option's name
+ @type name: string
+ @param val: the value to set
+ @type val: any"""
+
if not cpv in self.local:
self.local[cpv] = {}
self.local[cpv].update({name:val})
def get_local(self, cpv, name):
+ """Returns something out of the local config.
+
+ @param cpv: the cpv describing the package from which to get this option
+ @type cpv: string (cpv)
+ @param name: the option's name
+ @type name: string
+ @return: value stored for the cpv and name or None if not found
+ @rtype: any"""
+
if not cpv in self.local:
return None
if not name in self.local[cpv]:
@@ -82,57 +142,74 @@ class Config:
return self.local[cpv][name]
def set(self, name, val, section=const["main_sec"]):
+ """Sets an option.
+
+ @param name: name of the option
+ @type name: string
+ @param val: value to set the option to
+ @type val: string or boolean
+ @param section: section to look in; default is Main-Section
+ @type section: string"""
+
self._cfg.set(section, name, val)
def write(self):
+ """Writes to the config file and modify any external configs."""
self._file = open(self._file.name,"w")
self._cfg.write(self._file)
- self.modify_flags_config()
- self.modify_debug_config()
+ self.modify_external_configs()
class Database:
"""An internal database which holds a simple dictionary cat -> [package_list]."""
def __init__ (self):
"""Constructor."""
- self.db = {}
+ self._db = {}
def populate (self, category = None):
"""Populates the database.
+
@param category: An optional category - so only packages of this category are inserted.
@type category: string"""
+
+ # get the lists
packages = backend.find_all_packages(name = category, withVersion = False)
installed = backend.find_all_installed_packages(name = category, withVersion = False)
+
+ # cycle through packages
for p in packages:
list = p.split("/")
cat = list[0]
pkg = list[1]
if p in installed:
pkg += "*"
- if not cat in self.db: self.db[cat] = []
- self.db[cat].append(pkg)
+ if not cat in self._db: self._db[cat] = []
+ self._db[cat].append(pkg)
- for key in self.db:
- self.db[key].sort(cmp=cmp, key=str.lower)
+ for key in self._db: # sort alphabetically
+ self._db[key].sort(cmp=cmp, key=str.lower)
def get_cat (self, cat):
"""Returns the packages in the category.
+
@param cat: category to return the packages from
@type cat: string
@return: list of packages or []
- @rtype: list of strings"""
+ @rtype: string[]"""
+
try:
- return self.db[cat]
+ return self._db[cat]
except KeyError: # cat is in category list - but not in portage
debug("Catched KeyError =>", cat, "seems not to be an available category. Have you played with rsync-excludes?")
return []
def reload (self, cat):
"""Reloads the given category.
+
@param cat: category
@type cat: string"""
- del self.db[cat]
+ del self._db[cat]
self.populate(cat+"/")
class EmergeQueue:
@@ -141,22 +218,28 @@ class EmergeQueue:
def __init__ (self, tree = None, console = None, db = None):
"""Constructor.
- @param tree: Tree to append all the items to. Default: None.
+ @param tree: Tree to append all the items to.
@type tree: gtk.TreeStore
- @param console: Output is shown here. Default: None
+ @param console: Output is shown here.
@type console: vte.Terminal
@param db: A database instance.
@type db: Database"""
- self.mergequeue = []
- self.unmergequeue = []
- self.oneshotmerge = []
- self.iters = {}
- self.deps = {}
+ # the different queues
+ self.mergequeue = [] # for emerge
+ self.unmergequeue = [] # for emerge -C
+ self.oneshotmerge = [] # for emerge --oneshot
+
+ # dictionaries with data about the packages in the queue
+ self.iters = {} # iterator in the tree
+ self.deps = {} # all the deps of the package
+
+ # member vars
self.tree = tree
self.console = console
self.db = db
-
+
+ # our iterators pointing at the toplevels; they are set to None if do not have a tree
if self.tree:
self.emergeIt = self.tree.append(None, ["Emerge", ""])
self.unmergeIt = self.tree.append(None, ["Unmerge", ""])
@@ -164,22 +247,37 @@ class EmergeQueue:
self.emergeIt = self.unmergeIt = None
def _get_pkg_from_cpv (self, cpv, unmask = False):
+ """Gets a L{backend.Package}-object from a cpv.
+
+ @param cpv: the cpv to get the package for
+ @type cpv: string (cpv)
+ @param unmask: if True we will look for masked packages if we cannot find unmasked ones
+ @type unmask: boolean
+ @return: created package
+ @rtype: backend.Package
+
+ @raises backend.PackageNotFoundException: If no package could be found - normally it is existing but masked."""
+
+ # for the beginning: let us create a package object - but it is not guaranteed, that it actually exists in portage
pkg = backend.Package(cpv)
- if not pkg.is_masked() and not pkg.is_testing(allowed=True):
- masked = True
- else:
- masked = False
+ masked = not (pkg.is_masked() or pkg.is_testing(allowed=True)) # <-- why am I doing this? FIXME
+
+ # and now try to find it in portage
pkg = backend.find_packages("="+cpv, masked = masked)
- if pkg:
+
+ if pkg: # gotcha
pkg = pkg[0]
- elif unmask:
+
+ elif unmask: # no pkg returned, but we are allowed to unmask it
pkg = backend.find_packages("="+cpv, masked = True)[0]
if pkg.is_testing(allowed = True):
pkg.set_testing(True)
if pkg.is_masked():
pkg.set_masked()
- else:
+
+ else: # no pkg returned - and we are not allowed to unmask
raise backend.PackageNotFoundException(cpv)
+
return pkg
def update_tree (self, it, cpv, unmask = False, options = ""):
@@ -189,16 +287,20 @@ class EmergeQueue:
@type it: gtk.TreeIter
@param cpv: The package to append.
@type cpv: string (cat/pkg-ver)
+ @param unmask: True if we are allowed to look for masked packages
+ @type unmask: boolean
+ @param options: options to append to the tree
+ @type options: string
- @raise geneticone.backend.BlockedException: When occured during dependency-calculation."""
+ @raises backend.BlockedException: When occured during dependency-calculation.
+ @raises backend.PackageNotFoundException: If no package could be found - normally it is existing but masked."""
- # get dependencies
if cpv in self.deps:
- return # in list already
+ return # in list already and therefore it's already in the tree too
try:
pkg = self._get_pkg_from_cpv(cpv, unmask)
- except backend.PackageNotFoundException, e:
+ except backend.PackageNotFoundException, e: # package not found / package is masked -> delete current tree and re-raise the exception
if self.tree.iter_parent(it):
while self.tree.iter_parent(it):
it = self.tree.iter_parent(it)
@@ -209,31 +311,39 @@ class EmergeQueue:
subIt = self.tree.append(it, [cpv, "<i>"+options+"</i>"])
self.iters.update({cpv: subIt})
- deps = pkg.get_dep_packages()
+ # get dependencies
+ deps = pkg.get_dep_packages() # this might raise a BlockedException
self.deps.update({cpv : deps})
# recursive call
for d in deps:
try:
self.update_tree(subIt, d, unmask)
- except backend.BlockedException, e:
+ except backend.BlockedException, e: # BlockedException occured -> delete current tree and re-raise exception
debug("Something blocked:", e[0])
self.remove_with_children(subIt)
raise e
- def append (self, cpv, unmerge = False, update = False, unmask = False, oneshot = False, forceUpdate = False):
+ def append (self, cpv, unmerge = False, update = False, forceUpdate = False, unmask = False, oneshot = False):
"""Appends a cpv either to the merge queue or to the unmerge-queue.
Also updates the tree-view.
@param cpv: Package to add
@type cpv: string (cat/pkg-ver)
- @param unmerge: Set to True if you want to unmerge this package - else False. Default: False
- @type unmerge: boolean
- @param update: Set to True if a package is going to be updated (e.g. if the use-flags changed). Default: False
+ @param unmerge: Set to True if you want to unmerge this package - else False.
+ @type unmerge: boolean
+ @param update: Set to True if a package is going to be updated (e.g. if the use-flags changed).
@type update: boolean
+ @param forceUpdate: Set to True if the update should be forced.
+ @type forceUpdate: boolean
+ @param unmask: True if we are allowed to look for masked packages
+ @type unmask: boolean
+ @param oneshot: True if this package should not be added to the world-file.
+ @type oneshot: boolean
+
@raises geneticone.backend.PackageNotFoundException: if trying to add a package which does not exist"""
- if not unmerge:
+ if not unmerge: # emerge
try:
# insert dependencies
pkg = self._get_pkg_from_cpv(cpv, unmask)
@@ -246,38 +356,53 @@ class EmergeQueue:
hasBeenInQueue = (cpv in self.mergequeue or cpv in self.oneshotmerge)
parentIt = self.tree.iter_parent(self.iters[cpv])
options = ""
- self.remove_with_children(self.iters[cpv], False) # this is needed to def delete everything
- if hasBeenInQueue:
- if not oneshot:
- self.mergequeue.append(cpv)
- else:
- self.oneshotmerge.append(cpv)
- options="oneshot"
+ # delete it out of the tree - but NOT the changed flags
+ self.remove_with_children(self.iters[cpv], removeNewFlags = False)
+
+ if hasBeenInQueue: # package has been in queue before
+ options = self._queue_append(cpv, oneshot)
+
self.update_tree(parentIt, cpv, unmask, options = options)
else: # not update
- options = ""
- if not oneshot: self.mergequeue.append(cpv)
- else:
- self.oneshotmerge.append(cpv)
- options = "oneshot"
- if self.emergeIt: self.update_tree(self.emergeIt, cpv, unmask, options)
+ options = self._queue_append(cpv, oneshot)
+ if self.emergeIt:
+ self.update_tree(self.emergeIt, cpv, unmask, options)
except backend.BlockedException, e : # there is sth blocked --> call blocked_dialog
blocks = e[0]
dialogs.blocked_dialog(cpv, blocks)
return
+
else: # unmerge
self.unmergequeue.append(cpv)
if self.unmergeIt: # update tree
self.tree.append(self.unmergeIt, [cpv])
+
+ def _queue_append (self, cpv, oneshot = False):
+ """Convenience function appending a cpv either to self.mergequeue or to self.oneshotmerge.
+
+ @param cpv: cpv to add
+ @type cpv: string (cpv)
+ @param onehost: True if this package should not be added to the world-file.
+ @type oneshot: boolean
+
+ @returns: options set
+ @rtype: string"""
+
+ options = ""
+ if not oneshot:
+ self.mergequeue.append(cpv)
+ else:
+ self.oneshotmerge.append(cpv)
+ options="oneshot"
def _update_packages(self, packages, process = None):
"""This updates the packages-list. It simply makes the db to rebuild the specific category.
@param packages: The packages which we emerged.
@type packages: list of cpvs
- @param process: The process we have to wait for before we can do our work. Default: None.
+ @param process: The process we have to wait for before we can do our work.
@type process: subprocess.Popen"""
if process: process.wait()
@@ -304,6 +429,8 @@ class EmergeQueue:
# start emerge
process = Popen(["/usr/bin/python","/usr/bin/emerge"]+options+packages, stdout = slave, stderr = STDOUT, shell = False)
+
+ # start thread waiting for the stop of emerge
Thread(target=self._update_packages, args=(packages, process)).start()
# remove
@@ -315,27 +442,32 @@ class EmergeQueue:
@param force: If False, '-pv' is send to emerge. Default: False.
@type force: boolean"""
-
- if len(self.oneshotmerge) != 0:
- # prepare package-list for oneshot
+
+ def prepare(queue):
+ """Prepares the list of iterators and the list of packages."""
list = []
its = []
- for k in self.oneshotmerge:
+ for k in queue:
list += ["="+k]
its.append(self.iters[k])
+ return list, its
+
+ # oneshot-queue
+ if len(self.oneshotmerge) != 0:
+ # prepare package-list for oneshot
+ list, its = prepare
+
s = ["--oneshot"]
if not force: s += ["--verbose", "--pretend"]
+
self._emerge(s, list, its)
+ # normal queue
if len(self.mergequeue) != 0:
# prepare package-list
- list = []
- its = []
- for k in self.mergequeue:
- list += ["="+k]
- its.append(self.iters[k])
-
+ list, its = prepare
+
s = []
if not force: s = ["--verbose", "--pretend"]
@@ -358,6 +490,13 @@ class EmergeQueue:
self._emerge(s,list, [self.unmergeIt])
def remove_with_children (self, it, removeNewFlags = True):
+ """Convenience function which removes all children of an iterator and than the iterator itself.
+
+ @param parentIt: The iter which to remove.
+ @type parentIt: gtk.TreeIter
+ @param removeNewFlags: True if new flags should be removed; False otherwise. Default: True.
+ @type removeNewFlags: boolean"""
+
self.remove_children(it, removeNewFlags)
self.remove(it, removeNewFlags)
@@ -402,7 +541,7 @@ class EmergeQueue:
except ValueError:
debug("Catched ValueError =>", cpv, "seems not to be in merge-queue. Should be no harm.")
- if removeNewFlags:
+ if removeNewFlags: # remove the changed flags
flags.remove_new_use_flags(cpv)
flags.remove_new_masked(cpv)
flags.remove_new_testing(cpv)
diff --git a/geneticone/gui/windows.py b/geneticone/gui/windows.py
index 1b16598..a08fe16 100644
--- a/geneticone/gui/windows.py
+++ b/geneticone/gui/windows.py
@@ -28,22 +28,40 @@ from gui_helper import Database, Config, EmergeQueue
from dialogs import *
# for the terminal
-import pty
import vte
# other
from portage_util import unique_array
class AbstractDialog:
+ """A class all our dialogs get derived from. It sets useful default vars and automatically handles the ESC-Button."""
def __init__ (self, parent, title):
+ """Constructor.
+
+ @param parent: the parent window
+ @type parent: gtk.Window
+ @param title: the title of the window
+ @type title: string"""
+
+ # create new
self.window = gtk.Window(gtk.WINDOW_TOPLEVEL)
+
+ # set title
self.window.set_title(title)
+
+ # set modal and transient for the parent --> you have to close this one to get back to the parent
self.window.set_modal(True)
self.window.set_transient_for(parent)
self.window.set_destroy_with_parent(True)
+
+ # not resizable
self.window.set_resizable(False)
+
+ # default size = (1,1) ==> as small as possible
self.window.set_default_size(1,1)
+
+ # catch the ESC-key
self.window.connect("key-press-event", self.cb_key_pressed)
def cb_key_pressed (self, widget, event):
@@ -59,10 +77,17 @@ class AboutWindow (AbstractDialog):
"""A window showing the "about"-informations."""
def __init__ (self, parent):
+ """Constructor.
+
+ @param parent: the parent window
+ @type parent: gtk.Window"""
+
AbstractDialog.__init__(self, parent, "About Genetic/One")
+
box = gtk.VBox(False)
self.window.add(box)
+ # about label
label = gtk.Label()
label.set_justify(gtk.JUSTIFY_CENTER)
label.set_markup("""
@@ -76,69 +101,104 @@ Copyright (C) 2006 Necoro d.M. &lt;necoro@necoro.net&gt;
""" % VERSION)
box.pack_start(label)
+ # button
okBtn = gtk.Button("OK")
okBtn.connect("clicked", lambda x: self.window.destroy())
box.pack_start(okBtn)
+ # finished -> show
self.window.show_all()
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, "Search results")
- self.list = list
- self.jump_to = jump_to
+ self.list = list # list to show
+ self.jump_to = jump_to # function to call for jumping
box = gtk.HBox(False)
self.window.add(box)
+ # combo box
self.combo = gtk.combo_box_new_text()
for x in list:
self.combo.append_text(x)
- self.combo.set_active(0)
- self.combo.connect("key-press-event", self.cb_key_pressed)
+ self.combo.set_active(0) # first item
+ self.combo.connect("key-press-event", self.cb_key_pressed_combo)
box.pack_start(self.combo)
+ # ok-button
okBtn = gtk.Button("OK")
okBtn.connect("clicked", self.cb_ok_btn_clicked)
box.pack_start(okBtn)
+ # finished --> show
self.window.show_all()
- def cb_ok_btn_clicked (self, button, data = None):
+ def cb_ok_btn_clicked (self, button):
+ """Called if the OK-Button is clicked.
+ Calls self.jump_to(selected_entry) and closes the window."""
self.window.destroy()
self.jump_to(self.list[self.combo.get_active()])
return True
- def cb_key_pressed (self, widget, event):
+ 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.cb_ok_btn_clicked(self,widget)
return True
- elif keyname == "Escape":
- self.window.destroy()
- return True
else:
return False
class PreferenceWindow (AbstractDialog):
+ """Window displaying some preferences."""
def __init__ (self, parent, cfg):
- AbstractDialog.__init__(self, parent, "Preferences")
- self.window.set_resizable(True)
+ """Constructor.
+
+ @param parent: parent window
+ @type parent: gtk.Window
+ @param cfg: configuration object
+ @type cfg: gui_helper.Config"""
+ AbstractDialog.__init__(self, parent, "Preferences")
+ self.window.set_resizable(True) # override the default of the AbstractDialog
+
+ # our config
self.cfg = cfg
- box = gtk.VBox(True)
+ box = gtk.VBox()
+ box.set_spacing(5)
+
self.window.add(box)
+ # En-/Disable Debugging
self.debugCb = gtk.CheckButton(label="Debugging modus")
self.debugCb.set_active(self.cfg.get_boolean(self.cfg.const["debug_opt"]))
box.pack_start(self.debugCb, True, True)
+ pHolderLabel = gtk.Label("""<u>For the following options, you might use these placeholders:</u>
+<b>$(cat)</b> = category
+<b>$(pkg)</b> = package-name
+<b>$(cat-1)</b>/<b>$(cat-2)</b> = first/second part of the category""")
+ pHolderLabel.set_use_markup(True)
+ pHolderLabel.set_alignment(0,0)
+ box.pack_start(pHolderLabel)
+
+ # The use/mask/keywording checkboxes and edits
self.usePerVersionCb, self.useFileEdit = self.draw_cb_and_edit(box, "package.use", "usePerVersion_opt", "useFile_opt")
self.maskPerVersionCb, self.maskFileEdit = self.draw_cb_and_edit(box, "package.mask/package.unmask", "maskPerVersion_opt", "maskFile_opt")
self.testPerVersionCb, self.testFileEdit = self.draw_cb_and_edit(box, "package.keywords", "testingPerVersion_opt", "testingFile_opt")
@@ -155,16 +215,32 @@ class PreferenceWindow (AbstractDialog):
box.pack_start(buttonHB, True, True, 5)
+ # finished --> show all
self.window.show_all()
def draw_cb_and_edit (self, box, string, cb_opt, edit_opt):
+ """Draws a checkbox and an edit-field.
+
+ @param box: box to place the both things into
+ @type box: gtk.Box
+ @param string: string to show
+ @type string: string
+ @param cb_opt: the option string for the Config.const-dict
+ @type cb_opt: string
+ @param edit_opt: the option string for the Config.const-dic
+ @type edit_opt: string
+
+ @return: the checkbox and the edit-field
+ @rtype: (gtk.CheckButton, gtk.Edit)"""
+
+ # check-button
cb = gtk.CheckButton(label=("Add to %s on a per-version-base" % string))
cb.set_active(self.cfg.get_boolean(self.cfg.const[cb_opt]))
box.pack_start(cb, True, True)
+ # edit with label
hBox = gtk.HBox()
- label = gtk.Label(("File name to use if %s is a directory:\n<small><b>$(cat)</b> = category\n<b>$(pkg)</b> = package-name\n<b>$(cat-1)</b>/<b>$(cat-2)</b> = first/second part of the category</small>" % string))
- label.set_use_markup(True)
+ label = gtk.Label("File name to use if %s is a directory:" % string)
edit = gtk.Entry()
edit.set_text(self.cfg.get(self.cfg.const[edit_opt]))
hBox.pack_start(label, False)
@@ -174,6 +250,7 @@ class PreferenceWindow (AbstractDialog):
return (cb, edit)
def _save(self):
+ """Sets all options in the Config-instance."""
self.cfg.set(self.cfg.const["usePerVersion_opt"], str(self.usePerVersionCb.get_active()))
self.cfg.set(self.cfg.const["useFile_opt"], self.useFileEdit.get_text())
self.cfg.set(self.cfg.const["maskPerVersion_opt"], str(self.maskPerVersionCb.get_active()))
@@ -183,6 +260,7 @@ class PreferenceWindow (AbstractDialog):
self.cfg.set(self.cfg.const["debug_opt"], str(self.debugCb.get_active()))
def cb_ok_clicked(self, button):
+ """Saves, writes to config-file and closes the window."""
self._save()
self.cfg.write()
self.window.destroy()
@@ -506,8 +584,7 @@ class MainWindow:
# config
self.cfg = Config(CONFIG_LOCATION)
- self.cfg.modify_flags_config()
- self.cfg.modify_debug_config()
+ self.cfg.modify_external_configs()
# actions needed
self.emergeAction = gtk.Action("Emerge", "_Emerge", None, None)
@@ -654,9 +731,9 @@ class MainWindow:
("File", None, "_File"),
("EmergeMenu", None, "_Emerge"),
("Help", None, "_?"),
- ("Prefs", None, "_Preferences", None, None, lambda x,y: PreferenceWindow(self.window, self.cfg)),
+ ("Prefs", None, "_Preferences", None, None, lambda x: PreferenceWindow(self.window, self.cfg)),
("Close", None, "_Close", None, None, self.cb_destroy),
- ("About", None, "_About", None, None, lambda x,y: AboutWindow(self.window))])
+ ("About", None, "_About", None, None, lambda x: AboutWindow(self.window))])
group.add_action(self.emergeAction)
group.add_action(self.unmergeAction)
um.insert_action_group(group,0)