From bc8c3f5fa3d299febec60d2dd74b355f56187b9d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Krier?= Date: Fri, 23 May 2014 11:59:26 +0200 Subject: [PATCH] Add cellrenderer cache issue1318 review12291003 --- tryton/gui/window/view_form/view/list.py | 1 + .../view_form/view/list_gtk/editabletree.py | 1 + .../window/view_form/view/list_gtk/parser.py | 61 +++++++++++++++++++ 3 files changed, 63 insertions(+) diff --git a/tryton/gui/window/view_form/view/list.py b/tryton/gui/window/view_form/view/list.py index 0077d430e7..6a8978d7bd 100644 --- a/tryton/gui/window/view_form/view/list.py +++ b/tryton/gui/window/view_form/view/list.py @@ -780,6 +780,7 @@ class ViewList(ParserView): # self.widget.set_model(self.store) could be removed if the store # has not changed -> better ergonomy. To test def display(self): + self.widget_tree.display_counter += 1 current_record = self.screen.current_record if (self.reload or not self.widget_tree.get_model() diff --git a/tryton/gui/window/view_form/view/list_gtk/editabletree.py b/tryton/gui/window/view_form/view/list_gtk/editabletree.py index 2a566f4dac..2f6670172f 100644 --- a/tryton/gui/window/view_form/view/list_gtk/editabletree.py +++ b/tryton/gui/window/view_form/view/list_gtk/editabletree.py @@ -128,6 +128,7 @@ class EditableTreeView(TreeView): path, column = self.get_cursor() model = self.get_model() record = model.get_value(model.get_iter(path), 0) + self.display_counter += 1 # Force a display leaving = False if event.keyval == gtk.keysyms.Right: diff --git a/tryton/gui/window/view_form/view/list_gtk/parser.py b/tryton/gui/window/view_form/view/list_gtk/parser.py index 478cd6232d..33426653cf 100644 --- a/tryton/gui/window/view_form/view/list_gtk/parser.py +++ b/tryton/gui/window/view_form/view/list_gtk/parser.py @@ -85,6 +85,60 @@ def realized(func): return wrapper +class CellCache(list): + + methods = ('set_active', 'set_sensitive', 'set_property') + + def apply(self, cell): + for method, args, kwargs in self: + getattr(cell, method)(*args, **kwargs) + + def decorate(self, cell): + def decorate(func): + @wraps(func) + def wrapper(*args, **kwargs): + self.append((func.__name__, args, kwargs)) + return func(*args, **kwargs) + wrapper.previous = func + return wrapper + + for method in self.methods: + if getattr(cell, method, None): + setattr(cell, method, decorate(getattr(cell, method))) + cell.decorated = True + return cell + + def undecorate(self, cell): + for method in self.methods: + if getattr(cell, method, None): + setattr(cell, method, getattr(cell, method).previous) + del cell.decorated + + @classmethod + def cache(cls, func): + @wraps(func) + def wrapper(self, column, cell, store, iter): + if not hasattr(self, 'display_counters'): + self.display_counters = {} + if not hasattr(self, 'cell_caches'): + self.cell_caches = {} + record = store.get_value(iter, 0) + counter = self.treeview.display_counter + if (self.display_counters.get(record.id) != counter): + if getattr(cell, 'decorated', None): + func(self, column, cell, store, iter) + else: + cache = cls() + cache.decorate(cell) + func(self, column, cell, store, iter) + cache.undecorate(cell) + self.cell_caches[record.id] = cache + self.display_counters[record.id] = counter + else: + self.cell_caches[record.id].apply(cell) + return wrapper + + class ParserTree(ParserInterface): def __init__(self, parent=None, attrs=None, screen=None, @@ -104,6 +158,7 @@ class ParserTree(ParserInterface): else: treeview = TreeView() treeview.cells = {} + treeview.display_counter = 0 treeview.sequence = attrs.get('sequence', False) treeview.colors = attrs.get('colors', '"black"') treeview.keyword_open = attrs.get('keyword_open', False) @@ -316,6 +371,7 @@ class Affix(object): self.treeview = treeview @realized + @CellCache.cache def setter(self, column, cell, store, iter_): record = store.get_value(iter_, 0) field = record[self.field_name] @@ -366,6 +422,7 @@ class Char(object): self.treeview = treeview @realized + @CellCache.cache def setter(self, column, cell, store, iter): record = store.get_value(iter, 0) text = self.get_textual_value(record) @@ -510,6 +567,7 @@ class Boolean(Char): class URL(Char): @realized + @CellCache.cache def setter(self, column, cell, store, iter): super(URL, self).setter(column, cell, store, iter) record = store.get_value(iter, 0) @@ -616,6 +674,7 @@ class Binary(Char): callback() @realized + @CellCache.cache def setter(self, column, cell, store, iter): record = store.get_value(iter, 0) field = record[self.field_name] @@ -1019,6 +1078,7 @@ class ProgressBar(object): self.treeview = treeview @realized + @CellCache.cache def setter(self, column, cell, store, iter): record = store.get_value(iter, 0) field = record[self.field_name] @@ -1054,6 +1114,7 @@ class Button(object): self.renderer.connect('clicked', self.button_clicked) @realized + @CellCache.cache def setter(self, column, cell, store, iter): record = store.get_value(iter, 0) states = record.expr_eval(self.attrs.get('states', {}))