[thorstenp] improve advanced configuration editor speed. see #4457

This commit is contained in:
Yann Leboulanger 2008-11-05 20:26:58 +00:00
parent 2521ea6080
commit b632a8d2e1
2 changed files with 83 additions and 59 deletions

View File

@ -25,6 +25,7 @@
import gtk
import gtkgui_helpers
import gobject
from common import gajim
@ -41,6 +42,42 @@ C_TYPE
GTKGUI_GLADE = 'manage_accounts_window.glade'
def rate_limit(rate):
''' call func at most *rate* times per second '''
def decorator(func):
timeout = [None]
def f(*args, **kwargs):
if timeout[0] is not None:
gobject.source_remove(timeout[0])
timeout[0] = None
def timeout_func():
func(*args, **kwargs)
timeout[0] = None
timeout[0] = gobject.timeout_add(int(1000.0 / rate), timeout_func)
return f
return decorator
def tree_model_iter_children(model, treeiter):
it = model.iter_children(treeiter)
while it:
yield it
it = model.iter_next(it)
def tree_model_pre_order(model, treeiter):
yield treeiter
for childiter in tree_model_iter_children(model, treeiter):
for it in tree_model_pre_order(model, childiter):
yield it
try:
any(()) # builtin since python 2.5
except Exception:
def any(iterable):
for element in iterable:
if element:
return True
return False
class AdvancedConfigurationWindow(object):
def __init__(self):
self.xml = gtkgui_helpers.get_glade('advanced_configuration_window.glade')
@ -65,7 +102,9 @@ class AdvancedConfigurationWindow(object):
'color': _('Color')}
treeview = self.xml.get_widget('advanced_treeview')
self.treeview = treeview
self.model = gtk.TreeStore(str, str, str)
self.fill_model()
self.model.set_sort_column_id(0, gtk.SORT_ASCENDING)
self.modelfilter = self.model.filter_new()
self.modelfilter.set_visible_func(self.visible_func)
@ -88,9 +127,6 @@ class AdvancedConfigurationWindow(object):
treeview.insert_column_with_attributes(-1, _('Type'),
renderer_text, text = 2)
# add data to model
gajim.config.foreach(self.fill, self.model)
treeview.set_model(self.modelfilter)
# connect signal for selection change
@ -215,65 +251,34 @@ class AdvancedConfigurationWindow(object):
def on_advanced_close_button_clicked(self, widget):
self.window.destroy()
def find_iter(self, model, parent_iter, name):
if not parent_iter:
iter = model.get_iter_root()
else:
iter = model.iter_children(parent_iter)
while iter:
if model[iter][C_PREFNAME].decode('utf-8') == name:
break
iter = model.iter_next(iter)
return iter
def fill_model(self, node=None, parent=None):
for item, option in gajim.config.get_children(node):
name = item[-1]
if option is None: # Node
newparent = self.model.append(parent, [name, '', ''])
self.fill_model(item, newparent)
else: # Leaf
type_ = self.types[option[OPT_TYPE][0]]
if name == 'password':
value = _('Hidden')
else:
value = self.right_true_dict.get(option[OPT_VAL],
option[OPT_VAL])
self.model.append(parent, [name, value, type_])
def fill(self, model, name, parents, val):
iter = None
if parents:
for p in parents:
iter2 = self.find_iter(model, iter, p)
if iter2:
iter = iter2
if not val:
model.append(iter, [name, '', ''])
return
type = ''
if val[OPT_TYPE]:
type = val[OPT_TYPE][0]
type = self.types[type] # i18n
value = val[OPT_VAL]
if name == 'password':
#we talk about password
value = _('Hidden') # override passwords with this string
if value in self.right_true_dict:
value = self.right_true_dict[value]
model.append(iter, [name, value, type])
def visible_func(self, model, iter_):
str = self.entry.get_text().decode('utf-8')
if str in (None, ''):
return True # show all
name = model[iter_][C_PREFNAME].decode('utf-8')
# If a child of the iter matches, we return True
if model.iter_has_child(iter_):
iterC = model.iter_children(iter_)
while iterC:
nameC = model[iterC][C_PREFNAME].decode('utf-8')
if model.iter_has_child(iterC):
iterCC = model.iter_children(iterC)
while iterCC:
nameCC = model[iterCC][C_PREFNAME].decode('utf-8')
if nameCC.find(str) != -1:
return True
iterCC = model.iter_next(iterCC)
elif nameC.find(str) != -1:
return True
iterC = model.iter_next(iterC)
elif name.find(str) != -1:
return True
return False
def visible_func(self, model, treeiter):
search_string = self.entry.get_text()
return any(search_string in model[it][C_PREFNAME] for it in
tree_model_pre_order(model, treeiter) if model[it][C_VALUE] != '')
@rate_limit(3)
def on_advanced_entry_changed(self, widget):
self.modelfilter.refilter()
if not widget.get_text():
# Maybe the expanded rows should be remembered here ...
self.treeview.collapse_all()
else:
# ... and be restored correctly here
self.treeview.expand_all()
# vim: se ts=3:

View File

@ -477,6 +477,25 @@ class Config:
for opt3 in dict[opt2]:
cb(data, opt3, [opt, opt2], dict[opt2][opt3])
def get_children(self, node=None):
''' Tree-like interface '''
if node is None:
for child, option in self.__options.iteritems():
yield (child, ), option
for grandparent in self.__options_per_key:
yield (grandparent, ), None
elif len(node) == 1:
grandparent, = node
for parent in self.__options_per_key[grandparent][1]:
yield (grandparent, parent), None
elif len(node) == 2:
grandparent, parent = node
children = self.__options_per_key[grandparent][1][parent]
for child, option in children.iteritems():
yield (grandparent, parent, child), option
else:
raise ValueError('Invalid node')
def is_valid_int(self, val):
try:
ival = int(val)