From 2c79a7fc6ea5995ecdc7e3f8c83fe410586d9f6e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9=20=27Necoro=27=20Neumann?= Date: Fri, 5 Dec 2008 12:54:37 +0100 Subject: Make the dependency list lazy --- portato/gui/templates/MainWindow.glade | 206 +++++++++++++++---------------- portato/gui/views.py | 14 +++ portato/gui/windows/main.py | 215 ++++++++++++++++----------------- 3 files changed, 217 insertions(+), 218 deletions(-) (limited to 'portato') diff --git a/portato/gui/templates/MainWindow.glade b/portato/gui/templates/MainWindow.glade index f609344..50db1d8 100644 --- a/portato/gui/templates/MainWindow.glade +++ b/portato/gui/templates/MainWindow.glade @@ -1,6 +1,6 @@ - + 2 @@ -46,8 +46,8 @@ Re_load Portage True - + True @@ -424,7 +424,6 @@ True - True 0 @@ -442,7 +441,6 @@ True - True 1 @@ -597,271 +595,271 @@ - + True GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK True 0 - use flags - PANGO_ELLIPSIZE_END + label True 1 2 - 4 - 5 + 3 + 4 - + True GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - True 0 - <b>Use Flags:</b> + <b>License:</b> True True - 4 - 5 + 3 + 4 GTK_FILL 5 - + True - True GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK True - Testing - 0 - 0 - True - + <b>Installed, but not in portage anymore</b> + True - 7 - 8 - GTK_FILL + 2 + 5 + 6 - + True GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 0 + True + <span foreground='red'><b>MISSING KEYWORD</b></span> + True - 1 2 - 8 - 9 + 5 + 6 - + True - True GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - True - Masked - 0 - 0 - True - + 5 + + + - 8 - 9 - GTK_FILL + 1 + 2 + 2 + 3 - + True - True GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - True - Installed 0 - 0 - True - + <b>Description:</b> + True + True - 6 - 7 GTK_FILL + 5 - + True GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + True 0 - <b>Homepage:</b> + <b>Overlay:</b> True True - 2 - 3 + 1 + 2 GTK_FILL 5 - + True GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - True 0 label - True + True 1 2 - 1 - 2 - + True GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + True 0 label - True + True 1 2 + 1 + 2 - + True GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - True 0 - <b>Overlay:</b> + <b>Homepage:</b> True True - 1 - 2 + 2 + 3 GTK_FILL 5 - + True + True GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + True + Installed 0 - <b>Description:</b> - True - True + 0 + True + + 6 + 7 GTK_FILL - 5 - + True + True GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 5 - - - + True + Masked + 0 + 0 + True + - 1 - 2 - 2 - 3 + 8 + 9 + GTK_FILL - + True GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - True - <span foreground='red'><b>MISSING KEYWORD</b></span> - True + 0 + 1 2 - 5 - 6 + 8 + 9 - + True + True GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK True - <b>Installed, but not in portage anymore</b> - True + Testing + 0 + 0 + True + - 2 - 5 - 6 + 7 + 8 + GTK_FILL - + True GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + True 0 - <b>License:</b> + <b>Use Flags:</b> True True - 3 - 4 + 4 + 5 GTK_FILL 5 - + True GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK True 0 - label + use flags + PANGO_ELLIPSIZE_END True 1 2 - 3 - 4 + 4 + 5 @@ -893,7 +891,6 @@ True True GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - True @@ -921,14 +918,7 @@ GTK_POLICY_AUTOMATIC GTK_POLICY_AUTOMATIC - - True - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - False - True - False - + diff --git a/portato/gui/views.py b/portato/gui/views.py index 85a06c8..26a8a89 100644 --- a/portato/gui/views.py +++ b/portato/gui/views.py @@ -46,6 +46,20 @@ class LazyView (object): def _get_content (self): raise NotImplementedError +class LazyStoreView (gtk.TreeView, LazyView): + def __init__ (self, update_fn): + gtk.TreeView.__init__(self) + LazyView.__init__(self) + + self.update_fn = update_fn + + def cb_mapped (self, *args): + if self.updated and self.pkg: + self.set_model(self.update_fn(self.pkg)) + self.updated = False + + return False + class ListView (gtk.TextView, LazyView): def __init__ (self, content_fn): diff --git a/portato/gui/windows/main.py b/portato/gui/windows/main.py index 5420b40..dd556bb 100644 --- a/portato/gui/windows/main.py +++ b/portato/gui/windows/main.py @@ -34,7 +34,7 @@ from ..utils import Database, Config, GtkThread, get_color from ..queue import EmergeQueue from ..session import SESSION_VERSION, SessionException, OldSessionException, NewSessionException from ..wrapper import GtkTree, GtkConsole -from ..views import LogView, HighlightView, InstalledOnlyView +from ..views import LogView, HighlightView, InstalledOnlyView, LazyStoreView 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) @@ -97,21 +97,12 @@ class PackageTable: 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() + self.depView = self.tree.get_widget("dependencyScroll").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, pkg, queue = None, doEmerge = True, instantChange = False, type = None): """Updates the table to show the contents for the package. @@ -205,78 +196,6 @@ class PackageTable: self.useFlagsLL.hide() self.useFlagsLabel.hide() - def fill_dep_list(self): - - store = self.depList.get_model() - - 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]) - - def cmp_flag (x, y): - # get strings - as tuples are passed - x = x[0] - y = y[0] - - # remove "!" - ret = 0 - if x[0] == "!": - ret = 1 - x = x[1:] - if y[0] == "!": - ret = ret - 1 # if it is already 1, it is 0 now :) - y = y[1:] - - # cmp -- if two flags are equal, the negated one is greater - return cmp(x,y) or ret - - def get_icon (dep): - if dep.satisfied: - return self.icons["installed"] - elif dep.dep[0] == "!": - return self.icons["block"] - else: - return None - - def add (tree, it): - # useflags - flags = sorted(tree.flags.iteritems(), cmp = cmp_flag) - for use, usetree in flags: - 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 - for ortree in tree.ors: - orit = store.append(it, [self.icons["or"], _("One of the following")]) - add(ortree, orit) - - # Sub (all of) - for subtree in tree.subs: - allit = store.append(it, [None, _("All of the following")]) - add(subtree, allit) - - # normal - ndeps = sorted(tree.deps, key = sort_key) - for dep in ndeps: - store.append(it, [get_icon(dep), dep.dep]) - - try: - deptree = self.pkg.get_dependencies() - except AssertionError: - w = _("Can't display dependencies: This package has an unsupported dependency string.") - error(w) - store.append(None, [None, w]) - else: - add(deptree, None) - def fill_use_list(self): pkg = self.pkg @@ -305,23 +224,6 @@ class PackageTable: installed = use in instuse store.append(actual_exp_it, [enabled, installed, use, system.get_use_desc(use, self.pkg.get_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) @@ -365,7 +267,7 @@ class PackageTable: pkg = self.pkg # set the views - for v in (self.ebuildView, self.changelogView, self.filesView): + for v in (self.ebuildView, self.changelogView, self.filesView, self.depView): v.update(pkg, force = self.notebook.get_nth_page(self.notebook.get_current_page()) == v.get_parent()) # set the labels @@ -376,11 +278,6 @@ class PackageTable: 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 # @@ -593,8 +490,12 @@ class MainWindow (Window): 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) + # 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) # get the logging window as soon as possible self.logView = LogView(self.tree.get_widget("logView")) @@ -683,6 +584,12 @@ class MainWindow (Window): filesScroll = self.tree.get_widget("filesScroll") filesScroll.add(InstalledOnlyView(show_files)) + + depScroll = self.tree.get_widget("dependencyScroll") + self.depList = LazyStoreView(self.fill_dep_list) + self.build_dep_list() + depScroll.add(self.depList) + # table self.packageTable = PackageTable(self) @@ -886,7 +793,7 @@ class MainWindow (Window): if name: for cat, pkg, is_inst in self.db.get_cat(name, self.sortPkgListByName): if is_inst: - icon = self.instPixbuf + icon = self.icons["installed"] elif not self.showAll: continue # ignore not installed packages else: @@ -949,7 +856,7 @@ class MainWindow (Window): # append versions for vers, inst, slot in ((x.get_version(), x.is_installed(), get_slot(x)) for x in packages): if inst: - icon = self.instPixbuf + icon = self.icons["installed"] else: icon = None @@ -974,6 +881,94 @@ class MainWindow (Window): self.versionList.get_selection().select_path(pos) self.versionList.scroll_to_cell(pos) + def build_dep_list (self): + + 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 fill_dep_list(self, pkg): + + store = gtk.TreeStore(gtk.gdk.Pixbuf, str) + + 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]) + + def cmp_flag (x, y): + # get strings - as tuples are passed + x = x[0] + y = y[0] + + # remove "!" + ret = 0 + if x[0] == "!": + ret = 1 + x = x[1:] + if y[0] == "!": + ret = ret - 1 # if it is already 1, it is 0 now :) + y = y[1:] + + # cmp -- if two flags are equal, the negated one is greater + return cmp(x,y) or ret + + def get_icon (dep): + if dep.satisfied: + return self.icons["installed"] + elif dep.dep[0] == "!": + return self.icons["block"] + else: + return None + + def add (tree, it): + # useflags + flags = sorted(tree.flags.iteritems(), cmp = cmp_flag) + for use, usetree in flags: + 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 + for ortree in tree.ors: + orit = store.append(it, [self.icons["or"], _("One of the following")]) + add(ortree, orit) + + # Sub (all of) + for subtree in tree.subs: + allit = store.append(it, [None, _("All of the following")]) + add(subtree, allit) + + # normal + ndeps = sorted(tree.deps, key = sort_key) + for dep in ndeps: + store.append(it, [get_icon(dep), dep.dep]) + + try: + deptree = pkg.get_dependencies() + except AssertionError: + w = _("Can't display dependencies: This package has an unsupported dependency string.") + error(w) + store.append(None, [None, w]) + else: + add(deptree, None) + + return store + def refresh_stores (self): """ Refreshes the category and package stores. -- cgit v1.2.3