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 ##############################################################################
37 from common
import sur
41 from widget
.screen
import Screen
46 def __init__(self
, model_name
, parent
, model
=None, attrs
=None, model_ctx
=None,
47 window
=None, default_get_ctx
=None, readonly
=False):
53 if default_get_ctx
is None:
57 window
= service
.LocalService('gui.main').window
59 self
.dia
= gtk
.Dialog(_('OpenERP - Link'), window
,
60 gtk
.DIALOG_MODAL|gtk
.DIALOG_DESTROY_WITH_PARENT
)
62 if ('string' in attrs
) and attrs
['string']:
63 self
.dia
.set_title(self
.dia
.get_title() + ' - ' + attrs
['string'])
64 self
.dia
.set_property('default-width', 760)
65 self
.dia
.set_property('default-height', 500)
66 self
.dia
.set_position(gtk
.WIN_POS_CENTER_ON_PARENT
)
67 self
.dia
.set_icon(common
.OPENERP_ICON
)
69 self
.accel_group
= gtk
.AccelGroup()
70 self
.dia
.add_accel_group(self
.accel_group
)
72 self
.but_cancel
= self
.dia
.add_button(gtk
.STOCK_CANCEL
, gtk
.RESPONSE_CANCEL
)
73 self
.but_cancel
.add_accelerator('clicked', self
.accel_group
, gtk
.keysyms
.Escape
, gtk
.gdk
.CONTROL_MASK
, gtk
.ACCEL_VISIBLE
)
75 self
.but_ok
= self
.dia
.add_button(gtk
.STOCK_OK
, gtk
.RESPONSE_OK
)
76 self
.but_ok
.add_accelerator('clicked', self
.accel_group
, gtk
.keysyms
.Return
, gtk
.gdk
.CONTROL_MASK
, gtk
.ACCEL_VISIBLE
)
78 self
.default_get_ctx
= default_get_ctx
80 scroll
= gtk
.ScrolledWindow()
81 scroll
.set_policy(gtk
.POLICY_AUTOMATIC
, gtk
.POLICY_AUTOMATIC
)
82 scroll
.set_placement(gtk
.CORNER_TOP_LEFT
)
83 scroll
.set_shadow_type(gtk
.SHADOW_NONE
)
84 self
.dia
.vbox
.pack_start(scroll
, expand
=True, fill
=True)
87 vp
.set_shadow_type(gtk
.SHADOW_NONE
)
90 self
.screen
= Screen(model_name
, view_type
=[], parent
=parent
, window
=self
.dia
, readonly
=readonly
)
91 self
.screen
.models
._context
.update(model_ctx
)
93 model
= self
.screen
.new(context
=default_get_ctx
)
95 self
.screen
.models
.model_add(model
)
96 self
.screen
.current_model
= model
97 if ('views' in attrs
) and ('form' in attrs
['views']):
98 arch
= attrs
['views']['form']['arch']
99 fields
= attrs
['views']['form']['fields']
100 self
.screen
.add_view(arch
, fields
, display
=True,
101 context
=default_get_ctx
)
103 self
.screen
.add_view_id(False, 'form', display
=True,
104 context
=default_get_ctx
)
105 vp
.add(self
.screen
.widget
)
106 x
,y
= self
.screen
.screen_container
.size_get()
107 vp
.set_size_request(x
,y
+30)
109 self
.screen
.display()
112 model
= self
.screen
.new(context
=self
.default_get_ctx
)
113 self
.screen
.models
.model_add(model
)
114 self
.screen
.current_model
= model
117 def run(self
, datas
={}):
121 end
= (res
!= gtk
.RESPONSE_OK
) or self
.screen
.current_model
.validate()
123 self
.screen
.display()
125 if res
==gtk
.RESPONSE_OK
:
126 self
.screen
.current_view
.set_value()
127 model
= self
.screen
.current_model
129 return (False, False)
132 self
.screen
.signal_unconnect(self
)
133 self
.window
.present()
135 self
.screen
.destroy()
138 class one2many_list(interface
.widget_interface
):
139 def __init__(self
, window
, parent
, model
, attrs
={}):
140 interface
.widget_interface
.__init
__(self
, window
, parent
, model
, attrs
)
142 self
._readonly
= self
.default_readonly
143 self
.widget
= gtk
.VBox(homogeneous
=False, spacing
=5)
145 hb
= gtk
.HBox(homogeneous
=False, spacing
=5)
146 menubar
= gtk
.MenuBar()
147 if hasattr(menubar
, 'set_pack_direction') and \
148 hasattr(menubar
, 'set_child_pack_direction'):
149 menubar
.set_pack_direction(gtk
.PACK_DIRECTION_LTR
)
150 menubar
.set_child_pack_direction(gtk
.PACK_DIRECTION_LTR
)
152 menuitem_title
= gtk
.ImageMenuItem(stock_id
='gtk-preferences')
154 menu_title
= gtk
.Menu()
155 menuitem_set_to_default
= gtk
.MenuItem(_('Set to default value'), True)
156 menuitem_set_to_default
.connect('activate', lambda *x
:self
._menu
_sig
_default
_get
())
157 menu_title
.add(menuitem_set_to_default
)
158 menuitem_set_default
= gtk
.MenuItem(_('Set Default'), True)
159 menuitem_set_default
.connect('activate', lambda *x
: self
._menu
_sig
_default
_set
())
160 menu_title
.add(menuitem_set_default
)
161 menuitem_title
.set_submenu(menu_title
)
163 menubar
.add(menuitem_title
)
164 hb
.pack_start(menubar
, expand
=True, fill
=True)
166 tooltips
= gtk
.Tooltips()
168 self
.eb_new
= gtk
.EventBox()
169 tooltips
.set_tip(self
.eb_new
, _('Create a new entry'))
170 self
.eb_new
.set_events(gtk
.gdk
.BUTTON_PRESS
)
171 self
.eb_new
.connect('button_press_event', self
._sig
_new
)
172 img_new
= gtk
.Image()
173 img_new
.set_from_stock('gtk-new', gtk
.ICON_SIZE_MENU
)
174 img_new
.set_alignment(0.5, 0.5)
175 self
.eb_new
.add(img_new
)
176 hb
.pack_start(self
.eb_new
, expand
=False, fill
=False)
178 self
.eb_open
= gtk
.EventBox()
179 tooltips
.set_tip(self
.eb_open
, _('Edit this entry'))
180 self
.eb_open
.set_events(gtk
.gdk
.BUTTON_PRESS
)
181 self
.eb_open
.connect('button_press_event', self
._sig
_edit
)
182 img_open
= gtk
.Image()
183 img_open
.set_from_stock('gtk-open', gtk
.ICON_SIZE_MENU
)
184 img_open
.set_alignment(0.5, 0.5)
185 self
.eb_open
.add(img_open
)
186 hb
.pack_start(self
.eb_open
, expand
=False, fill
=False)
188 self
.eb_del
= gtk
.EventBox()
189 tooltips
.set_tip(self
.eb_del
, _('Remove this entry'))
190 self
.eb_del
.set_events(gtk
.gdk
.BUTTON_PRESS
)
191 self
.eb_del
.connect('button_press_event', self
._sig
_remove
)
192 img_del
= gtk
.Image()
193 img_del
.set_from_stock('gtk-delete', gtk
.ICON_SIZE_MENU
)
194 img_del
.set_alignment(0.5, 0.5)
195 self
.eb_del
.add(img_del
)
196 hb
.pack_start(self
.eb_del
, expand
=False, fill
=False)
198 hb
.pack_start(gtk
.VSeparator(), expand
=False, fill
=True)
200 eb_pre
= gtk
.EventBox()
201 tooltips
.set_tip(eb_pre
, _('Previous'))
202 eb_pre
.set_events(gtk
.gdk
.BUTTON_PRESS
)
203 eb_pre
.connect('button_press_event', self
._sig
_previous
)
204 img_pre
= gtk
.Image()
205 img_pre
.set_from_stock('gtk-go-back', gtk
.ICON_SIZE_MENU
)
206 img_pre
.set_alignment(0.5, 0.5)
208 hb
.pack_start(eb_pre
, expand
=False, fill
=False)
210 self
.label
= gtk
.Label('(0,0)')
211 hb
.pack_start(self
.label
, expand
=False, fill
=False)
213 eb_next
= gtk
.EventBox()
214 tooltips
.set_tip(eb_next
, _('Next'))
215 eb_next
.set_events(gtk
.gdk
.BUTTON_PRESS
)
216 eb_next
.connect('button_press_event', self
._sig
_next
)
217 img_next
= gtk
.Image()
218 img_next
.set_from_stock('gtk-go-forward', gtk
.ICON_SIZE_MENU
)
219 img_next
.set_alignment(0.5, 0.5)
220 eb_next
.add(img_next
)
221 hb
.pack_start(eb_next
, expand
=False, fill
=False)
223 hb
.pack_start(gtk
.VSeparator(), expand
=False, fill
=True)
225 eb_switch
= gtk
.EventBox()
226 tooltips
.set_tip(eb_switch
, _('Switch'))
227 eb_switch
.set_events(gtk
.gdk
.BUTTON_PRESS
)
228 eb_switch
.connect('button_press_event', self
.switch_view
)
229 img_switch
= gtk
.Image()
230 img_switch
.set_from_stock('gtk-justify-left', gtk
.ICON_SIZE_MENU
)
231 img_switch
.set_alignment(0.5, 0.5)
232 eb_switch
.add(img_switch
)
233 hb
.pack_start(eb_switch
, expand
=False, fill
=False)
236 self
.widget
.pack_start(hb
, expand
=False, fill
=True)
238 self
.screen
= Screen(attrs
['relation'], view_type
=attrs
.get('mode','tree,form').split(','), parent
=self
.parent
, views_preload
=attrs
.get('views', {}), tree_saves
=attrs
.get('saves', False), create_new
=True, row_activate
=self
._on
_activate
, default_get
=attrs
.get('default_get', {}), window
=self
._window
, readonly
=self
._readonly
)
239 self
.screen
.signal_connect(self
, 'record-message', self
._sig
_label
)
241 menuitem_title
.get_child().set_markup('<b>'+self
.screen
.current_view
.title
.replace('&','&').replace('<','<').replace('>','>')+'</b>')
243 self
.widget
.pack_start(self
.screen
.widget
, expand
=True, fill
=True)
245 self
.screen
.widget
.connect('key_press_event', self
.on_keypress
)
247 def on_keypress(self
, widget
, event
):
248 if (not self
._readonly
) and ((event
.keyval
== gtk
.keysyms
.N
and event
.state
& gtk
.gdk
.CONTROL_MASK\
249 and event
.state
& gtk
.gdk
.SHIFT_MASK
) or (event
.keyval
== gtk
.keysyms
.F1
)):
250 self
._sig
_new
(widget
, event
)
252 if event
.keyval
== gtk
.keysyms
.F2
:
253 self
._sig
_edit
(widget
, event
)
257 self
.screen
.destroy()
259 def _on_activate(self
, screen
, *args
):
262 def click_and_action(self
, type):
263 pos
= self
.tree_view
.pos_get()
265 val
= self
._value
[pos
]
266 id = val
.get('id', False)
267 obj
= service
.LocalService('action.main')
268 res
= obj
.exec_keyword(type, {'model':self
.model
, 'id': id or False, 'ids':[id], 'report_type': 'pdf'})
271 common
.message(_('You have to select a resource !'))
274 def switch_view(self
, btn
, arg
):
275 self
.screen
.switch_view()
277 def _readonly_set(self
, value
):
278 self
._readonly
= value
279 self
.eb_new
.set_sensitive(not value
)
280 self
.eb_del
.set_sensitive(not value
)
281 self
.screen
.readonly
= value
282 self
.screen
.display()
284 def _sig_new(self
, *args
):
286 ctx
= self
._view
.model
.expr_eval(self
.screen
.default_get
)
287 ctx
.update(self
._view
.model
.expr_eval('dict(%s)' % self
.attrs
.get('context', '')))
288 if event
.type in (gtk
.gdk
.BUTTON_PRESS
, gtk
.gdk
.KEY_PRESS
):
289 if (self
.screen
.current_view
.view_type
=='form') or self
.screen
.editable_get():
290 self
.screen
.new(context
=ctx
)
291 self
._readonly
= False
292 self
.screen
.current_view
.widget
.set_sensitive(True)
295 dia
= dialog(self
.attrs
['relation'], parent
=self
._view
.model
, attrs
=self
.attrs
, model_ctx
=self
.screen
.models
._context
, default_get_ctx
=ctx
, window
=self
._window
, readonly
=self
._readonly
)
297 ok
, value
= dia
.run()
299 self
.screen
.models
.model_add(value
)
300 value
.signal('record-changed', value
.parent
)
301 self
.screen
.display()
305 def _sig_edit(self
, *args
):
306 if self
.screen
.current_model
:
307 dia
= dialog(self
.attrs
['relation'], parent
=self
._view
.model
, model
=self
.screen
.current_model
, attrs
=self
.attrs
, window
=self
._window
, readonly
=self
._readonly
)
308 ok
, value
= dia
.run()
311 def _sig_next(self
, *args
):
313 if event
.type == gtk
.gdk
.BUTTON_PRESS
:
314 self
.screen
.display_next()
316 def _sig_previous(self
, *args
):
318 if event
.type == gtk
.gdk
.BUTTON_PRESS
:
319 self
.screen
.display_prev()
321 def _sig_remove(self
, *args
):
323 if event
.type == gtk
.gdk
.BUTTON_PRESS
:
324 if self
.screen
.current_view
.view_type
== 'form':
325 msg
= 'Are you sure to remove this record ?'
327 msg
= 'Are you sure to remove these records ?'
330 if not self
.screen
.models
.models
:
331 self
.screen
.current_view
.widget
.set_sensitive(False)
333 def _sig_label(self
, screen
, signal_data
):
335 if signal_data
[0] >= 0:
336 name
= str(signal_data
[0] + 1)
337 line
= '(%s/%s)' % (name
, signal_data
[1])
338 self
.label
.set_text(line
)
340 def _sig_refresh(self
, *args
):
343 def _sig_sequence(self
, *args
):
346 def display(self
, model
, model_field
):
348 self
.screen
.current_model
= None
349 self
.screen
.display()
351 super(one2many_list
, self
).display(model
, model_field
)
352 new_models
= model_field
.get_client(model
)
353 if self
.screen
.models
!= new_models
:
354 self
.screen
.models_set(new_models
)
355 if (self
.screen
.current_view
.view_type
=='tree') and self
.screen
.editable_get():
356 self
.screen
.current_model
= None
357 self
.screen
.display()
359 self
.screen
.display()
362 def set_value(self
, model
, model_field
):
363 self
.screen
.current_view
.set_value()
364 if self
.screen
.is_modified():
365 model
.modified
= True
366 model
.modified_fields
.setdefault(model_field
.name
)
369 # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: