add process for special=cancel button
[openerp-client.git] / bin / widget / view / form_gtk / parser.py
blob41853f0cdf656797748c360eb51bf32fb6146faa
1 ##############################################################################
3 # Copyright (c) 2004-2008 TINY SPRL. (http://tiny.be) All Rights Reserved.
5 # $Id$
7 # WARNING: This program as such is intended to be used by professional
8 # programmers who take the whole responsability of assessing all potential
9 # consequences resulting from its eventual inadequacies and bugs
10 # End users who are looking for a ready-to-use solution with commercial
11 # garantees and support are strongly adviced to contract a Free Software
12 # Service Company
14 # This program is Free Software; you can redistribute it and/or
15 # modify it under the terms of the GNU General Public License
16 # as published by the Free Software Foundation; either version 2
17 # of the License, or (at your option) any later version.
19 # This program is distributed in the hope that it will be useful,
20 # but WITHOUT ANY WARRANTY; without even the implied warranty of
21 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 # GNU General Public License for more details.
24 # You should have received a copy of the GNU General Public License
25 # along with this program; if not, write to the Free Software
26 # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
28 ##############################################################################
30 import tools
31 import interface
33 import widget.view.interface
34 from observator import oregistry, Observable
36 import gtk
38 import common
39 import service
40 import rpc
42 import copy
44 import options
47 class Button(Observable):
48 def __init__(self, attrs={}):
49 super(Button, self).__init__()
50 self.attrs = attrs
51 args = {
52 'label': attrs.get('string', 'unknown')
54 self.widget = gtk.Button(**args)
55 if attrs.get('icon', False):
56 try:
57 stock = attrs['icon']
58 icon = gtk.Image()
59 icon.set_from_stock(stock, gtk.ICON_SIZE_BUTTON)
60 self.widget.set_image(icon)
61 except Exception,e:
62 import logging
63 log = logging.getLogger('common')
64 log.warning(_('Wrong icon for the button !'))
65 # self.widget.set_use_stock(True)
66 # self.widget.set_label(args['label'])
68 self.widget.show()
69 self.widget.connect('clicked', self.button_clicked)
71 def button_clicked(self, widget):
72 model = self.form.screen.current_model
73 self.form.set_value()
74 button_type = self.attrs.get('special', '')
75 if button_type=='cancel':
76 self.form.screen.window.destroy()
77 elif model.validate():
78 id = self.form.screen.save_current()
79 if not self.attrs.get('confirm',False) or \
80 common.sur(self.attrs['confirm']):
81 button_type = self.attrs.get('type', 'workflow')
82 if button_type == 'workflow':
83 print 'Exec Workflow'
84 result = rpc.session.rpc_exec_auth('/object', 'exec_workflow',
85 self.form.screen.name,
86 self.attrs['name'], id)
87 print 'Result', result
88 if type(result)==type({}):
89 datas = {}
90 obj = service.LocalService('action.main')
91 obj._exec_action(result,datas)
92 elif button_type == 'object':
93 if not id:
94 return
95 result = rpc.session.rpc_exec_auth(
96 '/object', 'execute',
97 self.form.screen.name,
98 self.attrs['name'],
99 [id], model.context_get()
101 if type(result)==type({}):
102 datas = {}
103 obj = service.LocalService('action.main')
104 obj._exec_action(result,datas,context=self.form.screen.context)
106 elif button_type == 'action':
107 obj = service.LocalService('action.main')
108 action_id = int(self.attrs['name'])
109 obj.execute(action_id, {'model':self.form.screen.name, 'id': id or False,
110 'ids': id and [id] or [], 'report_type': 'pdf'}, context=self.form.screen.context)
111 else:
112 raise Exception, 'Unallowed button type'
113 self.form.screen.reload()
114 else:
115 self.warn('misc-message', _('Invalid Form, correct red fields !'))
116 self.form.screen.display()
118 def state_set(self, state):
119 if self.attrs.get('states', False):
120 my_states = self.attrs.get('states', '').split(',')
121 if state not in my_states:
122 self.widget.hide()
123 else:
124 self.widget.show()
125 else:
126 self.widget.show()
128 class _container(object):
129 def __init__(self, tooltips):
130 self.cont = []
131 self.col = []
132 self.sg = gtk.SizeGroup(gtk.SIZE_GROUP_HORIZONTAL)
133 self.tooltips = tooltips
134 self.trans_box = []
135 self.trans_box_label = []
137 def new(self, col=4):
138 table = gtk.Table(1, col)
139 table.set_homogeneous(False)
140 table.set_col_spacings(3)
141 table.set_row_spacings(0)
142 table.set_border_width(1)
143 self.cont.append( (table, 0, 0) )
144 self.col.append( col )
146 def get(self):
147 return self.cont[-1][0]
149 def pop(self):
150 (table, x, y) = self.cont.pop()
151 self.col.pop()
152 return table
154 def newline(self):
155 (table, x, y) = self.cont[-1]
156 if x>0:
157 self.cont[-1] = (table, 0, y+1)
158 table.resize(y+1,self.col[-1])
160 def wid_add(self, widget, name=None, expand=False, ypadding=2, rowspan=1,
161 colspan=1, translate=False, fname=None, help=False, fill=False):
162 (table, x, y) = self.cont[-1]
163 if colspan>self.col[-1]:
164 colspan=self.col[-1]
165 a = name and 1 or 0
166 if colspan+x+a>self.col[-1]:
167 self.newline()
168 (table, x, y) = self.cont[-1]
169 yopt = False
170 if expand:
171 yopt = yopt | gtk.EXPAND
172 if fill:
173 yopt = yopt | gtk.FILL
174 if colspan == 1 and a == 1:
175 colspan = 2
176 if name:
177 label = gtk.Label(name)
178 eb = gtk.EventBox()
179 eb.set_events(gtk.gdk.BUTTON_PRESS_MASK)
180 self.trans_box_label.append((eb, name, fname))
181 eb.add(label)
182 if help:
183 self.tooltips.set_tip(eb, help)
184 self.tooltips.enable()
185 eb.show()
186 if '_' in name:
187 label.set_text_with_mnemonic(name)
188 label.set_mnemonic_widget(widget)
189 label.set_alignment(1.0, 0.5)
190 table.attach(eb, x, x+1, y, y+rowspan, yoptions=yopt,
191 xoptions=gtk.FILL, ypadding=ypadding, xpadding=2)
192 hbox = widget
193 hbox.show_all()
194 if translate:
195 hbox = gtk.HBox(spacing=3)
196 hbox.pack_start(widget)
197 img = gtk.Image()
198 img.set_from_stock('terp-translate', gtk.ICON_SIZE_MENU)
199 ebox = gtk.EventBox()
200 ebox.set_events(gtk.gdk.BUTTON_PRESS_MASK)
201 self.trans_box.append((ebox, name, fname, widget))
203 ebox.add(img)
204 hbox.pack_start(ebox, fill=False, expand=False)
205 hbox.show_all()
206 table.attach(hbox, x+a, x+colspan, y, y+rowspan, yoptions=yopt,
207 ypadding=ypadding, xpadding=2)
208 self.cont[-1] = (table, x+colspan, y)
209 wid_list = table.get_children()
210 wid_list.reverse()
211 table.set_focus_chain(wid_list)
213 class parser_form(widget.view.interface.parser_interface):
214 def parse(self, model, root_node, fields, notebook=None, paned=None, tooltips=None):
215 dict_widget = {}
216 button_list = []
217 attrs = tools.node_attributes(root_node)
218 on_write = attrs.get('on_write', '')
219 if not tooltips:
220 self.tooltips = gtk.Tooltips()
221 else:
222 self.tooltips = tooltips
223 container = _container(self.tooltips)
224 container.new(col=int(attrs.get('col', 4)))
225 self.container = container
227 if not self.title:
228 attrs = tools.node_attributes(root_node)
229 self.title = attrs.get('string', 'Unknown')
231 for node in root_node.childNodes:
232 if not node.nodeType==node.ELEMENT_NODE:
233 continue
234 attrs = tools.node_attributes(node)
235 if node.localName=='image':
236 icon = gtk.Image()
237 icon.set_from_stock(attrs['name'], gtk.ICON_SIZE_DIALOG)
238 container.wid_add(icon,colspan=int(attrs.get('colspan',1)),expand=int(attrs.get('expand',0)), ypadding=10, help=attrs.get('help', False), fill=int(attrs.get('fill', 0)))
239 elif node.localName=='separator':
240 vbox = gtk.VBox()
241 if 'string' in attrs:
242 text = attrs.get('string', 'No String Attr.')
243 l = gtk.Label(text)
244 l.set_alignment(0.0, 0.5)
245 eb = gtk.EventBox()
246 eb.set_events(gtk.gdk.BUTTON_PRESS_MASK)
247 eb.add(l)
248 container.trans_box_label.append((eb, text, None))
249 vbox.pack_start(eb)
250 vbox.pack_start(gtk.HSeparator())
251 container.wid_add(vbox,colspan=int(attrs.get('colspan',1)),expand=int(attrs.get('expand',0)), ypadding=10, help=attrs.get('help', False), fill=int(attrs.get('fill', 0)))
252 elif node.localName=='label':
253 text = attrs.get('string', '')
254 if not text:
255 for node in node.childNodes:
256 if node.nodeType == node.TEXT_NODE:
257 text += node.data
258 else:
259 text += node.toxml()
260 label = gtk.Label(text)
261 label.set_use_markup(True)
262 if 'align' in attrs:
263 try:
264 label.set_alignment(float(attrs['align'] or 0.0), 0.5)
265 except:
266 pass
267 if 'angle' not in attrs:
268 label.set_line_wrap(True)
269 label.set_angle(int(attrs.get('angle', 0)))
270 eb = gtk.EventBox()
271 eb.set_events(gtk.gdk.BUTTON_PRESS_MASK)
272 eb.add(label)
273 container.trans_box_label.append((eb, text, None))
274 container.wid_add(eb, colspan=int(attrs.get('colspan', 1)), expand=False, help=attrs.get('help', False), fill=int(attrs.get('fill', 0)))
276 elif node.localName=='newline':
277 container.newline()
279 elif node.localName=='button':
280 button = Button(attrs)
281 button_list.append(button)
282 container.wid_add(button.widget, colspan=int(attrs.get('colspan', 1)), help=attrs.get('help', False))
284 elif node.localName=='notebook':
285 nb = gtk.Notebook()
286 if attrs and 'tabpos' in attrs:
287 pos = {'up':gtk.POS_TOP,
288 'down':gtk.POS_BOTTOM,
289 'left':gtk.POS_LEFT,
290 'right':gtk.POS_RIGHT
291 }[attrs['tabpos']]
292 else:
293 if options.options['client.form_tab'] == 'top':
294 pos = gtk.POS_TOP
295 elif options.options['client.form_tab'] == 'left':
296 pos = gtk.POS_LEFT
297 elif options.options['client.form_tab'] == 'right':
298 pos = gtk.POS_RIGHT
299 elif options.options['client.form_tab'] == 'bottom':
300 pos = gtk.POS_BOTTOM
301 nb.set_tab_pos(pos)
302 nb.set_border_width(3)
303 container.wid_add(nb, colspan=attrs.get('colspan', 3), expand=True, fill=True )
304 _, widgets, buttons, on_write = self.parse(model, node, fields, nb, tooltips=self.tooltips)
305 button_list += buttons
306 dict_widget.update(widgets)
308 elif node.localName=='page':
309 if attrs and 'angle' in attrs:
310 angle = int(attrs['angle'])
311 else:
312 angle = int(options.options['client.form_tab_orientation'])
313 l = gtk.Label(attrs.get('string','No String Attr.'))
314 l.set_angle(angle)
315 widget, widgets, buttons, on_write = self.parse(model, node, fields, notebook, tooltips=self.tooltips)
316 button_list += buttons
317 dict_widget.update(widgets)
318 notebook.append_page(widget, l)
320 elif node.localName=='field':
321 name = str(attrs['name'])
322 del attrs['name']
323 type = attrs.get('widget', fields[name]['type'])
324 fields[name].update(attrs)
325 fields[name]['model']=model
326 if not type in widgets_type:
327 continue
328 if attrs.get('invisible', False):
329 visval = eval(attrs['invisible'], {'context':self.screen.context})
330 if visval:
331 continue
333 fields[name]['name'] = name
334 if 'saves' in attrs:
335 fields[name]['saves'] = attrs['saves']
336 widget_act = widgets_type[type][0](self.window, self.parent, model, fields[name])
337 label = None
338 if not int(attrs.get('nolabel', 0)):
339 # TODO space before ':' depends of lang (ex: english no space)
340 if gtk.widget_get_default_direction() == gtk.TEXT_DIR_RTL:
341 label = ': '+fields[name]['string']
342 else:
343 label = fields[name]['string']+' :'
344 dict_widget[name] = widget_act
345 size = int(attrs.get('colspan', widgets_type[ type ][1]))
346 expand = widgets_type[ type ][2]
347 fill = widgets_type[ type ][3]
348 hlp = fields[name].get('help', attrs.get('help', False))
349 if attrs.get('height', False) or attrs.get('width', False):
350 widget_act.widget.set_size_request(
351 int(attrs.get('width', -1)), int(attrs.get('height', -1)))
352 container.wid_add(widget_act.widget, label, expand, translate=fields[name].get('translate',False), colspan=size, fname=name, help=hlp, fill=fill)
354 elif node.localName=='group':
355 frame = gtk.Frame(attrs.get('string', None))
356 frame.set_border_width(0)
358 container.wid_add(frame, colspan=int(attrs.get('colspan', 1)), expand=int(attrs.get('expand',0)), rowspan=int(attrs.get('rowspan', 1)), ypadding=0, fill=int(attrs.get('fill', 1)))
359 container.new(int(attrs.get('col',4)))
361 widget, widgets, buttons, on_write = self.parse(model, node, fields, tooltips=self.tooltips)
362 dict_widget.update(widgets)
363 button_list += buttons
364 frame.add(widget)
365 if not attrs.get('string', None):
366 frame.set_shadow_type(gtk.SHADOW_NONE)
367 container.get().set_border_width(0)
368 container.pop()
369 elif node.localName=='hpaned':
370 hp = gtk.HPaned()
371 container.wid_add(hp, colspan=int(attrs.get('colspan', 4)), expand=True, fill=True)
372 _, widgets, buttons, on_write = self.parse(model, node, fields, paned=hp, tooltips=self.tooltips)
373 button_list += buttons
374 dict_widget.update(widgets)
375 #if 'position' in attrs:
376 # hp.set_position(int(attrs['position']))
377 elif node.localName=='vpaned':
378 hp = gtk.VPaned()
379 container.wid_add(hp, colspan=int(attrs.get('colspan', 4)), expand=True, fill=True)
380 _, widgets, buttons, on_write = self.parse(model, node, fields, paned=hp, tooltips=self.tooltips)
381 button_list += buttons
382 dict_widget.update(widgets)
383 if 'position' in attrs:
384 hp.set_position(int(attrs['position']))
385 elif node.localName=='child1':
386 widget, widgets, buttons, on_write = self.parse(model, node, fields, paned=paned, tooltips=self.tooltips)
387 button_list += buttons
388 dict_widget.update(widgets)
389 paned.pack1(widget, resize=True, shrink=True)
390 elif node.localName=='child2':
391 widget, widgets, buttons, on_write = self.parse(model, node, fields, paned=paned, tooltips=self.tooltips)
392 button_list += buttons
393 dict_widget.update(widgets)
394 paned.pack2(widget, resize=True, shrink=True)
395 elif node.localName=='action':
396 from action import action
397 name = str(attrs['name'])
398 widget_act = action(self.window, self.parent, model, attrs)
399 dict_widget[name] = widget_act
400 container.wid_add(widget_act.widget, colspan=int(attrs.get('colspan', 3)), expand=True, fill=True)
401 for (ebox,src,name,widget) in container.trans_box:
402 ebox.connect('button_press_event',self.translate, model, name, src, widget)
403 for (ebox,src,name) in container.trans_box_label:
404 ebox.connect('button_press_event', self.translate_label, model, name, src)
405 return container.pop(), dict_widget, button_list, on_write
407 def translate(self, widget, event, model, name, src, widget_entry):
408 id = self.screen.current_model.id
409 if not id:
410 common.message(
411 _('You need to save resource before adding translations!'),
412 parent=self.window)
413 return False
414 id = self.screen.current_model.save(reload=False)
415 uid = rpc.session.uid
417 lang_ids = rpc.session.rpc_exec_auth('/object', 'execute', 'res.lang',
418 'search', [('translatable','=','1')])
420 if not lang_ids:
421 common.message(_('No other language available!'),
422 parent=self.window)
423 return False
424 langs = rpc.session.rpc_exec_auth('/object', 'execute', 'res.lang',
425 'read', lang_ids, ['code', 'name'])
427 code = rpc.session.context.get('lang', 'en_US')
429 #change 'en' to false for context
430 def adapt_context(val):
431 if val == 'en_US':
432 return False
433 else:
434 return val
436 #widget accessor functions
437 def value_get(widget):
438 if type(widget) == type(gtk.Entry()):
439 return widget.get_text()
440 elif type(widget.child) == type(gtk.TextView()):
441 buffer = widget.child.get_buffer()
442 iter_start = buffer.get_start_iter()
443 iter_end = buffer.get_end_iter()
444 return buffer.get_text(iter_start,iter_end,False)
445 else:
446 return None
448 def value_set(widget, value):
449 if type(widget) == type(gtk.Entry()):
450 widget.set_text(value)
451 elif type(widget.child) == type(gtk.TextView()):
452 if value==False:
453 value=''
454 buffer = widget.child.get_buffer()
455 buffer.delete(buffer.get_start_iter(), buffer.get_end_iter())
456 iter_start = buffer.get_start_iter()
457 buffer.insert(iter_start, value)
459 def widget_duplicate(widget):
460 if type(widget) == type(gtk.Entry()):
461 entry = gtk.Entry()
462 entry.set_property('activates_default', True)
463 entry.set_max_length(widget.get_max_length())
464 entry.set_width_chars(widget.get_width_chars())
465 return entry, gtk.FILL
466 elif type(widget.child) == type(gtk.TextView()):
467 tv = gtk.TextView()
468 tv.set_wrap_mode(gtk.WRAP_WORD)
469 sw = gtk.ScrolledWindow()
470 sw.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_ALWAYS)
471 sw.set_shadow_type(gtk.SHADOW_NONE)
472 sw.set_size_request(-1, 80)
473 sw.add(tv)
474 tv.set_accepts_tab(False)
475 return sw, gtk.FILL | gtk.EXPAND
476 else:
477 return None, False
480 win = gtk.Dialog(_('Add Translation'), self.window,
481 gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT)
482 win.vbox.set_spacing(5)
483 win.set_property('default-width', 600)
484 win.set_property('default-height', 400)
485 win.set_position(gtk.WIN_POS_CENTER_ON_PARENT)
486 win.set_icon(common.TINYERP_ICON)
488 accel_group = gtk.AccelGroup()
489 win.add_accel_group(accel_group)
491 but_cancel = win.add_button(gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL)
492 but_cancel.add_accelerator('clicked', accel_group, gtk.keysyms.Escape,
493 gtk.gdk.CONTROL_MASK, gtk.ACCEL_VISIBLE)
494 but_ok = win.add_button(gtk.STOCK_OK, gtk.RESPONSE_OK)
495 but_ok.add_accelerator('clicked', accel_group, gtk.keysyms.Return,
496 gtk.gdk.CONTROL_MASK, gtk.ACCEL_VISIBLE)
498 vbox = gtk.VBox(spacing=5)
500 entries_list = []
501 table = gtk.Table(len(langs), 2)
502 table.set_homogeneous(False)
503 table.set_col_spacings(3)
504 table.set_row_spacings(0)
505 table.set_border_width(1)
506 i = 0
507 for lang in langs:
508 context = copy.copy(rpc.session.context)
509 context['lang'] = adapt_context(lang['code'])
510 val = rpc.session.rpc_exec_auth('/object', 'execute', model,
511 'read', [id], [name], context)
512 val = val[0]
513 #TODO space before ':' depends of lang (ex: english no space)
514 if gtk.widget_get_default_direction() == gtk.TEXT_DIR_RTL:
515 label = gtk.Label(': ' + lang['name'])
516 else:
517 label = gtk.Label(lang['name'] + ' :')
518 label.set_alignment(1.0, 0.5)
519 (entry, yoptions) = widget_duplicate(widget_entry)
521 hbox = gtk.HBox(homogeneous=False)
522 if code == lang['code']:
523 value_set(entry,value_get(widget_entry))
524 else:
525 value_set(entry,val[name])
527 entries_list.append((val['id'], lang['code'], entry))
528 table.attach(label, 0, 1, i, i+1, yoptions=False, xoptions=gtk.FILL,
529 ypadding=2, xpadding=5)
530 table.attach(entry, 1, 2, i, i+1, yoptions=yoptions,
531 ypadding=2, xpadding=5)
532 i += 1
534 vbox.pack_start(table)
535 vp = gtk.Viewport()
536 vp.set_shadow_type(gtk.SHADOW_NONE)
537 vp.add(vbox)
538 sv = gtk.ScrolledWindow()
539 sv.set_policy(gtk.POLICY_AUTOMATIC,gtk.POLICY_AUTOMATIC )
540 sv.set_shadow_type(gtk.SHADOW_NONE)
541 sv.add(vp)
542 win.vbox.add(sv)
543 win.show_all()
545 ok = False
546 data = []
547 while not ok:
548 response = win.run()
549 ok = True
550 if response == gtk.RESPONSE_OK:
551 to_save = map(lambda x : (x[0], x[1], value_get(x[2])),
552 entries_list)
553 while to_save != []:
554 new_val = {}
555 new_val['id'],new_val['code'], new_val['value'] = to_save.pop()
556 #update form field
557 if new_val['code'] == code:
558 value_set(widget_entry, new_val['value'])
559 context = copy.copy(rpc.session.context)
560 context['lang'] = adapt_context(new_val['code'])
561 rpc.session.rpc_exec_auth('/object', 'execute', model,
562 'write', [id], {str(name): new_val['value']},
563 context)
564 if response == gtk.RESPONSE_CANCEL:
565 self.window.present()
566 win.destroy()
567 return
568 self.screen.current_model.reload()
569 self.window.present()
570 win.destroy()
571 return True
573 def translate_label(self, widget, event, model, name, src):
574 def callback_label(self, widget, event, model, name, src, window=None):
575 lang_ids = rpc.session.rpc_exec_auth('/object', 'execute',
576 'res.lang', 'search', [('translatable', '=', '1')])
577 if not lang_ids:
578 common.message(_('No other language available!'),
579 parent=window)
580 return False
581 langs = rpc.session.rpc_exec_auth('/object', 'execute', 'res.lang',
582 'read', lang_ids, ['code', 'name'])
584 win = gtk.Dialog(_('Add Translation'), window,
585 gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT)
586 win.vbox.set_spacing(5)
587 win.set_position(gtk.WIN_POS_CENTER_ON_PARENT)
588 win.set_icon(common.TINYERP_ICON)
589 vbox = gtk.VBox(spacing=5)
591 entries_list = []
592 for lang in langs:
593 code=lang['code']
594 val = rpc.session.rpc_exec_auth('/object', 'execute', model,
595 'read_string', False, [code], [name])
596 if val and code in val:
597 val = val[code]
598 else:
599 val={'code': code, 'name': src}
600 label = gtk.Label(lang['name'])
601 entry = gtk.Entry()
602 entry.set_text(val[name])
603 entries_list.append((code, entry))
604 hbox = gtk.HBox(homogeneous=True)
605 hbox.pack_start(label, expand=False, fill=False)
606 hbox.pack_start(entry, expand=True, fill=True)
607 vbox.pack_start(hbox, expand=False, fill=True)
608 vp = gtk.Viewport()
609 vp.set_shadow_type(gtk.SHADOW_NONE)
610 vp.add(vbox)
611 sv = gtk.ScrolledWindow()
612 sv.set_policy(gtk.POLICY_AUTOMATIC,gtk.POLICY_AUTOMATIC )
613 sv.set_shadow_type(gtk.SHADOW_NONE)
614 sv.add(vp)
615 win.vbox.add(sv)
616 win.add_button(gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL)
617 win.add_button(gtk.STOCK_OK, gtk.RESPONSE_OK)
618 win.resize(400,200)
619 win.show_all()
620 res = win.run()
621 if res == gtk.RESPONSE_OK:
622 to_save = map(lambda x: (x[0], x[1].get_text()), entries_list)
623 while to_save:
624 code, val = to_save.pop()
625 rpc.session.rpc_exec_auth('/object', 'execute', model,
626 'write_string', False, [code], {name: val})
627 window.present()
628 win.destroy()
629 return res
631 def callback_view(self, widget, event, model, src, window=None):
632 lang_ids = rpc.session.rpc_exec_auth('/object', 'execute',
633 'res.lang', 'search', [('translatable', '=', '1')])
634 if not lang_ids:
635 common.message(_('No other language available!'),
636 parent=window)
637 return False
638 langs = rpc.session.rpc_exec_auth('/object', 'execute', 'res.lang',
639 'read', lang_ids, ['code', 'name'])
641 win = gtk.Dialog(_('Add Translation'), window,
642 gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT)
643 win.set_position(gtk.WIN_POS_CENTER_ON_PARENT)
644 win.set_icon(common.TINYERP_ICON)
645 win.vbox.set_spacing(5)
646 vbox = gtk.VBox(spacing=5)
648 entries_list = []
649 for lang in langs:
650 code=lang['code']
651 view_item_ids = rpc.session.rpc_exec_auth('/object', 'execute',
652 'ir.translation', 'search', [
653 ('name', '=', model),
654 ('type', '=', 'view'),
655 ('lang', '=', code),
657 view_items = rpc.session.rpc_exec_auth('/object', 'execute',
658 'ir.translation', 'read', view_item_ids,
659 ['src', 'value'])
660 label = gtk.Label(lang['name'])
661 vbox.pack_start(label, expand=False, fill=True)
662 for val in view_items:
663 label = gtk.Label(val['src'])
664 entry = gtk.Entry()
665 entry.set_text(val['value'])
666 entries_list.append((val['id'], entry))
667 hbox = gtk.HBox(homogeneous=True)
668 hbox.pack_start(label, expand=False, fill=False)
669 hbox.pack_start(entry, expand=True, fill=True)
670 vbox.pack_start(hbox, expand=False, fill=True)
671 vp = gtk.Viewport()
672 vp.set_shadow_type(gtk.SHADOW_NONE)
673 vp.add(vbox)
674 sv = gtk.ScrolledWindow()
675 sv.set_policy(gtk.POLICY_AUTOMATIC,gtk.POLICY_AUTOMATIC )
676 sv.set_shadow_type(gtk.SHADOW_NONE)
677 sv.add(vp)
678 win.vbox.add(sv)
679 win.add_button(gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL)
680 win.add_button(gtk.STOCK_OK, gtk.RESPONSE_OK)
681 win.resize(400,200)
682 win.show_all()
683 res = win.run()
684 if res == gtk.RESPONSE_OK:
685 to_save = map(lambda x: (x[0], x[1].get_text()), entries_list)
686 while to_save:
687 id, val = to_save.pop()
688 rpc.session.rpc_exec_auth('/object', 'execute',
689 'ir.translation', 'write', [id], {'value': val})
690 window.present()
691 win.destroy()
692 return res
693 if event.button != 3:
694 return
695 menu = gtk.Menu()
696 if name:
697 item = gtk.ImageMenuItem(_('Translate label'))
698 item.connect("activate", callback_label, widget, event, model,
699 name, src, self.window)
700 item.set_sensitive(1)
701 item.show()
702 menu.append(item)
703 item = gtk.ImageMenuItem(_('Translate view'))
704 item.connect("activate", callback_view, widget, event, model, src,
705 self.window)
706 item.set_sensitive(1)
707 item.show()
708 menu.append(item)
709 menu.popup(None,None,None,event.button,event.time)
710 return True
712 import float_time
713 import calendar
714 import spinbutton
715 import spinint
716 import char
717 import checkbox
718 import button
719 import reference
720 import binary
721 import textbox
722 import textbox_tag
723 #import one2many
724 import many2many
725 import many2one
726 import selection
727 import one2many_list
728 import picture
729 import url
730 import image
733 widgets_type = {
734 'date': (calendar.calendar, 1, False, False),
735 'time': (calendar.stime, 1, False, False),
736 'datetime': (calendar.datetime, 1, False, False),
737 'float': (spinbutton.spinbutton, 1, False, False),
738 'integer': (spinint.spinint, 1, False, False),
739 'selection': (selection.selection, 1, False, False),
740 'char': (char.char, 1, False, False),
741 'float_time': (float_time.float_time, 1, False, False),
742 'boolean': (checkbox.checkbox, 1, False, False),
743 'button': (button.button, 1, False, False),
744 'reference': (reference.reference, 1, False, False),
745 'binary': (binary.wid_binary, 1, False, False),
746 'picture': (picture.wid_picture, 1, False, False),
747 'text': (textbox.textbox, 1, True, True),
748 'text_tag': (textbox_tag.textbox_tag, 1, True, True),
749 'one2many': (one2many_list.one2many_list, 1, True, True),
750 'one2many_form': (one2many_list.one2many_list, 1, True, True),
751 'one2many_list': (one2many_list.one2many_list, 1, True, True),
752 'many2many': (many2many.many2many, 1, True, True),
753 'many2one': (many2one.many2one, 1, False, False),
754 'email' : (url.email, 1, False, False),
755 'url' : (url.url, 1, False, False),
756 'callto' : (url.callto, 1, False, False),
757 'sip' : (url.sip, 1, False, False),
758 'image' : (image.image_wid, 1, False, False),
759 'uri' : (url.uri, 1, False, False),
762 # vim:noexpandtab: