From 61fa8239f1fbe7b413dacd6a5d14d806de0ecc52 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Krier?= Date: Mon, 6 Jun 2011 17:56:26 +0200 Subject: [PATCH] Fix selection widget in list view for dynamic Many2One review35013 --- .../window/view_form/view/list_gtk/parser.py | 122 ++++++++++-------- 1 file changed, 70 insertions(+), 52 deletions(-) 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 2e49d94c00..b89af9d84b 100644 --- a/tryton/gui/window/view_form/view/list_gtk/parser.py +++ b/tryton/gui/window/view_form/view/list_gtk/parser.py @@ -1,6 +1,7 @@ #This file is part of Tryton. The COPYRIGHT file at the top level of #this repository contains the full copyright notices and license terms. +import gobject from editabletree import EditableTreeView from tryton.gui.window.view_form.view.interface import ParserInterface from tryton.gui.window.win_search import WinSearch @@ -704,71 +705,88 @@ class Selection(Char): def __init__(self, *args): super(Selection, self).__init__(*args) self.renderer = CellRendererCombo() - selection_data = gtk.ListStore(str, str) + self.renderer.connect('editing-started', self.editing_started) + self._last_domain = None + self._domain_cache = {} selection = self.attrs.get('selection', [])[:] - self.selection = selection[:] - if not self.attrs.get('domain'): - domain = [] - else: - context = rpc.CONTEXT.copy() - context['context'] = context.copy() - context['_user'] = rpc._USER - domain = PYSONDecoder(context).decode(self.attrs['domain']) - if 'relation' in self.attrs: - args = ('model', self.attrs['relation'], 'search_read', - domain, 0, None, None, ['rec_name'], rpc.CONTEXT) + if not isinstance(selection, (list, tuple)): try: - result = rpc.execute(*args) + selection = rpc.execute('model', + self.model_name, selection, rpc.CONTEXT) except Exception, exception: - result = common.process_exception(exception, self.window, *args) - if not result: - result = [] - selection = [(x['id'], x['rec_name']) for x in result] - self.selection = selection[:] - else: - if not isinstance(selection, (list, tuple)): - try: - selection = rpc.execute('model', - self.model_name, selection, rpc.CONTEXT) - except Exception, exception: - common.process_exception(exception, self.window) - selection = [] - self.selection = selection[:] - - for dom in common.filter_domain(domain): - if dom[1] in ('=', '!='): - todel = [] - for i in xrange(len(selection)): - if (dom[1] == '=' \ - and selection[i][0] != dom[2]) \ - or (dom[1] == '!=' \ - and selection[i][0] == dom[2]): - todel.append(i) - for i in todel[::-1]: - del selection[i] - + common.process_exception(exception, self.window) + selection = [] + self.selection = selection[:] if self.attrs.get('sort', True): selection.sort(lambda x, y: cmp(x[1], y[1])) - self._selection = selection - for i in selection: - selection_data.append(i) - self.renderer.set_property('model', selection_data) - self.renderer.set_property('text-column', 1) + self.renderer.set_property('model', self.get_model(selection)) + self.renderer.set_property('text-column', 0) + + def get_model(self, selection): + model = gtk.ListStore(gobject.TYPE_STRING) + self._selection = {} + lst = [] + for (value, name) in selection: + name = str(name) + lst.append(name) + self._selection[name] = value + i = model.append() + model.set(i, 0, name) + return model def get_textual_value(self, record): + self.update_selection(record) value = record[self.field_name].get(record) if isinstance(value, (list, tuple)): value = value[0] return dict(self.selection).get(value, '') def value_from_text(self, record, text): - res = False - for val, txt in self._selection: - if txt[:len(text)].lower() == text.lower(): - if len(txt) == len(text): - return val - res = val - return res + return self._selection.get(text, False), text + + def editing_started(self, cell, editable, path): + store = self.treeview.get_model() + record = store.get_value(store.get_iter(path), 0) + self.update_selection(record) + model = self.get_model(self.selection) + editable.set_model(model) + editable.set_text_column(0) + completion = gtk.EntryCompletion() + #Only available in PyGTK 2.6 and above. + if hasattr(completion, 'set_inline_selection'): + completion.set_inline_selection(True) + completion.set_model(model) + editable.get_child().set_completion(completion) + completion.set_text_column(0) + return False + + def update_selection(self, record): + if 'relation' not in self.attrs: + return + field = record[self.field_name] + domain = field.domain_get(record) + if str(domain) in self._domain_cache: + self.selection = self._domain_cache[str(domain)] + self._last_domain = domain + if domain != self._last_domain: + args = ('model', self.attrs['relation'], 'search_read', domain, + 0, None, None, ['rec_name'], rpc.CONTEXT) + try: + result = rpc.execute(*args) + except Exception, exception: + result = common.process_exception(exception, self.window, *args) + + if isinstance(result, list): + selection = [(x['id'], x['rec_name']) for x in result] + selection.append((False, '')) + self._last_domain = domain + self._domain_cache[str(domain)] = selection + else: + selection = [] + self._last_domain = None + else: + selection = self.selection + self.selection = selection[:] class Reference(Char):