1 # -*- encoding: utf-8 -*-
2 ##############################################################################
4 # Copyright (c) 2004-2008 TINY SPRL. (http://tiny.be) All Rights Reserved.
8 # WARNING: This program as such is intended to be used by professional
9 # programmers who take the whole responsability of assessing all potential
10 # consequences resulting from its eventual inadequacies and bugs
11 # End users who are looking for a ready-to-use solution with commercial
12 # garantees and support are strongly adviced to contract a Free Software
15 # This program is Free Software; you can redistribute it and/or
16 # modify it under the terms of the GNU General Public License
17 # as published by the Free Software Foundation; either version 2
18 # of the License, or (at your option) any later version.
20 # This program is distributed in the hope that it will be useful,
21 # but WITHOUT ANY WARRANTY; without even the implied warranty of
22 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23 # GNU General Public License for more details.
25 # You should have received a copy of the GNU General Public License
26 # along with this program; if not, write to the Free Software
27 # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
29 ##############################################################################
34 import widget
.view
.interface
35 from observator
import oregistry
, Observable
48 class Button(Observable
):
49 def __init__(self
, attrs
={}):
50 super(Button
, self
).__init
__()
53 'label': attrs
.get('string', 'unknown')
55 self
.widget
= gtk
.Button(**args
)
56 if attrs
.get('icon', False):
60 icon
.set_from_stock(stock
, gtk
.ICON_SIZE_BUTTON
)
61 self
.widget
.set_image(icon
)
64 log
= logging
.getLogger('common')
65 log
.warning(_('Wrong icon for the button !'))
66 # self.widget.set_use_stock(True)
67 # self.widget.set_label(args['label'])
70 self
.widget
.connect('clicked', self
.button_clicked
)
73 return self
.widget
.hide()
76 return self
.widget
.show()
78 def button_clicked(self
, widget
):
79 model
= self
.form
.screen
.current_model
81 button_type
= self
.attrs
.get('special', '')
82 if button_type
=='cancel':
83 self
.form
.screen
.window
.destroy()
84 if 'name' in self
.attrs
.keys():
85 result
= rpc
.session
.rpc_exec_auth(
87 self
.form
.screen
.name
,
88 self
.attrs
['name'],[], model
.context_get())
90 obj
= service
.LocalService('action.main')
91 obj
._exec
_action
(result
,datas
,context
=self
.form
.screen
.context
)
92 elif model
.validate():
93 id = self
.form
.screen
.save_current()
94 if not self
.attrs
.get('confirm',False) or \
95 common
.sur(self
.attrs
['confirm']):
96 button_type
= self
.attrs
.get('type', 'workflow')
97 if button_type
== 'workflow':
98 #print 'Exec Workflow'
99 result
= rpc
.session
.rpc_exec_auth('/object', 'exec_workflow',
100 self
.form
.screen
.name
,
101 self
.attrs
['name'], id)
102 if type(result
)==type({}):
103 if result
['type']== 'ir.actions.act_window_close':
104 self
.form
.screen
.window
.destroy()
107 obj
= service
.LocalService('action.main')
108 obj
._exec
_action
(result
,datas
)
109 elif button_type
== 'object':
112 result
= rpc
.session
.rpc_exec_auth(
113 '/object', 'execute',
114 self
.form
.screen
.name
,
116 [id], model
.context_get()
118 if type(result
)==type({}):
119 self
.form
.screen
.window
.destroy()
121 obj
= service
.LocalService('action.main')
122 obj
._exec
_action
(result
,datas
,context
=self
.form
.screen
.context
)
124 elif button_type
== 'action':
125 obj
= service
.LocalService('action.main')
126 action_id
= int(self
.attrs
['name'])
127 obj
.execute(action_id
, {'model':self
.form
.screen
.name
, 'id': id or False,
128 'ids': id and [id] or [], 'report_type': 'pdf'}, context
=self
.form
.screen
.context
)
130 raise Exception, 'Unallowed button type'
131 self
.form
.screen
.reload()
133 self
.warn('misc-message', _('Invalid form, correct red fields !'), "red")
134 self
.form
.screen
.display()
138 class StateAwareWidget(object):
139 def __init__(self
, widget
, states
=None):
141 self
.states
= states
or []
143 def __getattr__(self
, a
):
144 return self
.widget
.__getattribute
__(a
)
146 def state_set(self
, state
):
147 if (not len(self
.states
)) or (state
in self
.states
):
152 def attrs_set(self
, model
):
153 sa
= hasattr(self
.widget
, 'attrs') and self
.widget
.attrs
or {}
154 attrs_changes
= eval(sa
.get('attrs',"{}"))
155 for k
,v
in attrs_changes
.items():
157 result
= tools
.calc_condition(self
,model
,condition
)
162 self
.widget
.set_sensitive(False)
164 self
.widget
.set_sensitive(False and sa
.get('readonly',False))
167 class _container(object):
168 def __init__(self
, tooltips
):
171 self
.sg
= gtk
.SizeGroup(gtk
.SIZE_GROUP_HORIZONTAL
)
172 self
.tooltips
= tooltips
174 self
.trans_box_label
= []
176 def new(self
, col
=4):
177 table
= gtk
.Table(1, col
)
178 table
.set_homogeneous(False)
179 table
.set_col_spacings(3)
180 table
.set_row_spacings(0)
181 table
.set_border_width(1)
182 self
.cont
.append( (table
, 0, 0) )
183 self
.col
.append( col
)
186 return self
.cont
[-1][0]
189 (table
, x
, y
) = self
.cont
.pop()
194 (table
, x
, y
) = self
.cont
[-1]
196 self
.cont
[-1] = (table
, 0, y
+1)
197 table
.resize(y
+1,self
.col
[-1])
199 def wid_add(self
, widget
, name
=None, expand
=False, ypadding
=2, rowspan
=1,
200 colspan
=1, translate
=False, fname
=None, help=False, fill
=False):
201 (table
, x
, y
) = self
.cont
[-1]
202 if colspan
>self
.col
[-1]:
205 if colspan
+x
+a
>self
.col
[-1]:
207 (table
, x
, y
) = self
.cont
[-1]
210 yopt
= yopt | gtk
.EXPAND
212 yopt
= yopt | gtk
.FILL
213 if colspan
== 1 and a
== 1:
216 label
= gtk
.Label(name
)
218 eb
.set_events(gtk
.gdk
.BUTTON_PRESS_MASK
)
219 self
.trans_box_label
.append((eb
, name
, fname
))
222 self
.tooltips
.set_tip(eb
, help)
223 self
.tooltips
.enable()
224 label
.set_markup("<sup><span foreground=\"darkgreen\">?</span></sup>"+name
.replace('&','&').replace('<','<').replace('>','>'))
227 label
.set_text_with_mnemonic(name
)
228 label
.set_mnemonic_widget(widget
)
229 label
.set_alignment(1.0, 0.5)
230 table
.attach(eb
, x
, x
+1, y
, y
+rowspan
, yoptions
=yopt
,
231 xoptions
=gtk
.FILL
, ypadding
=ypadding
, xpadding
=2)
235 hbox
= gtk
.HBox(spacing
=3)
236 hbox
.pack_start(widget
)
238 img
.set_from_stock('terp-translate', gtk
.ICON_SIZE_MENU
)
239 ebox
= gtk
.EventBox()
240 ebox
.set_events(gtk
.gdk
.BUTTON_PRESS_MASK
)
241 self
.trans_box
.append((ebox
, name
, fname
, widget
))
244 hbox
.pack_start(ebox
, fill
=False, expand
=False)
246 table
.attach(hbox
, x
+a
, x
+colspan
, y
, y
+rowspan
, yoptions
=yopt
,
247 ypadding
=ypadding
, xpadding
=2)
248 self
.cont
[-1] = (table
, x
+colspan
, y
)
249 wid_list
= table
.get_children()
251 table
.set_focus_chain(wid_list
)
253 class parser_form(widget
.view
.interface
.parser_interface
):
254 def parse(self
, model
, root_node
, fields
, notebook
=None, paned
=None, tooltips
=None):
256 saw_list
= [] # state aware widget list
257 attrs
= tools
.node_attributes(root_node
)
258 on_write
= attrs
.get('on_write', '')
260 self
.tooltips
= gtk
.Tooltips()
262 self
.tooltips
= tooltips
263 container
= _container(self
.tooltips
)
264 container
.new(col
=int(attrs
.get('col', 4)))
265 self
.container
= container
268 attrs
= tools
.node_attributes(root_node
)
269 self
.title
= attrs
.get('string', 'Unknown')
271 for node
in root_node
.childNodes
:
272 if not node
.nodeType
==node
.ELEMENT_NODE
:
274 attrs
= tools
.node_attributes(node
)
275 if node
.localName
=='image':
277 icon
.set_from_stock(attrs
['name'], gtk
.ICON_SIZE_DIALOG
)
278 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)))
279 elif node
.localName
=='separator':
281 if 'string' in attrs
:
282 text
= attrs
.get('string', 'No String Attr.')
283 l
= gtk
.Label('<b>'+(text
.replace('&','&').replace('<','<').replace('>','>'))+'</b>')
284 l
.set_use_markup(True)
285 l
.set_alignment(0.0, 0.5)
287 eb
.set_events(gtk
.gdk
.BUTTON_PRESS_MASK
)
289 container
.trans_box_label
.append((eb
, text
, None))
291 vbox
.pack_start(gtk
.HSeparator())
292 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)))
293 elif node
.localName
=='label':
294 text
= attrs
.get('string', '')
296 for node
in node
.childNodes
:
297 if node
.nodeType
== node
.TEXT_NODE
:
301 label
= gtk
.Label(text
)
302 label
.set_use_markup(True)
305 label
.set_alignment(float(attrs
['align'] or 0.0), 0.5)
308 if 'angle' not in attrs
:
309 label
.set_line_wrap(True)
310 label
.set_angle(int(attrs
.get('angle', 0)))
312 eb
.set_events(gtk
.gdk
.BUTTON_PRESS_MASK
)
314 container
.trans_box_label
.append((eb
, text
, None))
315 container
.wid_add(eb
, colspan
=int(attrs
.get('colspan', 1)), expand
=False, help=attrs
.get('help', False), fill
=int(attrs
.get('fill', 0)))
317 elif node
.localName
=='newline':
320 elif node
.localName
=='button':
321 button
= Button(attrs
)
322 states
= [e
for e
in attrs
.get('states','').split(',') if e
]
323 saw_list
.append(StateAwareWidget(button
, states
))
324 container
.wid_add(button
.widget
, colspan
=int(attrs
.get('colspan', 1)), help=attrs
.get('help', False))
326 elif node
.localName
=='notebook':
328 if attrs
and 'tabpos' in attrs
:
329 pos
= {'up':gtk
.POS_TOP
,
330 'down':gtk
.POS_BOTTOM
,
332 'right':gtk
.POS_RIGHT
335 if options
.options
['client.form_tab'] == 'top':
337 elif options
.options
['client.form_tab'] == 'left':
339 elif options
.options
['client.form_tab'] == 'right':
341 elif options
.options
['client.form_tab'] == 'bottom':
344 nb
.set_border_width(3)
345 container
.wid_add(nb
, colspan
=attrs
.get('colspan', 3), expand
=True, fill
=True )
346 _
, widgets
, saws
, on_write
= self
.parse(model
, node
, fields
, nb
, tooltips
=self
.tooltips
)
348 dict_widget
.update(widgets
)
350 elif node
.localName
=='page':
351 if attrs
and 'angle' in attrs
:
352 angle
= int(attrs
['angle'])
354 angle
= int(options
.options
['client.form_tab_orientation'])
355 l
= gtk
.Label(attrs
.get('string','No String Attr.'))
358 widget
, widgets
, saws
, on_write
= self
.parse(model
, node
, fields
, notebook
, tooltips
=self
.tooltips
)
360 dict_widget
.update(widgets
)
361 notebook
.append_page(widget
, l
)
363 elif node
.localName
=='field':
364 name
= str(attrs
['name'])
366 type = attrs
.get('widget', fields
[name
]['type'])
367 fields
[name
].update(attrs
)
368 fields
[name
]['model']=model
369 if not type in widgets_type
:
371 if attrs
.get('invisible', False):
372 visval
= eval(attrs
['invisible'], {'context':self
.screen
.context
})
376 fields
[name
]['name'] = name
378 fields
[name
]['saves'] = attrs
['saves']
380 if 'filename' in attrs
:
381 fields
[name
]['filename'] = attrs
['filename']
383 widget_act
= widgets_type
[type][0](self
.window
, self
.parent
, model
, fields
[name
])
385 if not int(attrs
.get('nolabel', 0)):
386 # TODO space before ':' depends of lang (ex: english no space)
387 if gtk
.widget_get_default_direction() == gtk
.TEXT_DIR_RTL
:
388 label
= ': '+fields
[name
]['string']
390 label
= fields
[name
]['string']+' :'
391 dict_widget
[name
] = widget_act
392 size
= int(attrs
.get('colspan', widgets_type
[ type ][1]))
393 expand
= widgets_type
[ type ][2]
394 fill
= widgets_type
[ type ][3]
395 hlp
= fields
[name
].get('help', attrs
.get('help', False))
396 if attrs
.get('height', False) or attrs
.get('width', False):
397 widget_act
.widget
.set_size_request(
398 int(attrs
.get('width', -1)), int(attrs
.get('height', -1)))
399 container
.wid_add(widget_act
.widget
, label
, expand
, translate
=fields
[name
].get('translate',False), colspan
=size
, fname
=name
, help=hlp
, fill
=fill
)
401 elif node
.localName
=='group':
402 frame
= gtk
.Frame(attrs
.get('string', None))
404 frame
.set_border_width(0)
405 states
= [e
for e
in attrs
.get('states','').split(',') if e
]
406 saw_list
.append(StateAwareWidget(frame
, states
))
408 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)))
409 container
.new(int(attrs
.get('col',4)))
411 widget
, widgets
, saws
, on_write
= self
.parse(model
, node
, fields
, tooltips
=self
.tooltips
)
412 dict_widget
.update(widgets
)
415 if not attrs
.get('string', None):
416 frame
.set_shadow_type(gtk
.SHADOW_NONE
)
417 container
.get().set_border_width(0)
419 elif node
.localName
=='hpaned':
421 container
.wid_add(hp
, colspan
=int(attrs
.get('colspan', 4)), expand
=True, fill
=True)
422 _
, widgets
, saws
, on_write
= self
.parse(model
, node
, fields
, paned
=hp
, tooltips
=self
.tooltips
)
424 dict_widget
.update(widgets
)
425 #if 'position' in attrs:
426 # hp.set_position(int(attrs['position']))
427 elif node
.localName
=='vpaned':
429 container
.wid_add(hp
, colspan
=int(attrs
.get('colspan', 4)), expand
=True, fill
=True)
430 _
, widgets
, saws
, on_write
= self
.parse(model
, node
, fields
, paned
=hp
, tooltips
=self
.tooltips
)
432 dict_widget
.update(widgets
)
433 if 'position' in attrs
:
434 hp
.set_position(int(attrs
['position']))
435 elif node
.localName
=='child1':
436 widget
, widgets
, saws
, on_write
= self
.parse(model
, node
, fields
, paned
=paned
, tooltips
=self
.tooltips
)
438 dict_widget
.update(widgets
)
439 paned
.pack1(widget
, resize
=True, shrink
=True)
440 elif node
.localName
=='child2':
441 widget
, widgets
, saws
, on_write
= self
.parse(model
, node
, fields
, paned
=paned
, tooltips
=self
.tooltips
)
443 dict_widget
.update(widgets
)
444 paned
.pack2(widget
, resize
=True, shrink
=True)
445 elif node
.localName
=='action':
446 from action
import action
447 name
= str(attrs
['name'])
448 widget_act
= action(self
.window
, self
.parent
, model
, attrs
)
449 dict_widget
[name
] = widget_act
450 container
.wid_add(widget_act
.widget
, colspan
=int(attrs
.get('colspan', 3)), expand
=True, fill
=True)
451 for (ebox
,src
,name
,widget
) in container
.trans_box
:
452 ebox
.connect('button_press_event',self
.translate
, model
, name
, src
, widget
)
453 for (ebox
,src
,name
) in container
.trans_box_label
:
454 ebox
.connect('button_press_event', self
.translate_label
, model
, name
, src
)
455 return container
.pop(), dict_widget
, saw_list
, on_write
457 def translate(self
, widget
, event
, model
, name
, src
, widget_entry
):
458 id = self
.screen
.current_model
.id
461 _('You need to save resource before adding translations!'),
464 id = self
.screen
.current_model
.save(reload=False)
465 uid
= rpc
.session
.uid
467 lang_ids
= rpc
.session
.rpc_exec_auth('/object', 'execute', 'res.lang',
468 'search', [('translatable','=','1')])
471 common
.message(_('No other language available!'),
474 langs
= rpc
.session
.rpc_exec_auth('/object', 'execute', 'res.lang',
475 'read', lang_ids
, ['code', 'name'])
477 code
= rpc
.session
.context
.get('lang', 'en_US')
479 #change 'en' to false for context
480 def adapt_context(val
):
486 #widget accessor functions
487 def value_get(widget
):
488 if type(widget
) == type(gtk
.Entry()):
489 return widget
.get_text()
490 elif type(widget
.child
) == type(gtk
.TextView()):
491 buffer = widget
.child
.get_buffer()
492 iter_start
= buffer.get_start_iter()
493 iter_end
= buffer.get_end_iter()
494 return buffer.get_text(iter_start
,iter_end
,False)
498 def value_set(widget
, value
):
499 if type(widget
) == type(gtk
.Entry()):
500 widget
.set_text(value
)
501 elif type(widget
.child
) == type(gtk
.TextView()):
504 buffer = widget
.child
.get_buffer()
505 buffer.delete(buffer.get_start_iter(), buffer.get_end_iter())
506 iter_start
= buffer.get_start_iter()
507 buffer.insert(iter_start
, value
)
509 def widget_duplicate(widget
):
510 if type(widget
) == type(gtk
.Entry()):
512 entry
.set_property('activates_default', True)
513 entry
.set_max_length(widget
.get_max_length())
514 entry
.set_width_chars(widget
.get_width_chars())
515 return entry
, gtk
.FILL
516 elif type(widget
.child
) == type(gtk
.TextView()):
518 tv
.set_wrap_mode(gtk
.WRAP_WORD
)
519 sw
= gtk
.ScrolledWindow()
520 sw
.set_policy(gtk
.POLICY_AUTOMATIC
, gtk
.POLICY_ALWAYS
)
521 sw
.set_shadow_type(gtk
.SHADOW_NONE
)
522 sw
.set_size_request(-1, 80)
524 tv
.set_accepts_tab(False)
525 return sw
, gtk
.FILL | gtk
.EXPAND
530 win
= gtk
.Dialog(_('Add Translation'), self
.window
,
531 gtk
.DIALOG_MODAL | gtk
.DIALOG_DESTROY_WITH_PARENT
)
532 win
.vbox
.set_spacing(5)
533 win
.set_property('default-width', 600)
534 win
.set_property('default-height', 400)
535 win
.set_position(gtk
.WIN_POS_CENTER_ON_PARENT
)
536 win
.set_icon(common
.TINYERP_ICON
)
538 accel_group
= gtk
.AccelGroup()
539 win
.add_accel_group(accel_group
)
541 but_cancel
= win
.add_button(gtk
.STOCK_CANCEL
, gtk
.RESPONSE_CANCEL
)
542 but_cancel
.add_accelerator('clicked', accel_group
, gtk
.keysyms
.Escape
,
543 gtk
.gdk
.CONTROL_MASK
, gtk
.ACCEL_VISIBLE
)
544 but_ok
= win
.add_button(gtk
.STOCK_OK
, gtk
.RESPONSE_OK
)
545 but_ok
.add_accelerator('clicked', accel_group
, gtk
.keysyms
.Return
,
546 gtk
.gdk
.CONTROL_MASK
, gtk
.ACCEL_VISIBLE
)
548 vbox
= gtk
.VBox(spacing
=5)
551 table
= gtk
.Table(len(langs
), 2)
552 table
.set_homogeneous(False)
553 table
.set_col_spacings(3)
554 table
.set_row_spacings(0)
555 table
.set_border_width(1)
558 context
= copy
.copy(rpc
.session
.context
)
559 context
['lang'] = adapt_context(lang
['code'])
560 val
= rpc
.session
.rpc_exec_auth('/object', 'execute', model
,
561 'read', [id], [name
], context
)
563 #TODO space before ':' depends of lang (ex: english no space)
564 if gtk
.widget_get_default_direction() == gtk
.TEXT_DIR_RTL
:
565 label
= gtk
.Label(': ' + lang
['name'])
567 label
= gtk
.Label(lang
['name'] + ' :')
568 label
.set_alignment(1.0, 0.5)
569 (entry
, yoptions
) = widget_duplicate(widget_entry
)
571 hbox
= gtk
.HBox(homogeneous
=False)
572 if code
== lang
['code']:
573 value_set(entry
,value_get(widget_entry
))
575 value_set(entry
,val
[name
])
577 entries_list
.append((val
['id'], lang
['code'], entry
))
578 table
.attach(label
, 0, 1, i
, i
+1, yoptions
=False, xoptions
=gtk
.FILL
,
579 ypadding
=2, xpadding
=5)
580 table
.attach(entry
, 1, 2, i
, i
+1, yoptions
=yoptions
,
581 ypadding
=2, xpadding
=5)
584 vbox
.pack_start(table
)
586 vp
.set_shadow_type(gtk
.SHADOW_NONE
)
588 sv
= gtk
.ScrolledWindow()
589 sv
.set_policy(gtk
.POLICY_AUTOMATIC
,gtk
.POLICY_AUTOMATIC
)
590 sv
.set_shadow_type(gtk
.SHADOW_NONE
)
600 if response
== gtk
.RESPONSE_OK
:
601 to_save
= map(lambda x
: (x
[0], x
[1], value_get(x
[2])),
605 new_val
['id'],new_val
['code'], new_val
['value'] = to_save
.pop()
607 if new_val
['code'] == code
:
608 value_set(widget_entry
, new_val
['value'])
609 context
= copy
.copy(rpc
.session
.context
)
610 context
['lang'] = adapt_context(new_val
['code'])
611 rpc
.session
.rpc_exec_auth('/object', 'execute', model
,
612 'write', [id], {str(name
): new_val
['value']},
614 if response
== gtk
.RESPONSE_CANCEL
:
615 self
.window
.present()
618 self
.screen
.current_model
.reload()
619 self
.window
.present()
623 def translate_label(self
, widget
, event
, model
, name
, src
):
624 def callback_label(self
, widget
, event
, model
, name
, src
, window
=None):
625 lang_ids
= rpc
.session
.rpc_exec_auth('/object', 'execute',
626 'res.lang', 'search', [('translatable', '=', '1')])
628 common
.message(_('No other language available!'),
631 langs
= rpc
.session
.rpc_exec_auth('/object', 'execute', 'res.lang',
632 'read', lang_ids
, ['code', 'name'])
634 win
= gtk
.Dialog(_('Add Translation'), window
,
635 gtk
.DIALOG_MODAL | gtk
.DIALOG_DESTROY_WITH_PARENT
)
636 win
.vbox
.set_spacing(5)
637 win
.set_position(gtk
.WIN_POS_CENTER_ON_PARENT
)
638 win
.set_icon(common
.TINYERP_ICON
)
639 vbox
= gtk
.VBox(spacing
=5)
644 val
= rpc
.session
.rpc_exec_auth('/object', 'execute', model
,
645 'read_string', False, [code
], [name
])
646 if val
and code
in val
:
649 val
={'code': code
, 'name': src
}
650 label
= gtk
.Label(lang
['name'])
652 entry
.set_text(val
[name
])
653 entries_list
.append((code
, entry
))
654 hbox
= gtk
.HBox(homogeneous
=True)
655 hbox
.pack_start(label
, expand
=False, fill
=False)
656 hbox
.pack_start(entry
, expand
=True, fill
=True)
657 vbox
.pack_start(hbox
, expand
=False, fill
=True)
659 vp
.set_shadow_type(gtk
.SHADOW_NONE
)
661 sv
= gtk
.ScrolledWindow()
662 sv
.set_policy(gtk
.POLICY_AUTOMATIC
,gtk
.POLICY_AUTOMATIC
)
663 sv
.set_shadow_type(gtk
.SHADOW_NONE
)
666 win
.add_button(gtk
.STOCK_CANCEL
, gtk
.RESPONSE_CANCEL
)
667 win
.add_button(gtk
.STOCK_OK
, gtk
.RESPONSE_OK
)
671 if res
== gtk
.RESPONSE_OK
:
672 to_save
= map(lambda x
: (x
[0], x
[1].get_text()), entries_list
)
674 code
, val
= to_save
.pop()
675 rpc
.session
.rpc_exec_auth('/object', 'execute', model
,
676 'write_string', False, [code
], {name
: val
})
681 def callback_view(self
, widget
, event
, model
, src
, window
=None):
682 lang_ids
= rpc
.session
.rpc_exec_auth('/object', 'execute',
683 'res.lang', 'search', [('translatable', '=', '1')])
685 common
.message(_('No other language available!'),
688 langs
= rpc
.session
.rpc_exec_auth('/object', 'execute', 'res.lang',
689 'read', lang_ids
, ['code', 'name'])
691 win
= gtk
.Dialog(_('Add Translation'), window
,
692 gtk
.DIALOG_MODAL | gtk
.DIALOG_DESTROY_WITH_PARENT
)
693 win
.set_position(gtk
.WIN_POS_CENTER_ON_PARENT
)
694 win
.set_icon(common
.TINYERP_ICON
)
695 win
.vbox
.set_spacing(5)
696 vbox
= gtk
.VBox(spacing
=5)
701 view_item_ids
= rpc
.session
.rpc_exec_auth('/object', 'execute',
702 'ir.translation', 'search', [
703 ('name', '=', model
),
704 ('type', '=', 'view'),
707 view_items
= rpc
.session
.rpc_exec_auth('/object', 'execute',
708 'ir.translation', 'read', view_item_ids
,
710 label
= gtk
.Label(lang
['name'])
711 vbox
.pack_start(label
, expand
=False, fill
=True)
712 for val
in view_items
:
713 label
= gtk
.Label(val
['src'])
715 entry
.set_text(val
['value'])
716 entries_list
.append((val
['id'], entry
))
717 hbox
= gtk
.HBox(homogeneous
=True)
718 hbox
.pack_start(label
, expand
=False, fill
=False)
719 hbox
.pack_start(entry
, expand
=True, fill
=True)
720 vbox
.pack_start(hbox
, expand
=False, fill
=True)
722 vp
.set_shadow_type(gtk
.SHADOW_NONE
)
724 sv
= gtk
.ScrolledWindow()
725 sv
.set_policy(gtk
.POLICY_AUTOMATIC
,gtk
.POLICY_AUTOMATIC
)
726 sv
.set_shadow_type(gtk
.SHADOW_NONE
)
729 win
.add_button(gtk
.STOCK_CANCEL
, gtk
.RESPONSE_CANCEL
)
730 win
.add_button(gtk
.STOCK_OK
, gtk
.RESPONSE_OK
)
734 if res
== gtk
.RESPONSE_OK
:
735 to_save
= map(lambda x
: (x
[0], x
[1].get_text()), entries_list
)
737 id, val
= to_save
.pop()
738 rpc
.session
.rpc_exec_auth('/object', 'execute',
739 'ir.translation', 'write', [id], {'value': val
})
743 if event
.button
!= 3:
747 item
= gtk
.ImageMenuItem(_('Translate label'))
748 item
.connect("activate", callback_label
, widget
, event
, model
,
749 name
, src
, self
.window
)
750 item
.set_sensitive(1)
753 item
= gtk
.ImageMenuItem(_('Translate view'))
754 item
.connect("activate", callback_view
, widget
, event
, model
, src
,
756 item
.set_sensitive(1)
759 menu
.popup(None,None,None,event
.button
,event
.time
)
785 'date': (calendar
.calendar
, 1, False, False),
786 'time': (calendar
.stime
, 1, False, False),
787 'datetime': (calendar
.datetime
, 1, False, False),
788 'float': (spinbutton
.spinbutton
, 1, False, False),
789 'integer': (spinint
.spinint
, 1, False, False),
790 'selection': (selection
.selection
, 1, False, False),
791 'char': (char
.char
, 1, False, False),
792 'float_time': (float_time
.float_time
, 1, False, False),
793 'boolean': (checkbox
.checkbox
, 1, False, False),
794 'button': (button
.button
, 1, False, False),
795 'reference': (reference
.reference
, 1, False, False),
796 'binary': (binary
.wid_binary
, 1, False, False),
797 'picture': (picture
.wid_picture
, 1, False, False),
798 'text': (textbox
.textbox
, 1, True, True),
799 'text_tag': (textbox_tag
.textbox_tag
, 1, True, True),
800 'one2many': (one2many_list
.one2many_list
, 1, True, True),
801 'one2many_form': (one2many_list
.one2many_list
, 1, True, True),
802 'one2many_list': (one2many_list
.one2many_list
, 1, True, True),
803 'many2many': (many2many
.many2many
, 1, True, True),
804 'many2one': (many2one
.many2one
, 1, False, False),
805 'email' : (url
.email
, 1, False, False),
806 'url' : (url
.url
, 1, False, False),
807 'callto' : (url
.callto
, 1, False, False),
808 'sip' : (url
.sip
, 1, False, False),
809 'image' : (image
.image_wid
, 1, False, False),
810 'uri' : (url
.uri
, 1, False, False),
811 'progressbar' : (progressbar
.progressbar
, 1, False, False),
815 # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: