Merge lp:~openerp-dev/openobject-client/trunk-m2o_with_selection-rga into lp:openobject-client

Proposed by Ravi Gadhia (OpenERP)
Status: Rejected
Rejected by: Naresh(OpenERP)
Proposed branch: lp:~openerp-dev/openobject-client/trunk-m2o_with_selection-rga
Merge into: lp:openobject-client
Diff against target: 579 lines (+169/-124)
9 files modified
bin/widget/model/field.py (+39/-9)
bin/widget/model/group.py (+4/-2)
bin/widget/model/record.py (+4/-0)
bin/widget/screen/screen.py (+0/-8)
bin/widget/view/form_gtk/selection.py (+46/-73)
bin/widget/view/list.py (+1/-1)
bin/widget/view/tree_gtk/editabletree.py (+7/-2)
bin/widget/view/tree_gtk/parser.py (+51/-24)
bin/widget_search/selection.py (+17/-5)
To merge this branch: bzr merge lp:~openerp-dev/openobject-client/trunk-m2o_with_selection-rga
Reviewer Review Type Date Requested Status
Naresh(OpenERP) Pending
Review via email: mp+58245@code.launchpad.net

This proposal supersedes a proposal from 2011-03-15.

Description of the change

Hello,

Improve selection field.

Now M2O field with widget="selection" no need to pre-load selection value (at time of fields_view_get) it's get value on popup by name_search and we can apply domain as like M2O field

related server branch:
https://code.launchpad.net/~openerp-dev/openobject-server/trunk-M2O_with_selection-rga

To post a comment you must log in.
Revision history for this message
Naresh(OpenERP) (nch-openerp) wrote : Posted in a previous version of this proposal

Hello,

For the client side stuff, there are few bugs I found.

1: The feature of search view "search_default_XXXX" in the context is not working causing a regression here with the above change.

2: setting value of the field which has widget="selection" thru an onchange does not work. Again a regression.

3:If a O2M has a subfield which has widget="selection" attribute behaves very odd

4:Once I have selected the value from the list that the name_search returns then on my next click the domain should take the text that is already selected in the field. currently it takes a ""(blank) value resulting in all records.

Thanks

review: Needs Resubmitting
Revision history for this message
Naresh(OpenERP) (nch-openerp) wrote :

will have to implement it with new spec like web(proto)

Unmerged revisions

1842. By Ravi Gadhia (OpenERP)

Merge with trunk client

1841. By Ravi Gadhia (OpenERP)

[IMP] search text should not clear even it's in selection list(model)

1840. By Ravi Gadhia (OpenERP)

[IMP] If selection field has not key:val then get it by rpc call

1839. By Ravi Gadhia (OpenERP)

[FIX] when widget=selection on one2many field's form view (where each time new modelfield created whid dialog box popup)

1838. By Ravi Gadhia (OpenERP)

[Fix] Search view: set default value on (M2O) widget=selection field

1837. By Ravi Gadhia (OpenERP)

Remove un-used variable

1836. By Ravi Gadhia (OpenERP)

[IMP] Editable list view: add context, domain on selection field

1835. By Ravi Gadhia (OpenERP)

[IMP] Editable list view: M2O field with selection make rpc call at the time of popup (no preloded selection data)

1834. By Ravi Gadhia (OpenERP)

[IMP]Form view: add context, domain on selection field + usability imrovement

1833. By Ravi Gadhia (OpenERP)

