summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--geneticone/backend/flags.py12
-rw-r--r--geneticone/backend/portage_helper.py2
-rw-r--r--geneticone/gui/gui_helper.py34
-rw-r--r--geneticone/gui/windows.py337
4 files changed, 209 insertions, 176 deletions
diff --git a/geneticone/backend/flags.py b/geneticone/backend/flags.py
index 214faf9..20b63ef 100644
--- a/geneticone/backend/flags.py
+++ b/geneticone/backend/flags.py
@@ -24,7 +24,7 @@ from portage_util import unique_array
def grep (pkg, path):
"""Grep runs "egrep" on a given path and looks for occurences of a given package.
@param pkg: the package
- @type pkg: string (cpv) or L{geneticone.Package}-object
+ @type pkg: string (cpv) or L{backend.Package}-object
@param path: path to look in
@type path: string
@@ -40,7 +40,7 @@ def grep (pkg, path):
def get_data(pkg, path):
"""This splits up the data of L{grep} and builds tuples in the format (file,line,criterion,list_of_flags).
@param pkg: package to find
- @type pkg: string (cpv) or L{geneticone.Package}-object
+ @type pkg: string (cpv) or L{backend.Package}-object
@param path: path to look in
@type path: string
@@ -94,7 +94,7 @@ def set_use_flag (pkg, flag):
"""Sets the useflag for a given package.
@param pkg: the package
- @type pkg: string (cpv) or L{geneticone.Package}-object
+ @type pkg: string (cpv) or L{backend.Package}-object
@param flag: the flag to set
@type flag: string"""
@@ -162,7 +162,7 @@ def set_use_flag (pkg, flag):
def remove_new_use_flags (cpv):
"""Removes all new use-flags for a specific package.
@param cpv: the package for which to remove the flags
- @type cpv: string (cpv) or L{geneticone.Package}-object"""
+ @type cpv: string (cpv) or L{backend.Package}-object"""
if isinstance(cpv, package.Package):
cpv = cpv.get_cpv()
@@ -174,7 +174,7 @@ def remove_new_use_flags (cpv):
def get_new_use_flags (cpv):
"""Gets all the new use-flags for a specific package.
@param cpv: the package for which to remove the flags
- @type cpv: string (cpv) or L{geneticone.Package}-object
+ @type cpv: string (cpv) or L{backend.Package}-object
@returns: list of flags
@rtype: list"""
@@ -438,7 +438,7 @@ arch = ""
def set_testing (pkg, enable):
"""Enables the package for installing when it is marked as testing (~ARCH).
@param pkg: the package
- @type pkg: string (cpv) or L{geneticone.Package}-object
+ @type pkg: string (cpv) or L{backend.Package}-object
@param enable: controls whether to enable (True) or disable (False) for test-installing
@type enable: boolean"""
diff --git a/geneticone/backend/portage_helper.py b/geneticone/backend/portage_helper.py
index 3346aaf..5703875 100644
--- a/geneticone/backend/portage_helper.py
+++ b/geneticone/backend/portage_helper.py
@@ -33,7 +33,7 @@ def find_lambda (name):
return lambda x: True
def geneticize_list (list_of_packages):
- """Convertes a list of gentoolkit.Packages into L{geneticone.backend.Packages}.
+ """Convertes a list of gentoolkit.Packages into L{backend.Package}s.
@param list_of_packages: the list of packages
@type list_of_packages: list of gentoolkit.Packages
@returns: converted list
diff --git a/geneticone/gui/gui_helper.py b/geneticone/gui/gui_helper.py
index 0113342..acbccd3 100644
--- a/geneticone/gui/gui_helper.py
+++ b/geneticone/gui/gui_helper.py
@@ -21,13 +21,18 @@ import pty
import vte
class Database:
+ """An internal database which holds a simple dictionary cat -> [package_list]."""
def __init__ (self):
+ """Constructor."""
self.db = {}
- def populate (self, cat = None):
- packages = backend.find_all_packages(name = cat, withVersion = False)
- installed = backend.find_all_installed_packages(name = cat, withVersion = False)
+ def populate (self, category = None):
+ """Populates the database.
+ @param category: An optional category - so only packages of this category are inserted.
+ @type category: string"""
+ packages = backend.find_all_packages(name = category, withVersion = False)
+ installed = backend.find_all_installed_packages(name = category, withVersion = False)
for p in packages:
list = p.split("/")
cat = list[0]
@@ -37,13 +42,25 @@ class Database:
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)
+
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"""
try:
return self.db[cat]
except KeyError: # cat is in category list - but not in portage
return []
def reload (self, cat):
+ """Reloads the given category.
+ @param cat: category
+ @type cat: string"""
+
del self.db[cat]
self.populate(cat+"/")
@@ -57,8 +74,8 @@ class EmergeQueue:
@type tree: gtk.TreeStore
@param console: Output is shown here. Default: None
@type console: vte.Terminal
- @param packages: The list of packages sorted by categories. We will delete the appropriate category if we updated sth. Default: None
- @type packages: dictionary: {category: list_of_packages}."""
+ @param db: A database instance.
+ @type db: Database"""
self.mergequeue = []
self.unmergequeue = []
@@ -82,7 +99,7 @@ class EmergeQueue:
@param cpv: The package to append.
@type cpv: string (cat/pkg-ver)
- @raise geneticone.BlockedException: When occured during dependency-calculation."""
+ @raise geneticone.backend.BlockedException: When occured during dependency-calculation."""
# get dependencies
if cpv in self.deps:
@@ -117,7 +134,8 @@ class EmergeQueue:
@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
- @type update: boolean"""
+ @type update: boolean
+ @raises geneticone.backend.PackageNotFoundException: if trying to add a package which does not exist"""
if not unmerge:
try:
@@ -151,7 +169,7 @@ class EmergeQueue:
self.tree.append(self.unmergeIt, [cpv])
def _update_packages(self, packages, process = None):
- """This updates the packages-list. It simply removes all affected categories so they have to be rebuilt.
+ """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
diff --git a/geneticone/gui/windows.py b/geneticone/gui/windows.py
index 4259848..95703ce 100644
--- a/geneticone/gui/windows.py
+++ b/geneticone/gui/windows.py
@@ -11,7 +11,7 @@
# our backend stuff
-VERSION = "0.3.1"
+VERSION = "0.3.4"
MENU_EMERGE = 1
MENU_UNEMERGE = 2
@@ -34,6 +34,7 @@ import vte
from portage_util import unique_array
class AboutWindow:
+ """A window showing the "about"-informations."""
def __init__ (self, parent):
# window
@@ -65,6 +66,55 @@ Copyright (C) 2006 Necoro d.M. <necoro@necoro.net>
self.window.show_all()
+class SearchWindow:
+ """A window showing the results of a search process."""
+
+ def __init__ (self, parent, list, jump_to):
+ # window
+ self.window = gtk.Window(gtk.WINDOW_TOPLEVEL)
+ self.window.set_title("Search results")
+ self.window.set_modal(True)
+ self.window.set_transient_for(parent)
+ self.window.set_destroy_with_parent(True)
+ self.window.set_resizable(False)
+ self.window.set_default_size(1,1)
+ self.window.connect("key-press-event", self.cb_key_pressed)
+ self.list = list
+ self.jump_to = jump_to
+
+ box = gtk.HBox(False)
+ self.window.add(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)
+
+ box.pack_start(self.combo)
+
+ okBtn = gtk.Button("OK")
+ okBtn.connect("clicked", self.cb_ok_btn_clicked)
+ box.pack_start(okBtn)
+
+ self.window.show_all()
+
+ def cb_ok_btn_clicked (self, button, data = None):
+ self.window.destroy()
+ self.jump_to(self.list[self.combo.get_active()])
+ return True
+
+ def cb_key_pressed (self, widget, event):
+ 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 PackageWindow:
"""A window with data about a specfic package."""
@@ -86,8 +136,7 @@ class PackageWindow:
self.window.set_destroy_with_parent(True)
self.window.set_resizable(False)
self.window.set_default_size(1,1) # as small as possible
- self.window.connect("delete-event", lambda a,b: False)
- #self.window.connect("configure-event", self.cbSizeCheck)
+ self.window.connect("key-press-event", self.cb_key_press_event)
# packages and installed packages
self.packages = backend.sort_package_list(backend.get_all_versions(cp))
@@ -103,12 +152,12 @@ class PackageWindow:
# the label (must be here, because it depends on the combo box)
desc = self.actual_package().get_env_var("DESCRIPTION")
- use_markup = True
if not desc:
desc = "<no description>"
use_markup = False
else:
desc = "<b>"+desc+"</b>"
+ use_markup = True
self.descLabel = gtk.Label(desc)
self.descLabel.set_line_wrap(True)
self.descLabel.set_justify(gtk.JUSTIFY_CENTER)
@@ -162,36 +211,54 @@ class PackageWindow:
buttonHB.pack_start(self.cancelBtn)
# current status
- self.cb_changed(self.vCombo)
+ self.cb_combo_changed(self.vCombo)
# show
self.window.show_all()
- def cb_changed (self, combo, data = None):
- """Callback for the changed ComboBox.
- It then rebuilds the useList and the checkboxes."""
- # remove old useList
- self.useListScroll.remove(self.useList)
+ def update_checkboxes (self):
+ """Updates the checkboxes."""
+ self.installedCheck.set_active(self.actual_package().is_installed())
+ self.maskedCheck.set_active(self.actual_package().is_masked())
+ self.testingCheck.set_active((self.actual_package().get_mask_status() % 3) == 1)
+
+ def fill_use_list(self, store):
+ pkg = self.actual_package()
+ pkg_flags = pkg.get_all_use_flags()
+ pkg_flags.sort()
+ for use in pkg_flags:
+ if pkg.is_installed() and use in pkg.get_actual_use_flags(): # flags set during install
+ enabled = True
+ elif (not pkg.is_installed()) and use in pkg.get_settings("USE").split() and not flags.invert_use_flag(use) in pkg.get_new_use_flags(): # flags that would be set
+ enabled = True
+ elif use in pkg.get_new_use_flags():
+ enabled = True
+ else:
+ enabled = False
+ store.append([enabled, use, backend.get_use_desc(use, self.cp)])
- # build new
- self.useList = self.build_use_list()
- self.useListScroll.add(self.useList)
- self.update_checkboxes()
+ return store
- self.useListScroll.set_policy(gtk.POLICY_NEVER, gtk.POLICY_NEVER)
+ def build_use_list (self):
+ """Builds the useList."""
+ store = gtk.ListStore(bool, str, str)
+ self.fill_use_list(store)
- # set emerge-button-label
- if not self.actual_package().is_installed():
- self.emergeBtn.set_label("_Emerge")
- self.unmergeBtn.set_sensitive(False)
+ # build view
+ view = gtk.TreeView(store)
+ cell = gtk.CellRendererText()
+ tCell = gtk.CellRendererToggle()
+ tCell.set_property("activatable", True)
+ tCell.connect("toggled", self.cb_use_flag_toggled, store)
+ view.append_column(gtk.TreeViewColumn("Enabled", tCell, active = 0))
+ view.append_column(gtk.TreeViewColumn("Flags", cell, text = 1))
+ view.append_column(gtk.TreeViewColumn("Description", cell, text = 2))
+
+ if store.iter_n_children(None) == 0: # if there are no nodes in the list ...
+ view.set_child_visible(False) # ... do not show the list
else:
- self.emergeBtn.set_label("R_emerge")
- self.unmergeBtn.set_sensitive(True)
-
- # refresh - make window as small as possible
- self.table.show_all()
- self.window.resize(1,1)
- return True
+ view.set_child_visible(True)
+ return view
def build_vers_combo (self):
"""Creates the combo box with the different versions."""
@@ -215,7 +282,7 @@ class PackageWindow:
except AttributeError: # no package found
combo.set_active(0)
- combo.connect("changed", self.cb_changed)
+ combo.connect("changed", self.cb_combo_changed)
return combo
@@ -223,6 +290,38 @@ class PackageWindow:
"""Returns the actual package (a backend.Package-object)."""
return self.packages[self.vCombo.get_active()]
+ def cb_key_press_event (self, widget, event):
+ """Closes the window if esc is pressed."""
+ keyname = gtk.gdk.keyval_name(event.keyval)
+ if keyname == "Escape":
+ self.window.destroy()
+ return True
+ else:
+ return False
+
+ def cb_combo_changed (self, combo, data = None):
+ """Callback for the changed ComboBox.
+ It then rebuilds the useList and the checkboxes."""
+
+ store = self.useList.get_model()
+ store.clear()
+ self.fill_use_list(store)
+
+ self.update_checkboxes()
+
+ # set emerge-button-label
+ if not self.actual_package().is_installed():
+ self.emergeBtn.set_label("_Emerge")
+ self.unmergeBtn.set_sensitive(False)
+ else:
+ self.emergeBtn.set_label("R_emerge")
+ self.unmergeBtn.set_sensitive(True)
+
+ # refresh - make window as small as possible
+ self.table.show_all()
+ self.window.resize(1,1)
+ return True
+
def cb_button_pressed (self, b, event, data = None):
"""Callback for pressed checkboxes. Just quits the event-loop - no redrawing."""
if not isinstance(b, gtk.CellRendererToggle):
@@ -272,79 +371,6 @@ class PackageWindow:
self.flagChanged = True
return True
- def update_checkboxes (self):
- """Updates the checkboxes."""
- self.installedCheck.set_active(self.actual_package().is_installed())
- self.maskedCheck.set_active(self.actual_package().is_masked())
- self.testingCheck.set_active((self.actual_package().get_mask_status() % 3) == 1)
-
- def build_use_list (self):
- """Builds the useList."""
- store = gtk.ListStore(bool, str, str)
-
- pkg = self.actual_package()
- for use in pkg.get_all_use_flags():
- if pkg.is_installed() and use in pkg.get_actual_use_flags(): # flags set during install
- enabled = True
- elif (not pkg.is_installed()) and use in pkg.get_settings("USE").split() and not flags.invert_use_flag(use) in pkg.get_new_use_flags(): # flags that would be set
- enabled = True
- elif use in pkg.get_new_use_flags():
- enabled = True
- else:
- enabled = False
- store.append([enabled, use, backend.get_use_desc(use, self.cp)])
-
- # build view
- view = gtk.TreeView(store)
- cell = gtk.CellRendererText()
- tCell = gtk.CellRendererToggle()
- tCell.set_property("activatable", True)
- tCell.connect("toggled", self.cb_use_flag_toggled, store)
- view.append_column(gtk.TreeViewColumn("Enabled", tCell, active = 0))
- view.append_column(gtk.TreeViewColumn("Flags", cell, text = 1))
- view.append_column(gtk.TreeViewColumn("Description", cell, text = 2))
-
- if store.iter_n_children(None) == 0:
- view.set_child_visible(False)
- else:
- view.set_child_visible(True)
- return view
-
-class SearchWindow:
- """A window showing the results of a search process."""
-
- def __init__ (self, parent, list, jump_to):
- # window
- self.window = gtk.Window(gtk.WINDOW_TOPLEVEL)
- self.window.set_title("Search results")
- self.window.set_modal(True)
- self.window.set_transient_for(parent)
- self.window.set_destroy_with_parent(True)
- self.window.set_resizable(False)
- self.window.set_default_size(1,1)
- self.list = list
- self.jump_to = jump_to
-
- box = gtk.HBox(False)
- self.window.add(box)
-
- self.combo = gtk.combo_box_new_text()
- for x in list:
- self.combo.append_text(x)
- self.combo.set_active(0)
-
- box.pack_start(self.combo)
-
- okBtn = gtk.Button("OK")
- okBtn.connect("clicked", self.cb_ok_btn_clicked)
- box.pack_start(okBtn)
-
- self.window.show_all()
-
- def cb_ok_btn_clicked (self, button, data = None):
- self.window.destroy()
- self.jump_to(self.list[self.combo.get_active()])
-
class MainWindow:
"""Application main window."""
@@ -354,7 +380,6 @@ class MainWindow:
# window
self.window = gtk.Window(gtk.WINDOW_TOPLEVEL)
self.window.set_title("Genetic/One")
- self.window.connect("delete_event", self.cb_delete)
self.window.connect("destroy", self.cb_destroy)
self.window.set_border_width(2)
self.window.set_geometry_hints (self.window, min_width = 600, min_height = 800, max_height = gtk.gdk.screen_height(), max_width = gtk.gdk.screen_width())
@@ -376,6 +401,7 @@ class MainWindow:
self.searchEntry = gtk.Entry()
self.searchBtn = gtk.Button("_Search")
self.searchBtn.connect("clicked", self.cb_search_clicked)
+ self.searchEntry.connect("activate", self.cb_search_clicked)
hbSearch = gtk.HBox(False, 5)
hbSearch.pack_start(self.searchEntry, True, True)
hbSearch.pack_start(self.searchBtn, False, False)
@@ -465,14 +491,6 @@ class MainWindow:
# set emerge queue
self.queue = EmergeQueue(console=term, tree = emergeStore, db = self.db)
- def cb_delete (self, widget, data = None):
- """Returns false -> window is deleted."""
- return False
-
- def cb_destroy (self, widget, data = None):
- """Calls main_quit()."""
- gtk.main_quit()
-
def create_main_menu (self):
"""Creates the main menu. XXX: Rebuild to use UIManager"""
# the menu-list
@@ -489,35 +507,26 @@ class MainWindow:
self.itemFactory.create_items(mainMenuDesc)
return self.itemFactory.get_widget("<main>")
- def cb_cat_list_selection (self, view, data = None, force = False):
- """Callback for a category-list selection. Updates the package list with these packages in the category."""
- if view == self.catList: # be sure it is the catList
- # get the selected category
- sel = view.get_selection()
- store, it = sel.get_selected()
-
- if it:
- # remove old one
- self.scroll_2.remove(self.pkgList)
- # create new package list
- self.pkgList = self.create_pkg_list(store.get_value(it,0), force)
- self.scroll_2.add(self.pkgList)
- self.scroll_2.show_all()
- return False
+ def fill_pkg_store (self, store, name = None):
+ if name:
+ for p in self.db.get_cat(name):
+ store.append([p])
+ return store
+
+ def create_pkg_list (self, name = None, force = False):
+ """Creates the package list. Gets the name of the category."""
+ self.selCatName = name # actual category
+ store = gtk.ListStore(str)
+ self.fill_pkg_store(store,name)
+
+ # build view
+ pkgList = gtk.TreeView(store)
+ cell = gtk.CellRendererText()
+ col = gtk.TreeViewColumn("Packages", cell, text = 0)
+ pkgList.append_column(col)
+ pkgList.connect("row-activated", self.cb_row_activated, store)
- def cb_row_activated (self, view, path, col, store = None):
- """Callback for an activated row in the pkgList. Opens a package window."""
- if view == self.pkgList:
- package = store.get_value(store.get_iter(path), 0)
- if package[-1] == '*': package = package[:-1]
- PackageWindow(self.window, self.selCatName+"/"+package, self.queue)
- elif view == self.emergeView:
- if len(path) > 1:
- package = store.get_value(store.get_iter(path), 0)
- cat, name, vers, rev = backend.split_package_name(package)
- if rev != "r0": vers = vers+"-"+rev
- PackageWindow(self.window, cat+"/"+name, queue = self.queue, version = vers, delOnClose = False, doEmerge = False)
- return True
+ return pkgList
def create_cat_list (self):
"""Creates the category list."""
@@ -539,28 +548,38 @@ class MainWindow:
return view
- packages = {} # directory category -> [packages]
- def create_pkg_list (self, name = None, force = False):
- """Creates the package list. Gets the name of the category."""
- self.selCatName = name # actual category
- store = gtk.ListStore(str)
-
- # calculate packages
- if name:
- for p in self.db.get_cat(name):
- store.append([p])
-
- # sort alphabetically
- store.set_sort_column_id(0, gtk.SORT_ASCENDING)
+ def jump_to (self, cp):
+ """Is called when we want to jump to a specific package."""
+ PackageWindow(self.window, cp, self.queue)
+
+ def cb_destroy (self, widget, data = None):
+ """Calls main_quit()."""
+ gtk.main_quit()
- # build view
- pkgList = gtk.TreeView(store)
- cell = gtk.CellRendererText()
- col = gtk.TreeViewColumn("Packages", cell, text = 0)
- pkgList.append_column(col)
- pkgList.connect("row-activated", self.cb_row_activated, store)
+ def cb_cat_list_selection (self, view, data = None, force = False):
+ """Callback for a category-list selection. Updates the package list with these packages in the category."""
+ if view == self.catList: # be sure it is the catList
+ # get the selected category
+ sel = view.get_selection()
+ store, it = sel.get_selected()
+ if it:
+ self.pkgList.get_model().clear()
+ self.fill_pkg_store(self.pkgList.get_model(), store.get_value(it, 0))
+ return False
- return pkgList
+ def cb_row_activated (self, view, path, col, store = None):
+ """Callback for an activated row in the pkgList. Opens a package window."""
+ if view == self.pkgList:
+ package = store.get_value(store.get_iter(path), 0)
+ if package[-1] == '*': package = package[:-1]
+ PackageWindow(self.window, self.selCatName+"/"+package, self.queue)
+ elif view == self.emergeView:
+ if len(path) > 1:
+ package = store.get_value(store.get_iter(path), 0)
+ cat, name, vers, rev = backend.split_package_name(package)
+ if rev != "r0": vers = vers+"-"+rev
+ PackageWindow(self.window, cat+"/"+name, queue = self.queue, version = vers, delOnClose = False, doEmerge = False)
+ return True
def cb_remove_clicked (self, button, data = None):
"""Removes a selected item in the (un)emerge-queue if possible."""
@@ -614,10 +633,6 @@ class MainWindow:
else:
SearchWindow(self.window, packages, self.jump_to)
- def jump_to (self, cp):
- """Is called when we want to jump to a specific package."""
- PackageWindow(self.window, cp, self.queue)
-
def main (self):
"""Main."""
gobject.threads_init()