1 ##############################################################################
3 # Copyright (c) 2004-2008 TINY SPRL. (http://tiny.be) All Rights Reserved.
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
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 ##############################################################################
33 import widget
.view
.interface
34 from observator
import oregistry
, Observable
47 class Button(Observable
):
48 def __init__(self
, attrs
={}):
49 super(Button
, self
).__init
__()
52 'label': attrs
.get('string', 'unknown')
54 self
.widget
= gtk
.Button(**args
)
55 if attrs
.get('icon', False):
59 icon
.set_from_stock(stock
, gtk
.ICON_SIZE_BUTTON
)
60 self
.widget
.set_image(icon
)
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'])
69 self
.widget
.connect('clicked', self
.button_clicked
)
71 def button_clicked(self
, widget
):
72 model
= self
.form
.screen
.current_model
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':
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({}):
90 obj
= service
.LocalService('action.main')
91 obj
._exec
_action
(result
,datas
)
92 elif button_type
== 'object':
95 result
= rpc
.session
.rpc_exec_auth(
97 self
.form
.screen
.name
,
99 [id], model
.context_get()
101 if type(result
)==type({}):
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
)
112 raise Exception, 'Unallowed button type'
113 self
.form
.screen
.reload()
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
:
128 class _container(object):
129 def __init__(self
, tooltips
):
132 self
.sg
= gtk
.SizeGroup(gtk
.SIZE_GROUP_HORIZONTAL
)
133 self
.tooltips
= tooltips
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
)
147 return self
.cont
[-1][0]
150 (table
, x
, y
) = self
.cont
.pop()
155 (table
, x
, y
) = self
.cont
[-1]
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]:
166 if colspan
+x
+a
>self
.col
[-1]:
168 (table
, x
, y
) = self
.cont
[-1]
171 yopt
= yopt | gtk
.EXPAND
173 yopt
= yopt | gtk
.FILL
174 if colspan
== 1 and a
== 1:
177 label
= gtk
.Label(name
)
179 eb
.set_events(gtk
.gdk
.BUTTON_PRESS_MASK
)
180 self
.trans_box_label
.append((eb
, name
, fname
))
183 self
.tooltips
.set_tip(eb
, help)
184 self
.tooltips
.enable()
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)
195 hbox
= gtk
.HBox(spacing
=3)
196 hbox
.pack_start(widget
)
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
))
204 hbox
.pack_start(ebox
, fill
=False, expand
=False)
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()
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):
217 attrs
= tools
.node_attributes(root_node
)
218 on_write
= attrs
.get('on_write', '')
220 self
.tooltips
= gtk
.Tooltips()
222 self
.tooltips
= tooltips
223 container
= _container(self
.tooltips
)
224 container
.new(col
=int(attrs
.get('col', 4)))
225 self
.container
= container
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
:
234 attrs
= tools
.node_attributes(node
)
235 if node
.localName
=='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':
241 if 'string' in attrs
:
242 text
= attrs
.get('string', 'No String Attr.')
244 l
.set_alignment(0.0, 0.5)
246 eb
.set_events(gtk
.gdk
.BUTTON_PRESS_MASK
)
248 container
.trans_box_label
.append((eb
, text
, None))
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', '')
255 for node
in node
.childNodes
:
256 if node
.nodeType
== node
.TEXT_NODE
:
260 label
= gtk
.Label(text
)
261 label
.set_use_markup(True)
264 label
.set_alignment(float(attrs
['align'] or 0.0), 0.5)
267 if 'angle' not in attrs
:
268 label
.set_line_wrap(True)
269 label
.set_angle(int(attrs
.get('angle', 0)))
271 eb
.set_events(gtk
.gdk
.BUTTON_PRESS_MASK
)
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':
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':
286 if attrs
and 'tabpos' in attrs
:
287 pos
= {'up':gtk
.POS_TOP
,
288 'down':gtk
.POS_BOTTOM
,
290 'right':gtk
.POS_RIGHT
293 if options
.options
['client.form_tab'] == 'top':
295 elif options
.options
['client.form_tab'] == 'left':
297 elif options
.options
['client.form_tab'] == 'right':
299 elif options
.options
['client.form_tab'] == 'bottom':
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'])
312 angle
= int(options
.options
['client.form_tab_orientation'])
313 l
= gtk
.Label(attrs
.get('string','No String Attr.'))
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'])
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
:
328 if attrs
.get('invisible', False):
329 visval
= eval(attrs
['invisible'], {'context':self
.screen
.context
})
333 fields
[name
]['name'] = name
335 fields
[name
]['saves'] = attrs
['saves']
336 widget_act
= widgets_type
[type][0](self
.window
, self
.parent
, model
, fields
[name
])
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']
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
365 if not attrs
.get('string', None):
366 frame
.set_shadow_type(gtk
.SHADOW_NONE
)
367 container
.get().set_border_width(0)
369 elif node
.localName
=='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':
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
411 _('You need to save resource before adding translations!'),
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')])
421 common
.message(_('No other language available!'),
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
):
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)
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()):
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()):
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()):
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)
474 tv
.set_accepts_tab(False)
475 return sw
, gtk
.FILL | gtk
.EXPAND
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)
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)
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
)
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'])
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
))
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)
534 vbox
.pack_start(table
)
536 vp
.set_shadow_type(gtk
.SHADOW_NONE
)
538 sv
= gtk
.ScrolledWindow()
539 sv
.set_policy(gtk
.POLICY_AUTOMATIC
,gtk
.POLICY_AUTOMATIC
)
540 sv
.set_shadow_type(gtk
.SHADOW_NONE
)
550 if response
== gtk
.RESPONSE_OK
:
551 to_save
= map(lambda x
: (x
[0], x
[1], value_get(x
[2])),
555 new_val
['id'],new_val
['code'], new_val
['value'] = to_save
.pop()
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']},
564 if response
== gtk
.RESPONSE_CANCEL
:
565 self
.window
.present()
568 self
.screen
.current_model
.reload()
569 self
.window
.present()
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')])
578 common
.message(_('No other language available!'),
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)
594 val
= rpc
.session
.rpc_exec_auth('/object', 'execute', model
,
595 'read_string', False, [code
], [name
])
596 if val
and code
in val
:
599 val
={'code': code
, 'name': src
}
600 label
= gtk
.Label(lang
['name'])
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)
609 vp
.set_shadow_type(gtk
.SHADOW_NONE
)
611 sv
= gtk
.ScrolledWindow()
612 sv
.set_policy(gtk
.POLICY_AUTOMATIC
,gtk
.POLICY_AUTOMATIC
)
613 sv
.set_shadow_type(gtk
.SHADOW_NONE
)
616 win
.add_button(gtk
.STOCK_CANCEL
, gtk
.RESPONSE_CANCEL
)
617 win
.add_button(gtk
.STOCK_OK
, gtk
.RESPONSE_OK
)
621 if res
== gtk
.RESPONSE_OK
:
622 to_save
= map(lambda x
: (x
[0], x
[1].get_text()), entries_list
)
624 code
, val
= to_save
.pop()
625 rpc
.session
.rpc_exec_auth('/object', 'execute', model
,
626 'write_string', False, [code
], {name
: val
})
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')])
635 common
.message(_('No other language available!'),
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)
651 view_item_ids
= rpc
.session
.rpc_exec_auth('/object', 'execute',
652 'ir.translation', 'search', [
653 ('name', '=', model
),
654 ('type', '=', 'view'),
657 view_items
= rpc
.session
.rpc_exec_auth('/object', 'execute',
658 'ir.translation', 'read', view_item_ids
,
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'])
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)
672 vp
.set_shadow_type(gtk
.SHADOW_NONE
)
674 sv
= gtk
.ScrolledWindow()
675 sv
.set_policy(gtk
.POLICY_AUTOMATIC
,gtk
.POLICY_AUTOMATIC
)
676 sv
.set_shadow_type(gtk
.SHADOW_NONE
)
679 win
.add_button(gtk
.STOCK_CANCEL
, gtk
.RESPONSE_CANCEL
)
680 win
.add_button(gtk
.STOCK_OK
, gtk
.RESPONSE_OK
)
684 if res
== gtk
.RESPONSE_OK
:
685 to_save
= map(lambda x
: (x
[0], x
[1].get_text()), entries_list
)
687 id, val
= to_save
.pop()
688 rpc
.session
.rpc_exec_auth('/object', 'execute',
689 'ir.translation', 'write', [id], {'value': val
})
693 if event
.button
!= 3:
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)
703 item
= gtk
.ImageMenuItem(_('Translate view'))
704 item
.connect("activate", callback_view
, widget
, event
, model
, src
,
706 item
.set_sensitive(1)
709 menu
.popup(None,None,None,event
.button
,event
.time
)
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),