[IMP] Form view: m20 with selection widget make rpc call when combobox popup

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'bin/widget/model/field.py'
--- bin/widget/model/field.py 2011-04-13 13:24:05 +0000
+++ bin/widget/model/field.py 2011-04-19 08:45:00 +0000
@@ -45,12 +45,31 @@
45 klass = TYPES.get(type, CharField)45 klass = TYPES.get(type, CharField)
46 return klass46 return klass
4747
48class M2O_SelectionField(dict):
49 def __init__(self ,*args, **kwargs):
50 self.swap = {}
51
52 def __setitem__(self, key, value):
53 self.swap[value] = key
54 super(M2O_SelectionField, self).__setitem__(key, value)
55
56 def update(self, *args, **kwargs):
57 for key, val in args[0].items():
58 self.swap[val] = key
59 super(M2O_SelectionField, self).update(args[0])
60
61 def get_value(self, key):
62 return self.get(key, '')
63
64 def get_key(self,value):
65 return self.swap.get(value, False)
4866
49class CharField(object):67class CharField(object):
50 def __init__(self, parent, attrs):68 def __init__(self, parent, attrs):
51 self.parent = parent69 self.parent = parent
52 self.attrs = attrs70 self.attrs = attrs
53 self.name = attrs['name']71 self.name = attrs['name']
72 self.selection = M2O_SelectionField()
54 self.internal = False73 self.internal = False
55 self.default_attrs = {}74 self.default_attrs = {}
5675
@@ -104,12 +123,12 @@
104 return True123 return True
105124
106 def get(self, model, check_load=True, readonly=True, modified=False):125 def get(self, model, check_load=True, readonly=True, modified=False):
107 return model.value.get(self.name, False) or False126 return model.value.get(self.name, False)
108127
109 def set_client(self, model, value, test_state=True, force_change=False):128 def set_client(self, model, value, test_state=True, force_change=False):
110 internal = model.value.get(self.name, False)129 internal = model.value.get(self.name, False)
111 self.set(model, value, test_state)130 self.set(model, value, test_state)
112 if (internal or False) != (model.value.get(self.name,False) or False):131 if (internal or False) != (model.value.get(self.name, False) or False):
113 model.modified = True132 model.modified = True
114 model.modified_fields.setdefault(self.name)133 model.modified_fields.setdefault(self.name)
115 self.sig_changed(model)134 self.sig_changed(model)
@@ -136,7 +155,7 @@
136 try:155 try:
137 attrs_changes = eval(self.attrs.get('attrs',"{}"))156 attrs_changes = eval(self.attrs.get('attrs',"{}"))
138 except:157 except:
139 attrs_changes = eval(self.attrs.get('attrs',"{}"),model.value)158 attrs_changes = eval(self.attrs.get('attrs',"{}"), model.value)
140 for k,v in attrs_changes.items():159 for k,v in attrs_changes.items():
141 for i in range(0,len(v)):160 for i in range(0,len(v)):
142 if v[i][2]:161 if v[i][2]:
@@ -242,14 +261,24 @@
242261
243262
244class SelectionField(CharField):263class SelectionField(CharField):
264
265 def get(self, model, check_load=True, readonly=True, modified=False):
266 return model.value.get(self.name, False)
267
245 def set(self, model, value, test_state=True, modified=False):268 def set(self, model, value, test_state=True, modified=False):
269 self.selection.update(dict(self.attrs.get('selection',[])))
270
271 if isinstance(value,(list,tuple)) and len(value):
272 self.selection[value[0]] = value[1]
273
274 if value and isinstance(value, (int, long)) and self.attrs.get('relation', False):
275 rpc2 = RPCProxy(self.attrs['relation'])
276 result = rpc2.name_get([value], rpc.session.context)
277 self.selection.update(dict(result))
278
246 value = isinstance(value,(list,tuple)) and len(value) and value[0] or value279 value = isinstance(value,(list,tuple)) and len(value) and value[0] or value
247280
248 if not self.get_state_attrs(model).get('required', False) and value is None:281 super(SelectionField, self).set(model, value, test_state, modified)
249 super(SelectionField, self).set(model, value, test_state, modified)
250
251 if value in [sel[0] for sel in self.attrs['selection']]:
252 super(SelectionField, self).set(model, value, test_state, modified)
253282
254class FloatField(CharField):283class FloatField(CharField):
255 def validate(self, model):284 def validate(self, model):
@@ -303,6 +332,7 @@
303 def get_client(self, model):332 def get_client(self, model):
304 #model._check_load()333 #model._check_load()
305 if model.value[self.name]:334 if model.value[self.name]:
335 self.selection.update(dict([model.value[self.name]]))
306 return model.value[self.name][1]336 return model.value[self.name][1]
307 return False337 return False
308338
309339
=== modified file 'bin/widget/model/group.py'
--- bin/widget/model/group.py 2011-04-13 05:28:58 +0000
+++ bin/widget/model/group.py 2011-04-19 08:45:00 +0000
@@ -343,7 +343,10 @@
343 for f in fields.keys():343 for f in fields.keys():
344 add_field = True344 add_field = True
345 if f in models.fields:345 if f in models.fields:
346 if fields[f].get('widget','') == models.fields[f].get('widget',''):346 if fields[f].get('widget','') == models.fields[f].get('widget','') :
347 if fields[f].get('widget','') == 'selection' and models.mfields[f].selection:
348 selection = models.mfields[f].selection
349 fields[f]['selection'] = zip(selection.keys(),selection.values())
347 models.fields[f].update(fields[f])350 models.fields[f].update(fields[f])
348 add_field = False351 add_field = False
349 if f in models.mfields and fields[f].get('type','') == 'one2many':352 if f in models.mfields and fields[f].get('type','') == 'one2many':
@@ -352,7 +355,6 @@
352 models.fields[f] = fields[f]355 models.fields[f] = fields[f]
353 models.fields[f]['name'] = f356 models.fields[f]['name'] = f
354 to_add.append(f)357 to_add.append(f)
355
356 self.mfields_load(to_add, models)358 self.mfields_load(to_add, models)
357 for fname in to_add:359 for fname in to_add:
358 for m in models.models:360 for m in models.models:
359361
=== modified file 'bin/widget/model/record.py'
--- bin/widget/model/record.py 2011-04-13 05:07:59 +0000
+++ bin/widget/model/record.py 2011-04-19 08:45:00 +0000
@@ -33,6 +33,7 @@
33from gtk import glade33from gtk import glade
34import tools34import tools
35from field import O2MField35from field import O2MField
36from field import SelectionField
3637
37class EvalEnvironment(object):38class EvalEnvironment(object):
38 def __init__(self, parent):39 def __init__(self, parent):
@@ -232,6 +233,9 @@
232 if self.mgroup.mfields[fieldname].attrs.get('on_change',False):233 if self.mgroup.mfields[fieldname].attrs.get('on_change',False):
233 fields_with_on_change[fieldname] = value234 fields_with_on_change[fieldname] = value
234 else:235 else:
236 if self.mgroup.mfields[fieldname].attrs.get('widget') == 'selection' and value:
237 relation = self.mgroup.mfields[fieldname].attrs['relation']
238 value = rpc.session.rpc_exec_auth('/object', 'execute', relation, 'name_search', '', [('id','=',value)], 'ilike')[0]
235 self.mgroup.mfields[fieldname].set_default(self, value)239 self.mgroup.mfields[fieldname].set_default(self, value)
236 for field, value in fields_with_on_change.items():240 for field, value in fields_with_on_change.items():
237 self.mgroup.mfields[field].set_default(self, value)241 self.mgroup.mfields[field].set_default(self, value)
238242
=== modified file 'bin/widget/screen/screen.py'
--- bin/widget/screen/screen.py 2011-04-13 09:12:58 +0000
+++ bin/widget/screen/screen.py 2011-04-19 08:45:00 +0000
@@ -592,13 +592,6 @@
592 if attrs['widget']=='one2many_list':592 if attrs['widget']=='one2many_list':
593 attrs['widget']='one2many'593 attrs['widget']='one2many'
594 attrs['type'] = attrs['widget']594 attrs['type'] = attrs['widget']
595 if attrs.get('selection',[]):
596 attrs['selection'] = eval(attrs['selection'])
597 for att_key, att_val in attrs['selection'].items():
598 for sel in fields[str(attrs['name'])]['selection']:
599 if att_key == sel[0]:
600 sel[1] = att_val
601 attrs['selection'] = fields[str(attrs['name'])]['selection']
602 fields[unicode(attrs['name'])].update(attrs)595 fields[unicode(attrs['name'])].update(attrs)
603 for node2 in node:596 for node2 in node:
604 _parse_fields(node2, fields)597 _parse_fields(node2, fields)
@@ -617,7 +610,6 @@
617 self.models.screen = self610 self.models.screen = self
618 self.models.add_fields(fields, self.models, context=context)611 self.models.add_fields(fields, self.models, context=context)
619 self.fields = self.models.fields612 self.fields = self.models.fields
620
621 parser = widget_parse(parent=self.parent, window=self.window)613 parser = widget_parse(parent=self.parent, window=self.window)
622 view = parser.parse(self, root_node, self.fields, toolbar=toolbar, submenu=submenu, help=help)614 view = parser.parse(self, root_node, self.fields, toolbar=toolbar, submenu=submenu, help=help)
623 if view:615 if view:
624616
=== modified file 'bin/widget/view/form_gtk/selection.py'
--- bin/widget/view/form_gtk/selection.py 2010-07-16 05:41:32 +0000
+++ bin/widget/view/form_gtk/selection.py 2011-04-19 08:45:00 +0000
@@ -23,7 +23,7 @@
23import interface23import interface
24import gtk24import gtk
25import gobject25import gobject
2626import rpc
27import gettext27import gettext
2828
29class selection(interface.widget_interface):29class selection(interface.widget_interface):
@@ -31,109 +31,83 @@
31 interface.widget_interface.__init__(self, window, parent, model, attrs)31 interface.widget_interface.__init__(self, window, parent, model, attrs)
3232
33 self.widget = gtk.HBox(spacing=3)33 self.widget = gtk.HBox(spacing=3)
34 self.entry = gtk.ComboBoxEntry()34 self.name = attrs['name']
35 self.attrs = attrs
36 self.entry = gtk.combo_box_entry_new_text()
37 self.entry.connect('notify::popup-shown', self.popup_show)
35 self.child = self.entry.get_child()38 self.child = self.entry.get_child()
39 self.relation_model = self.attrs.get('relation', '')
36 self.child.set_property('activates_default', True)40 self.child.set_property('activates_default', True)
37 self.child.connect('changed', self.sig_changed)41 self.child.connect('changed', self.sig_changed)
38 self.child.connect('populate-popup', self._menu_open)42 self.child.connect('populate-popup', self._menu_open)
39 self.child.connect('key_press_event', self.sig_key_press)
40 self.child.connect('activate', self.sig_activate)
41 self.child.connect_after('focus-out-event', self.sig_activate)43 self.child.connect_after('focus-out-event', self.sig_activate)
42 self.entry.set_size_request(int(attrs.get('size', -1)), -1)
43 self.widget.pack_start(self.entry, expand=True, fill=True)44 self.widget.pack_start(self.entry, expand=True, fill=True)
4445
45 # the dropdown button is not focusable by a tab46 # the dropdown button is not focusable by a tab
46 self.widget.set_focus_chain([self.child])47 self.widget.set_focus_chain([self.child])
47 self.ok = True48 self.set_popdown(attrs.get('selection',[]))
48 self._selection={}49 self._selection={}
4950 self.entry_text = ""
50 self.set_popdown(attrs.get('selection', []))51
52
53 def popup_show(self, combobox, popup_show):
54 text = self.child.get_text()
55# if self._view.modelfield.selection.get_key(text):
56# text = ""
57 if combobox.get_property('popup-shown') and self.attrs.get('widget','') == 'selection':
58 domain = self._view.modelfield.domain_get(self._view.model)
59 context = self._view.modelfield.context_get(self._view.model)
60 selection = rpc.session.rpc_exec_auth('/object', 'execute', self.relation_model, 'name_search', text , domain , 'ilike', context , False)
61 self.set_popdown(selection)
5162
52 def set_popdown(self, selection):63 def set_popdown(self, selection):
53 self.model = gtk.ListStore(gobject.TYPE_STRING)64 self.model = self.entry.get_model()
65 self.model.clear()
54 self._selection={}66 self._selection={}
55 lst = []67 lst = []
56 for (value, name) in selection:68 if not selection:
57 name = str(name)69 selection = [(False, '')]
70 for (i,j) in selection:
71 name = str(j)
58 lst.append(name)72 lst.append(name)
59 self._selection[name] = value73 self._selection[i]=name
60 i = self.model.append()74 self.entry.append_text(name)
61 self.model.set(i, 0, name)
62 self.entry.set_model(self.model)
63 self.entry.set_text_column(0)
64 return lst
6575
66 def _readonly_set(self, value):76 def _readonly_set(self, value):
67 interface.widget_interface._readonly_set(self, value)77 interface.widget_interface._readonly_set(self, value)
68 self.entry.set_sensitive(not value)78 self.entry.set_sensitive(not value)
6979
70 def value_get(self):
71 res = self.child.get_text()
72 return self._selection.get(res, False)
73
74 def sig_key_press(self, widget, event):
75 # allow showing available entries by hitting "ctrl+space"
76 completion=gtk.EntryCompletion()
77 if hasattr(completion, 'set_inline_selection'):
78 completion.set_inline_selection(True)
79 if (event.type == gtk.gdk.KEY_PRESS) \
80 and ((event.state & gtk.gdk.CONTROL_MASK) != 0) \
81 and (event.keyval == gtk.keysyms.space):
82 self.entry.popup()
83 elif not (event.keyval == gtk.keysyms.Up or event.keyval == gtk.keysyms.Down):
84 completion.set_match_func(self.match_func,widget)
85 completion.set_model(self.model)
86 widget.set_completion(completion)
87 completion.set_text_column(0)
88
89 def match_func(self, completion, key, iter, widget):
90 model = completion.get_model()
91 return model[iter][0].lower().find(widget.get_text().lower()) >= 0 and True or False
92
93 def sig_activate(self, *args):80 def sig_activate(self, *args):
94 text = self.child.get_text()81 text = self.child.get_text()
95 value = False82 value = self._view.modelfield.selection.get_key(text)
96 if text:83 if not value:
97 for txt, val in self._selection.items():84 self.entry_text = text
98 if not val:
99 continue
100 if txt[:len(text)].lower() == text.lower():
101 value = val
102 if len(txt) == len(text):
103 break
104 self._view.modelfield.set_client(self._view.model, value, force_change=True)85 self._view.modelfield.set_client(self._view.model, value, force_change=True)
105 self.display(self._view.model, self._view.modelfield)86 self.display(self._view.model, self._view.modelfield)
10687
107
108 def set_value(self, model, model_field):88 def set_value(self, model, model_field):
109 model_field.set_client(model, self.value_get())89 model_field.selection.update(self._selection)
11090 text = self.child.get_text()
111 def _menu_sig_default_set(self):91 value = False
112 self.set_value(self._view.model, self._view.modelfield)92 if text:
113 super(selection, self)._menu_sig_default_set()93 model_field.selection.get_key(text)
94 value = model_field.selection.get_key(text)
95 model_field.set_client(model, value)
11496
115 def display(self, model, model_field):97 def display(self, model, model_field):
116 self.ok = False
117 if not model_field:98 if not model_field:
118 self.child.set_text('')99 self.child.set_text('')
119 self.ok = True100 return
120 return False101 model_field.selection.update(dict(self.attrs.get('selection',[])))
121 super(selection, self).display(model, model_field)102 super(selection, self).display(model, model_field)
122 value = model_field.get(model)103 key = model_field.get(model, False)
123 if not value:104# model_field.selection.update(self._selection)
124 self.child.set_text('')105 text = model_field.selection.get_value(key)
125 else:106 self.child.set_text(self.entry_text or text)
126 found = False107 self.entry_text = ""
127 for long_text, sel_value in self._selection.items():
128 if sel_value == value:
129 self.child.set_text(long_text)
130 found = True
131 break
132 self.ok = True
133108
134 def sig_changed(self, *args):109 def sig_changed(self, combox):
135 if self.ok:110 self._focus_out()
136 self._focus_out()
137111
138 def _color_widget(self):112 def _color_widget(self):
139 return self.child113 return self.child
@@ -141,4 +115,3 @@
141 def grab_focus(self):115 def grab_focus(self):
142 return self.entry.grab_focus()116 return self.entry.grab_focus()
143# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:117# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
144
145118
=== modified file 'bin/widget/view/list.py'
--- bin/widget/view/list.py 2011-04-12 08:48:06 +0000
+++ bin/widget/view/list.py 2011-04-19 08:45:00 +0000
@@ -860,7 +860,7 @@
860 if col in self.widget_tree.handlers:860 if col in self.widget_tree.handlers:
861 if self.widget_tree.handlers[col]:861 if self.widget_tree.handlers[col]:
862 renderer.disconnect(self.widget_tree.handlers[col])862 renderer.disconnect(self.widget_tree.handlers[col])
863 self.widget_tree.handlers[col] = renderer.connect_after('editing-started', send_keys, self.widget_tree)863 self.widget_tree.handlers[col] = renderer.connect_after('editing-started', send_keys, self.widget_tree, col.name)
864864
865865
866 def set_invisible_attr(self):866 def set_invisible_attr(self):
867867
=== modified file 'bin/widget/view/tree_gtk/editabletree.py'
--- bin/widget/view/tree_gtk/editabletree.py 2010-12-23 09:52:21 +0000
+++ bin/widget/view/tree_gtk/editabletree.py 2011-04-19 08:45:00 +0000
@@ -149,7 +149,12 @@
149 def get_cursor(self):149 def get_cursor(self):
150 res = super(EditableTreeView, self).get_cursor()150 res = super(EditableTreeView, self).get_cursor()
151 return res151 return res
152152
153 def get_current_model(self):
154 path, column = self.get_cursor()
155 store = self.get_model()
156 return store.get_value(store.get_iter(path), 0)
157
153 def set_value(self):158 def set_value(self):
154 path, column = self.get_cursor()159 path, column = self.get_cursor()
155 store = self.get_model()160 store = self.get_model()
@@ -175,7 +180,7 @@
175 def on_keypressed(self, entry, event, cell_value):180 def on_keypressed(self, entry, event, cell_value):
176 path, column = self.get_cursor()181 path, column = self.get_cursor()
177 store = self.get_model()182 store = self.get_model()
178 model = store.get_value(store.get_iter(path), 0)183 model = self.get_current_model()
179 if event.keyval in self.leaving_events:184 if event.keyval in self.leaving_events:
180 shift_pressed = bool(gtk.gdk.SHIFT_MASK & event.state)185 shift_pressed = bool(gtk.gdk.SHIFT_MASK & event.state)
181 if isinstance(entry, gtk.Entry):186 if isinstance(entry, gtk.Entry):
182187
=== modified file 'bin/widget/view/tree_gtk/parser.py'
--- bin/widget/view/tree_gtk/parser.py 2011-03-20 11:26:23 +0000
+++ bin/widget/view/tree_gtk/parser.py 2011-04-19 08:45:00 +0000
@@ -33,6 +33,7 @@
33from editabletree import EditableTreeView33from editabletree import EditableTreeView
34from widget.view import interface34from widget.view import interface
35from widget.view.list import group_record35from widget.view.list import group_record
36from widget.model.field import SelectionField, M2OField
36import time37import time
37import date_renderer38import date_renderer
3839
@@ -47,13 +48,16 @@
47import gobject48import gobject
48import pango49import pango
4950
50def send_keys(renderer, entry, position, treeview):51def send_keys(renderer, entry, position, treeview, col_name):
51 if entry:52 if entry:
52 entry.connect('key_press_event', treeview.on_keypressed, renderer.get_property('text'))53 entry.connect('key_press_event', treeview.on_keypressed, renderer.get_property('text'))
53 entry.set_data('renderer', renderer)54 entry.set_data('renderer', renderer)
54 entry.editing_done_id = entry.connect('editing_done', treeview.on_editing_done)55 entry.editing_done_id = entry.connect('editing_done', treeview.on_editing_done)
55 if isinstance(entry, gtk.ComboBoxEntry):56 if isinstance(entry, gtk.ComboBoxEntry):
56 entry.connect('changed', treeview.on_editing_done)57 entry.connect('changed', treeview.on_editing_done)
58 if isinstance(entry, gtk.ComboBoxEntry):
59 popup = treeview.cells[col_name].popup
60 entry.connect('notify::popup-shown', popup, treeview)
5761
58def sort_model(column, screen):62def sort_model(column, screen):
59 unsaved_model = [x for x in screen.models if x.id == None or x.modified]63 unsaved_model = [x for x in screen.models if x.id == None or x.modified]
@@ -107,10 +111,8 @@
107 treeview.sequence = False111 treeview.sequence = False
108 treeview.connect("motion-notify-event", treeview.set_tooltip)112 treeview.connect("motion-notify-event", treeview.set_tooltip)
109 treeview.connect('key-press-event', treeview.on_tree_key_press)113 treeview.connect('key-press-event', treeview.on_tree_key_press)
110
111 for node in root_node:114 for node in root_node:
112 node_attrs = tools.node_attributes(node)115 node_attrs = tools.node_attributes(node)
113
114 if node.tag == 'button':116 if node.tag == 'button':
115 cell = Cell('button')(node_attrs['string'], treeview, node_attrs)117 cell = Cell('button')(node_attrs['string'], treeview, node_attrs)
116 cell.name = node_attrs['name']118 cell.name = node_attrs['name']
@@ -158,16 +160,17 @@
158 self.window)160 self.window)
159 treeview.cells[fname] = cell161 treeview.cells[fname] = cell
160 renderer = cell.renderer162 renderer = cell.renderer
161163 col = gtk.TreeViewColumn(None, renderer)
164 col.name = fname
162 write_enable = editable and not node_attrs.get('readonly', False)165 write_enable = editable and not node_attrs.get('readonly', False)
163 if isinstance(renderer, gtk.CellRendererToggle):166 if isinstance(renderer, gtk.CellRendererToggle):
164 renderer.set_property('activatable', write_enable)167 renderer.set_property('activatable', write_enable)
165 elif isinstance(renderer, (gtk.CellRendererText, gtk.CellRendererCombo, date_renderer.DecoratorRenderer)):168 elif isinstance(renderer, (gtk.CellRendererText, gtk.CellRendererCombo, date_renderer.DecoratorRenderer)):
166 renderer.set_property('editable', write_enable)169 renderer.set_property('editable', write_enable)
167 if write_enable:170 if write_enable:
168 handler_id = renderer.connect_after('editing-started', send_keys, treeview)171 handler_id = renderer.connect_after('editing-started', send_keys, treeview, col.name)
169172
170 col = gtk.TreeViewColumn(None, renderer)173
171 treeview.handlers[col] = handler_id174 treeview.handlers[col] = handler_id
172 col_label = gtk.Label('')175 col_label = gtk.Label('')
173 if fields[fname].get('required', False):176 if fields[fname].get('required', False):
@@ -176,7 +179,7 @@
176 col_label.set_text(fields[fname]['string'])179 col_label.set_text(fields[fname]['string'])
177 col_label.show()180 col_label.show()
178 col.set_widget(col_label)181 col.set_widget(col_label)
179 col.name = fname182
180 col._type = fields[fname]['type']183 col._type = fields[fname]['type']
181 col.set_cell_data_func(renderer, cell.setter)184 col.set_cell_data_func(renderer, cell.setter)
182 col.set_clickable(True)185 col.set_clickable(True)
@@ -549,6 +552,13 @@
549 return rpc.name_get([found[0]], context)[0]552 return rpc.name_get([found[0]], context)[0]
550 else:553 else:
551 return False, None554 return False, None
555
556 def get_textual_value(self, model):
557 if isinstance(model[self.field_name], SelectionField):
558 key = model[self.field_name].get_client(model)
559 return model[self.field_name].selection.get_value(key)
560 return model[self.field_name].get_client(model) or ''
561
552562
553563
554class O2M(Char):564class O2M(Char):
@@ -609,29 +619,46 @@
609 def __init__(self, *args):619 def __init__(self, *args):
610 super(Selection, self).__init__(*args)620 super(Selection, self).__init__(*args)
611 self.renderer = gtk.CellRendererCombo()621 self.renderer = gtk.CellRendererCombo()
612 selection_data = gtk.ListStore(object, str)622 self.selection_data = gtk.ListStore(str, str)
613 for x in self.attrs.get('selection', []):623 selection = self.attrs.get('selection', [])
614 selection_data.append(x)624 for x in selection:
615 self.renderer.set_property('model', selection_data)625 self.selection_data.append(x)
626 if not selection:
627 self.selection_data.append([False, ''])
628 self.renderer.set_property('model', self.selection_data)
616 self.renderer.set_property('text-column', 1)629 self.renderer.set_property('text-column', 1)
630 self.relation = self.attrs.get('relation')
617631
618 def get_textual_value(self, model):632 def get_textual_value(self, model):
619 selection = dict(self.attrs['selection'])633 key = model[self.field_name].get(model)
620 selection_value = selection.get(model[self.field_name].get(model), '')634 selection_value = model[self.field_name].selection.get_value(key)
621 if isinstance(model, group_record):635 if isinstance(model, group_record):
622 return selection_value + model[self.field_name].count636 return selection_value + model[self.field_name].count
623 return selection_value637 return selection_value
638
639 def popup(self, combobox, para, treeview):
640 if combobox.get_property('popup-shown') and self.relation:
641 entry = combobox.get_child()
642 text = entry.get_property('text')
643 rpc = RPCProxy(self.relation)
644 model = treeview.get_current_model()
645 domain = model[self.field_name].domain_get(model)
646 context = model[self.field_name].context_get(model)
647 key = model[self.field_name].selection.get_key(text)
648 if key:
649 text = ''
650 selection = rpc.name_search(text, domain, 'ilike',context, False)
651 if selection:
652 self.selection_data.clear()
653 model = treeview.get_current_model()
654 model[self.field_name].selection.update(dict(selection))
655 for x in selection:
656 self.selection_data.append(x)
624657
625 def value_from_text(self, model, text):658 def value_from_text(self, model, text):
626 selection = self.attrs['selection']659 key = model[self.field_name].get(model)
627 text = tools.ustr(text)660 selection_value = model[self.field_name].selection.get_value(key)
628 res = False661 return model[self.field_name].selection.get_key(text)
629 for val, txt in selection:
630 if txt[:len(text)].lower() == text.lower():
631 if len(txt) == len(text):
632 return val
633 res = val
634 return res
635662
636663
637class ProgressBar(object):664class ProgressBar(object):
638665
=== modified file 'bin/widget_search/selection.py'
--- bin/widget_search/selection.py 2011-04-04 11:19:53 +0000
+++ bin/widget_search/selection.py 2011-04-19 08:45:00 +0000
@@ -28,25 +28,37 @@
28class selection(wid_int.wid_int):28class selection(wid_int.wid_int):
29 def __init__(self, name, parent, attrs={}, model=None, screen=None):29 def __init__(self, name, parent, attrs={}, model=None, screen=None):
30 wid_int.wid_int.__init__(self, name, parent, attrs, screen)30 wid_int.wid_int.__init__(self, name, parent, attrs, screen)
31
32 self.widget = gtk.combo_box_entry_new_text()31 self.widget = gtk.combo_box_entry_new_text()
32 self.widget.connect('notify::popup-shown', self.popup_show)
33 self.context = screen.context
34 self.relation_model = self.attrs.get('relation', '')
33 self.widget.child.set_editable(True)35 self.widget.child.set_editable(True)
34 self.attrs = attrs36 self.attrs = attrs
35 self._selection = {}37 self._selection = {}
36 self.name = name38 self.name = name
37 self.val_id = False39 self.set_popdown(attrs.get('selection',[]))
38 if 'selection' in attrs:
39 self.set_popdown(attrs.get('selection',[]))
40 if self.default_search:40 if self.default_search:
41 if isinstance(self.default_search,list):41 if isinstance(self.default_search,list):
42 self.default_search = self.default_search[0]42 self.default_search = self.default_search[0]
43 if self.attrs['type'] == 'many2one':43 if self.attrs['type'] == 'many2one':
44 self._value_set(int(self.default_search))44 sel = rpc.session.rpc_exec_auth('/object', 'execute', self.relation_model, 'name_search', '' , [('id','=',self.default_search)] , 'ilike', self.context, False)
45 self.set_popdown(sel)
46 self._value_set(int(self.default_search))
45 else:47 else:
46 self._value_set(str(self.default_search))48 self._value_set(str(self.default_search))
47 if self.widget.child.get_text() in self._selection.keys():49 if self.widget.child.get_text() in self._selection.keys():
48 self.widget.set_active(self.indexes[self.widget.child.get_text()]-1)50 self.widget.set_active(self.indexes[self.widget.child.get_text()]-1)
4951
52 def popup_show(self, combobox, popup_show):
53 search_text = self.widget.child.get_text()
54# if self._selection.get(search_text, False):
55# search_text =''
56 if combobox.get_property('popup-shown') and self.attrs['type'] == 'many2one':
57 selection = rpc.session.rpc_exec_auth('/object', 'execute', self.relation_model, 'name_search', search_text , [] , 'ilike', self.context, False)
58 self.set_popdown(selection)
59 if not selection:
60 self.widget.child.set_text('')
61
50 def set_popdown(self, selection):62 def set_popdown(self, selection):
51 self.model = self.widget.get_model()63 self.model = self.widget.get_model()
52 self.model.clear()64 self.model.clear()